Commit 4c1f4c8f by Harish Butani

refactor: introduce concepts for ConstructableType, HierarchicalType, IInstance,…

refactor: introduce concepts for ConstructableType, HierarchicalType, IInstance, ITypedInstance etc.
parent 7a33946d
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.metadata;
/**
* Represents a Struct or Trait or Object.
*/
public interface IInstance {
String getTypeName();
Object get(String attrName) throws MetadataException;
void set(String attrName, Object val) throws MetadataException;
}
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.metadata;
import com.google.common.collect.ImmutableList;
import org.apache.metadata.storage.Id;
/**
* Represents and instance of a ClassType. These have identity.
* Transient instances will have a UNASSIGNED identity.
*/
public interface IReferencableInstance extends IStruct {
ImmutableList<String> getTraits();
Id getId();
IStruct getTrait(String typeName);
}
......@@ -18,9 +18,9 @@
package org.apache.metadata;
public interface IStruct {
/**
* A marker interface for StructType and TraitType instances.
*/
public interface IStruct extends IInstance {
String getTypeName();
Object get(String attrName) throws MetadataException;
void set(String attrName, Object val) throws MetadataException;
}
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.metadata;
import org.apache.metadata.types.FieldMapping;
/**
* An instance whose structure is associated with a IDataType.
* This is obtained by a call to 'createInstance' or the result of a Query.
* A ITypedInstance can only contain information on attributes of the associated Type.
* Instance can still be invalid because of missing required fields or incorrect multiplicity.
* But user can only get/set on a known field of the associated type. Type values have to match
* the IDataType of the associated attribute.
*/
public interface ITypedInstance extends IInstance {
FieldMapping fieldMapping();
}
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.metadata;
public interface ITypedReferencableInstance extends ITypedInstance, IReferencableInstance {
}
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.metadata;
public interface ITypedStruct extends IStruct, ITypedInstance {
}
......@@ -24,14 +24,16 @@ public class Id {
public final int id;
public final String className;
public final int version;
public Id(int id, String className) {
public Id(int id, int version, String className) {
this.id = id;
this.className = className;
this.version = version;
}
public Id(String className) {
this(UNASSIGNED, className);
this(UNASSIGNED, 0, className);
}
public boolean isUnassigned() {
......
......@@ -20,6 +20,7 @@ package org.apache.metadata.storage;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.apache.metadata.IStruct;
import org.apache.metadata.ITypedStruct;
import org.apache.metadata.MetadataException;
import org.apache.metadata.types.AttributeInfo;
import org.apache.metadata.types.FieldMapping;
......@@ -30,7 +31,7 @@ import java.math.BigInteger;
import java.util.Date;
import java.util.Map;
public class StructInstance implements IStruct {
public class StructInstance implements ITypedStruct {
public final String dataTypeName;
public final FieldMapping fieldMapping;
public final boolean nullFlags[];
......@@ -84,6 +85,11 @@ public class StructInstance implements IStruct {
}
@Override
public FieldMapping fieldMapping() {
return fieldMapping;
}
@Override
public Object get(String attrName) throws MetadataException {
return fieldMapping.get(this, attrName);
}
......
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.metadata.types;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.apache.metadata.IStruct;
import org.apache.metadata.MetadataException;
import org.apache.metadata.storage.DownCastStructInstance;
import java.util.*;
/**
* Represents a Type that can have SuperTypes. An Instance of the HierarchicalType can be downcast to a SuperType.
* @param <ST> the Type of the SuperType. TraitTypes have TraitTypes as SuperTypes, ClassTypes have ClassTypes
* as SuperTypes.
* @param <T> the class of the Instance of this DataType.
*/
public abstract class HierarchicalType<ST extends HierarchicalType,T> extends AbstractDataType<T>
implements Comparable<ST> {
public final ITypeBrowser typeSystem;
public final String name;
public final FieldMapping fieldMapping;
public final int numFields;
public final ImmutableList<String> superTypes;
protected final ImmutableList<AttributeInfo> immediateAttrs;
protected ImmutableMap<String, List<Path>> superTypePaths;
protected ImmutableMap<String, Path> pathNameToPathMap;
/**
* Used when creating a Type, to support recursive Structs.
*/
HierarchicalType(ITypeBrowser typeSystem, String name, ImmutableList<String> superTypes, int numFields) {
this.typeSystem = typeSystem;
this.name = name;
this.fieldMapping = null;
this.numFields = numFields;
this.superTypes = superTypes;
this.immediateAttrs = null;
}
HierarchicalType(ITypeBrowser typeSystem, String name, ImmutableList<String> superTypes, AttributeInfo... fields)
throws MetadataException {
this.typeSystem = typeSystem;
this.name = name;
this.fieldMapping = constructFieldMapping(superTypes,
fields);
this.numFields = this.fieldMapping.fields.size();
this.superTypes = superTypes == null ? ImmutableList.<String>of() : superTypes;
this.immediateAttrs = ImmutableList.<AttributeInfo>copyOf(fields);
}
protected FieldMapping constructFieldMapping(ImmutableList<String> superTraits,
AttributeInfo... fields)
throws MetadataException {
Map<String,AttributeInfo> fieldsMap = new LinkedHashMap<String, AttributeInfo>();
Map<String, Integer> fieldPos = new HashMap<String, Integer>();
Map<String, Integer> fieldNullPos = new HashMap<String, Integer>();
int numBools = 0;
int numBytes = 0;
int numShorts = 0;
int numInts = 0;
int numLongs = 0;
int numFloats = 0;
int numDoubles = 0;
int numBigInts = 0;
int numBigDecimals = 0;
int numDates = 0;
int numStrings = 0;
int numArrays = 0;
int numMaps = 0;
int numStructs = 0;
Map<String, List<Path>> superTypePaths = new HashMap<String, List<Path>>();
Map<String, Path> pathNameToPathMap = new HashMap<String, Path>();
Queue<Path> queue = new LinkedList<Path>();
queue.add(new Node(getName()));
while(!queue.isEmpty()) {
Path currentPath = queue.poll();
ST superType = currentPath.typeName == getName() ? (ST) this :
(ST) typeSystem.dataType(currentPath.typeName);
pathNameToPathMap.put(currentPath.pathName, currentPath);
if ( superType != this ) {
List<Path> typePaths = superTypePaths.get(superType.getName());
if ( typePaths == null ) {
typePaths = new ArrayList<Path>();
superTypePaths.put(superType.getName(), typePaths);
}
typePaths.add(currentPath);
}
ImmutableList<AttributeInfo> superTypeFields = superType == this ?
ImmutableList.<AttributeInfo>copyOf(fields) : superType.immediateAttrs;
Set<String> immediateFields = new HashSet<String>();
for(AttributeInfo i : superTypeFields) {
if ( superType == this && immediateFields.contains(i.name) ) {
throw new MetadataException(
String.format("Struct defintion cannot contain multiple fields with the same name %s",
i.name));
}
String attrName = i.name;
if ( fieldsMap.containsKey(attrName)) {
attrName = currentPath.addOverrideAttr(attrName);
}
fieldsMap.put(attrName, i);
fieldNullPos.put(attrName, fieldNullPos.size());
if ( i.dataType() == DataTypes.BOOLEAN_TYPE ) {
fieldPos.put(attrName, numBools);
numBools++;
} else if ( i.dataType() == DataTypes.BYTE_TYPE ) {
fieldPos.put(attrName, numBytes);
numBytes++;
} else if ( i.dataType() == DataTypes.SHORT_TYPE ) {
fieldPos.put(attrName, numShorts);
numShorts++;
} else if ( i.dataType() == DataTypes.INT_TYPE ) {
fieldPos.put(attrName, numInts);
numInts++;
} else if ( i.dataType() == DataTypes.LONG_TYPE ) {
fieldPos.put(attrName, numLongs);
numLongs++;
} else if ( i.dataType() == DataTypes.FLOAT_TYPE ) {
fieldPos.put(attrName, numFloats);
numFloats++;
} else if ( i.dataType() == DataTypes.DOUBLE_TYPE ) {
fieldPos.put(attrName, numDoubles);
numDoubles++;
} else if ( i.dataType() == DataTypes.BIGINTEGER_TYPE ) {
fieldPos.put(attrName, numBigInts);
numBigInts++;
} else if ( i.dataType() == DataTypes.BIGDECIMAL_TYPE ) {
fieldPos.put(attrName, numBigDecimals);
numBigDecimals++;
} else if ( i.dataType() == DataTypes.DATE_TYPE ) {
fieldPos.put(attrName, numDates);
numDates++;
} else if ( i.dataType() == DataTypes.STRING_TYPE ) {
fieldPos.put(attrName, numStrings);
numStrings++;
} else if ( i.dataType().getTypeCategory() == DataTypes.TypeCategory.ARRAY ) {
fieldPos.put(attrName, numArrays);
numArrays++;
} else if ( i.dataType().getTypeCategory() == DataTypes.TypeCategory.MAP ) {
fieldPos.put(attrName, numMaps);
numMaps++;
} else if ( i.dataType().getTypeCategory() == DataTypes.TypeCategory.STRUCT ) {
fieldPos.put(attrName, numStructs);
numStructs++;
} else {
throw new MetadataException(String.format("Unknown datatype %s", i.dataType()));
}
}
ImmutableList<String> sTs = superType == this ? superTraits : superType.superTypes;
for(String sT : sTs) {
queue.add(new Path(sT, currentPath));
}
}
this.superTypePaths = ImmutableMap.copyOf(superTypePaths);
this.pathNameToPathMap = ImmutableMap.copyOf(pathNameToPathMap);
return new FieldMapping(fieldsMap,
fieldPos,
fieldNullPos,
numBools,
numBytes,
numShorts,
numInts,
numLongs,
numFloats,
numDoubles,
numBigInts,
numBigDecimals,
numDates,
numStrings,
numArrays,
numMaps,
numStructs);
}
public IStruct castAs(IStruct s, String superTypeName) throws MetadataException {
if ( !superTypePaths.containsKey(superTypeName) ) {
throw new MetadataException(String.format("Cannot downcast to %s from type %s", superTypeName, getName()));
}
if (s != null) {
if (s.getTypeName() != getName()) {
throw new MetadataException(
String.format("Downcast called on wrong type %s, instance type is %s",
getName(), s.getTypeName()));
}
List<Path> pathToSuper = superTypePaths.get(superTypeName);
if ( pathToSuper.size() > 1 ) {
throw new MetadataException(
String.format("Cannot downcast called to %s, from %s: there are multiple paths to SuperType",
superTypeName, getName()));
}
ST superType = (ST) typeSystem.dataType(superTypeName);
Map<String, String> downCastMap = superType.constructDowncastFieldMap(this, pathToSuper.get(0));
return new DownCastStructInstance(superTypeName,
new DownCastFieldMapping(ImmutableMap.copyOf(downCastMap)),
s);
}
return null;
}
protected Map<String, String> constructDowncastFieldMap(ST subType, Path pathToSubType) {
String pathToSubTypeName = pathToSubType.pathAfterThis;
/*
* the downcastMap;
*/
Map<String, String> dCMap = new HashMap<String, String>();
Iterator<Path> itr = pathIterator();
while(itr.hasNext()) {
Path p = itr.next();
Path pInSubType = (Path) subType.pathNameToPathMap.get(p.pathName + "." + pathToSubTypeName);
if ( pInSubType.hiddenAttributeMap != null ) {
for(Map.Entry<String, String> e : pInSubType.hiddenAttributeMap.entrySet()) {
String mappedInThisType =
p.hiddenAttributeMap != null ? p.hiddenAttributeMap.get(e.getKey()) : null;
if ( mappedInThisType == null ) {
dCMap.put(e.getKey(), e.getValue());
} else {
dCMap.put(mappedInThisType, e.getValue());
}
}
}
}
return dCMap;
}
@Override
public int compareTo(ST o) {
String oName = o.getName();
if ( superTypes.contains(oName) ) {
return 1;
} else if ( o.superTypes.contains(getName())) {
return -1;
} else {
return getName().compareTo(oName);
}
}
public Iterator<Path> pathIterator() {
return new PathItr();
}
class PathItr implements Iterator<Path> {
Queue<Path> pathQueue;
PathItr() {
pathQueue = new LinkedList<Path>();
pathQueue.add(pathNameToPathMap.get(getName()));
}
@Override
public boolean hasNext() {
return !pathQueue.isEmpty();
}
@Override
public Path next() {
Path p = pathQueue.poll();
ST t = (ST) typeSystem.dataType(p.typeName);
if ( t.superTypes != null ) {
ImmutableList<String> sTs = t.superTypes;
for(String sT : sTs) {
String nm = sT + "." + p.pathName;
pathQueue.add(pathNameToPathMap.get(nm));
}
}
return p;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
static class Path {
public final String typeName;
private final Path subTypePath;
public final String pathName;
public final String pathAfterThis;
/*
* name mapping for attributes hidden by a SubType.
*/
Map<String, String> hiddenAttributeMap;
Path(String typeName, Path childPath) throws MetadataException {
this.typeName = typeName;
this.subTypePath = childPath;
if ( childPath.contains(typeName) ) {
throw new CyclicTypeDefinition(this);
}
pathName = String.format("%s.%s", typeName, childPath.pathName);
pathAfterThis = childPath.pathName;
}
Path(String typeName) {
assert getClass() == Node.class;
this.typeName = typeName;
this.subTypePath = null;
pathName = typeName;
pathAfterThis = null;
}
public boolean contains(String typeName) {
return this.typeName.equals(typeName) || (subTypePath != null && subTypePath.contains(typeName));
}
public String pathString(String nodeSep) {
StringBuilder b = new StringBuilder();
Path p = this;
while ( p != null ) {
b.append(p.typeName);
p = p.subTypePath;
if ( p != null ) {
b.append(nodeSep);
}
}
return b.toString();
}
String addOverrideAttr(String name) {
hiddenAttributeMap = hiddenAttributeMap == null ? new HashMap<String, String>() : hiddenAttributeMap;
String oName = pathName + "." + name;
hiddenAttributeMap.put(name, oName);
return oName;
}
}
static class Node extends Path {
Node(String typeName) {
super(typeName);
}
}
static class CyclicTypeDefinition extends MetadataException {
CyclicTypeDefinition(Path p) {
super(String.format("Cycle in Type Definition %s", p.pathString(" -> ")));
}
}
}
package org.apache.metadata.types;
import org.apache.metadata.ITypedInstance;
public interface IConstructableType<U, T extends ITypedInstance> extends IDataType<U> {
T createInstance();
FieldMapping fieldMapping();
}
......@@ -20,6 +20,7 @@ package org.apache.metadata.types;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.apache.metadata.IStruct;
import org.apache.metadata.ITypedStruct;
import org.apache.metadata.MetadataException;
import org.apache.metadata.Struct;
import org.apache.metadata.storage.StructInstance;
......@@ -28,12 +29,14 @@ import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
public class StructType extends AbstractDataType<IStruct> {
public class StructType extends AbstractDataType<IStruct>
implements IConstructableType<IStruct, ITypedStruct> {
public final ITypeBrowser typeSystem;
public final String name;
public final FieldMapping fieldMapping;
public final int numFields;
private final TypedStructHandler handler;
/**
* Used when creating a StructType, to support recursive Structs.
......@@ -43,6 +46,7 @@ public class StructType extends AbstractDataType<IStruct> {
this.name = name;
this.fieldMapping = null;
this.numFields = numFields;
this.handler = null;
}
protected StructType(ITypeBrowser typeSystem, String name,
......@@ -52,6 +56,11 @@ public class StructType extends AbstractDataType<IStruct> {
this.fieldMapping = constructFieldMapping(superTypes,
fields);
this.numFields = this.fieldMapping.fields.size();
this.handler = new TypedStructHandler(this);
}
public FieldMapping fieldMapping() {
return fieldMapping;
}
@Override
......@@ -156,77 +165,21 @@ public class StructType extends AbstractDataType<IStruct> {
@Override
public StructInstance convert(Object val, Multiplicity m) throws MetadataException {
if ( val != null ) {
if ( val instanceof Struct ) {
Struct s = (Struct) val;
if ( s.typeName != name ) {
throw new ValueConversionException(this, val);
}
StructInstance ts = createInstance();
for(Map.Entry<String,AttributeInfo> e : fieldMapping.fields.entrySet() ) {
String attrKey = e.getKey();
AttributeInfo i = e.getValue();
Object aVal = s.get(attrKey);
try {
ts.set(attrKey, aVal);
} catch(ValueConversionException ve) {
throw new ValueConversionException(this, val, ve);
}
}
return ts;
} else if ( val instanceof StructInstance && ((StructInstance)val).getTypeName() == getName() ) {
return (StructInstance) val;
} else {
throw new ValueConversionException(this, val);
}
}
if (!m.nullAllowed() ) {
throw new ValueConversionException.NullConversionException(m);
}
return null;
public DataTypes.TypeCategory getTypeCategory() {
return DataTypes.TypeCategory.STRUCT;
}
@Override
public DataTypes.TypeCategory getTypeCategory() {
return DataTypes.TypeCategory.STRUCT;
public ITypedStruct convert(Object val, Multiplicity m) throws MetadataException {
return handler.convert(val, m);
}
public StructInstance createInstance() {
return new StructInstance(getName(),
fieldMapping,
new boolean[fieldMapping.fields.size()],
fieldMapping.numBools == 0 ? null : new boolean[fieldMapping.numBools],
fieldMapping.numBytes == 0 ? null : new byte[fieldMapping.numBytes],
fieldMapping.numShorts == 0 ? null : new short[fieldMapping.numShorts],
fieldMapping.numInts == 0 ? null : new int[fieldMapping.numInts],
fieldMapping.numLongs == 0 ? null : new long[fieldMapping.numLongs],
fieldMapping.numFloats == 0 ? null : new float[fieldMapping.numFloats],
fieldMapping.numDoubles == 0 ? null : new double[fieldMapping.numDoubles],
fieldMapping.numBigDecimals == 0 ? null : new BigDecimal[fieldMapping.numBigDecimals],
fieldMapping.numBigInts == 0 ? null : new BigInteger[fieldMapping.numBigInts],
fieldMapping.numDates == 0 ? null : new Date[fieldMapping.numDates],
fieldMapping.numStrings == 0 ? null : new String[fieldMapping.numStrings],
fieldMapping.numArrays == 0 ? null : new ImmutableList[fieldMapping.numArrays],
fieldMapping.numMaps == 0 ? null : new ImmutableMap[fieldMapping.numMaps],
fieldMapping.numStructs == 0 ? null : new StructInstance[fieldMapping.numStructs]);
public ITypedStruct createInstance() {
return handler.createInstance();
}
@Override
public void output(IStruct s, Appendable buf, String prefix) throws MetadataException {
TypeUtils.outputVal("{", buf, prefix);
if ( s == null ) {
TypeUtils.outputVal("<null>\n", buf, "");
return;
}
TypeUtils.outputVal("\n", buf, "");
String fieldPrefix = prefix + "\t";
for(AttributeInfo i : fieldMapping.fields.values()) {
Object aVal = s.get(i.name);
TypeUtils.outputVal(i.name + " : ", buf, fieldPrefix);
i.dataType().output(aVal, buf, "");
TypeUtils.outputVal("\n", buf, "");
}
TypeUtils.outputVal("\n}\n", buf, "");
handler.output(s, buf, prefix);
}
}
......@@ -18,38 +18,28 @@
package org.apache.metadata.types;
import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.apache.metadata.IStruct;
import org.apache.metadata.ITypedStruct;
import org.apache.metadata.MetadataException;
import org.apache.metadata.Struct;
import org.apache.metadata.storage.DownCastStructInstance;
import org.apache.metadata.storage.StructInstance;
import java.util.*;
public class TraitType extends HierarchicalType<TraitType, IStruct>
implements IConstructableType<IStruct, ITypedStruct> {
public class TraitType extends StructType implements Comparable<TraitType> {
public final ImmutableList<String> superTraits;
protected final ImmutableList<AttributeInfo> immediateAttrs;
protected ImmutableMap<String, List<Path>> superTypePaths;
protected ImmutableMap<String, Path> pathNameToPathMap;
private final TypedStructHandler handler;
/**
* Used when creating a TraitType, to support recursive Structs.
*/
TraitType(ITypeBrowser typeSystem, String name, ImmutableList<String> superTraits, int numFields) {
super(typeSystem, name, numFields);
this.superTraits = superTraits;
this.immediateAttrs = null;
super(typeSystem, name, superTraits, numFields);
handler = null;
}
TraitType(ITypeBrowser typeSystem, String name, ImmutableList<String> superTraits, AttributeInfo... fields)
throws MetadataException {
super(typeSystem, name, superTraits, fields);
this.superTraits = superTraits == null ? ImmutableList.<String>of() : superTraits;
this.immediateAttrs = ImmutableList.<AttributeInfo>copyOf(fields);
handler = new TypedStructHandler(this);
}
@Override
......@@ -57,139 +47,8 @@ public class TraitType extends StructType implements Comparable<TraitType> {
return name;
}
@Override
protected FieldMapping constructFieldMapping(ImmutableList<String> superTraits,
AttributeInfo... fields)
throws MetadataException {
Map<String,AttributeInfo> fieldsMap = new LinkedHashMap<String, AttributeInfo>();
Map<String, Integer> fieldPos = new HashMap<String, Integer>();
Map<String, Integer> fieldNullPos = new HashMap<String, Integer>();
int numBools = 0;
int numBytes = 0;
int numShorts = 0;
int numInts = 0;
int numLongs = 0;
int numFloats = 0;
int numDoubles = 0;
int numBigInts = 0;
int numBigDecimals = 0;
int numDates = 0;
int numStrings = 0;
int numArrays = 0;
int numMaps = 0;
int numStructs = 0;
Map<String, List<Path>> superTypePaths = new HashMap<String, List<Path>>();
Map<String, Path> pathNameToPathMap = new HashMap<String, Path>();
Queue<Path> queue = new LinkedList<Path>();
queue.add(new Node(getName()));
while(!queue.isEmpty()) {
Path currentPath = queue.poll();
TraitType superType = currentPath.typeName == getName() ? this :
(TraitType) typeSystem.dataType(currentPath.typeName);
pathNameToPathMap.put(currentPath.pathName, currentPath);
if ( superType != this ) {
List<Path> typePaths = superTypePaths.get(superType.getName());
if ( typePaths == null ) {
typePaths = new ArrayList<Path>();
superTypePaths.put(superType.getName(), typePaths);
}
typePaths.add(currentPath);
}
ImmutableList<AttributeInfo> superTypeFields = superType == this ?
ImmutableList.<AttributeInfo>copyOf(fields) : superType.immediateAttrs;
Set<String> immediateFields = new HashSet<String>();
for(AttributeInfo i : superTypeFields) {
if ( superType == this && immediateFields.contains(i.name) ) {
throw new MetadataException(
String.format("Struct defintion cannot contain multiple fields with the same name %s",
i.name));
}
String attrName = i.name;
if ( fieldsMap.containsKey(attrName)) {
attrName = currentPath.addOverrideAttr(attrName);
}
fieldsMap.put(attrName, i);
fieldNullPos.put(attrName, fieldNullPos.size());
if ( i.dataType() == DataTypes.BOOLEAN_TYPE ) {
fieldPos.put(attrName, numBools);
numBools++;
} else if ( i.dataType() == DataTypes.BYTE_TYPE ) {
fieldPos.put(attrName, numBytes);
numBytes++;
} else if ( i.dataType() == DataTypes.SHORT_TYPE ) {
fieldPos.put(attrName, numShorts);
numShorts++;
} else if ( i.dataType() == DataTypes.INT_TYPE ) {
fieldPos.put(attrName, numInts);
numInts++;
} else if ( i.dataType() == DataTypes.LONG_TYPE ) {
fieldPos.put(attrName, numLongs);
numLongs++;
} else if ( i.dataType() == DataTypes.FLOAT_TYPE ) {
fieldPos.put(attrName, numFloats);
numFloats++;
} else if ( i.dataType() == DataTypes.DOUBLE_TYPE ) {
fieldPos.put(attrName, numDoubles);
numDoubles++;
} else if ( i.dataType() == DataTypes.BIGINTEGER_TYPE ) {
fieldPos.put(attrName, numBigInts);
numBigInts++;
} else if ( i.dataType() == DataTypes.BIGDECIMAL_TYPE ) {
fieldPos.put(attrName, numBigDecimals);
numBigDecimals++;
} else if ( i.dataType() == DataTypes.DATE_TYPE ) {
fieldPos.put(attrName, numDates);
numDates++;
} else if ( i.dataType() == DataTypes.STRING_TYPE ) {
fieldPos.put(attrName, numStrings);
numStrings++;
} else if ( i.dataType().getTypeCategory() == DataTypes.TypeCategory.ARRAY ) {
fieldPos.put(attrName, numArrays);
numArrays++;
} else if ( i.dataType().getTypeCategory() == DataTypes.TypeCategory.MAP ) {
fieldPos.put(attrName, numMaps);
numMaps++;
} else if ( i.dataType().getTypeCategory() == DataTypes.TypeCategory.STRUCT ) {
fieldPos.put(attrName, numStructs);
numStructs++;
} else {
throw new MetadataException(String.format("Unknown datatype %s", i.dataType()));
}
}
for(String sT : superType == this ? superTraits : superType.superTraits) {
queue.add(new Path(sT, currentPath));
}
}
this.superTypePaths = ImmutableMap.copyOf(superTypePaths);
this.pathNameToPathMap = ImmutableMap.copyOf(pathNameToPathMap);
return new FieldMapping(fieldsMap,
fieldPos,
fieldNullPos,
numBools,
numBytes,
numShorts,
numInts,
numLongs,
numFloats,
numDoubles,
numBigInts,
numBigDecimals,
numDates,
numStrings,
numArrays,
numMaps,
numStructs);
public FieldMapping fieldMapping() {
return fieldMapping;
}
@Override
......@@ -197,177 +56,18 @@ public class TraitType extends StructType implements Comparable<TraitType> {
return DataTypes.TypeCategory.TRAIT;
}
protected Map<String, String> constructDowncastFieldMap(TraitType subType, Path pathToSubType) {
String pathToSubTypeName = pathToSubType.pathAfterThis;
/*
* the downcastMap;
*/
Map<String, String> dCMap = new HashMap<String, String>();
Iterator<Path> itr = pathIterator();
while(itr.hasNext()) {
Path p = itr.next();
Path pInSubType = subType.pathNameToPathMap.get(p.pathName + "." + pathToSubTypeName);
if ( pInSubType.hiddenAttributeMap != null ) {
for(Map.Entry<String, String> e : pInSubType.hiddenAttributeMap.entrySet()) {
String mappedInThisType =
p.hiddenAttributeMap != null ? p.hiddenAttributeMap.get(e.getKey()) : null;
if ( mappedInThisType == null ) {
dCMap.put(e.getKey(), e.getValue());
} else {
dCMap.put(mappedInThisType, e.getValue());
}
}
}
}
return dCMap;
}
public IStruct castAs(IStruct s, String superTypeName) throws MetadataException {
if ( !superTypePaths.containsKey(superTypeName) ) {
throw new MetadataException(String.format("Cannot downcast to %s from type %s", superTypeName, getName()));
}
if (s != null) {
if (s.getTypeName() != getName()) {
throw new MetadataException(
String.format("Downcast called on wrong type %s, instance type is %s",
getName(), s.getTypeName()));
}
List<Path> pathToSuper = superTypePaths.get(superTypeName);
if ( pathToSuper.size() > 1 ) {
throw new MetadataException(
String.format("Cannot downcast called to %s, from %s: there are multiple paths to SuperType",
superTypeName, getName()));
}
TraitType superType = (TraitType) typeSystem.dataType(superTypeName);
Map<String, String> downCastMap = superType.constructDowncastFieldMap(this, pathToSuper.get(0));
return new DownCastStructInstance(superTypeName,
new DownCastFieldMapping(ImmutableMap.copyOf(downCastMap)),
s);
}
return null;
}
public Iterator<Path> pathIterator() {
return new PathItr();
}
@Override
public int compareTo(TraitType o) {
String oName = o.getName();
if ( superTraits.contains(oName) ) {
return 1;
} else if ( o.superTraits.contains(getName())) {
return -1;
} else {
return getName().compareTo(oName);
}
public ITypedStruct convert(Object val, Multiplicity m) throws MetadataException {
return handler.convert(val, m);
}
class PathItr implements Iterator<Path> {
Queue<Path> pathQueue;
PathItr() {
pathQueue = new LinkedList<Path>();
pathQueue.add(pathNameToPathMap.get(getName()));
}
@Override
public boolean hasNext() {
return !pathQueue.isEmpty();
}
@Override
public Path next() {
Path p = pathQueue.poll();
TraitType t = (TraitType) typeSystem.dataType(p.typeName);
if ( t.superTraits != null ) {
for(String sT : t.superTraits) {
String nm = sT + "." + p.pathName;
pathQueue.add(pathNameToPathMap.get(nm));
}
}
return p;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
public ITypedStruct createInstance() {
return handler.createInstance();
}
static class Path {
public final String typeName;
private final Path subTypePath;
public final String pathName;
public final String pathAfterThis;
/*
* name mapping for attributes hidden by a SubType.
*/
Map<String, String> hiddenAttributeMap;
Path(String typeName, Path childPath) throws MetadataException {
this.typeName = typeName;
this.subTypePath = childPath;
if ( childPath.contains(typeName) ) {
throw new CyclicTypeDefinition(this);
}
pathName = String.format("%s.%s", typeName, childPath.pathName);
pathAfterThis = childPath.pathName;
}
Path(String typeName) {
assert getClass() == Node.class;
this.typeName = typeName;
this.subTypePath = null;
pathName = typeName;
pathAfterThis = null;
}
public boolean contains(String typeName) {
return this.typeName.equals(typeName) || (subTypePath != null && subTypePath.contains(typeName));
}
public String pathString(String nodeSep) {
StringBuilder b = new StringBuilder();
Path p = this;
while ( p != null ) {
b.append(p.typeName);
p = p.subTypePath;
if ( p != null ) {
b.append(nodeSep);
}
}
return b.toString();
}
String addOverrideAttr(String name) {
hiddenAttributeMap = hiddenAttributeMap == null ? new HashMap<String, String>() : hiddenAttributeMap;
String oName = pathName + "." + name;
hiddenAttributeMap.put(name, oName);
return oName;
}
}
static class Node extends Path {
Node(String typeName) {
super(typeName);
}
@Override
public void output(IStruct s, Appendable buf, String prefix) throws MetadataException {
handler.output(s, buf, prefix);
}
static class CyclicTypeDefinition extends MetadataException {
CyclicTypeDefinition(Path p) {
super(String.format("Cycle in Type Definition %s", p.pathString(" -> ")));
}
}
}
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.metadata.types;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.apache.metadata.IStruct;
import org.apache.metadata.ITypedStruct;
import org.apache.metadata.MetadataException;
import org.apache.metadata.Struct;
import org.apache.metadata.storage.StructInstance;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.Map;
public class TypedStructHandler {
private final IConstructableType<IStruct, ITypedStruct> structType;
private final FieldMapping fieldMapping;
public TypedStructHandler(IConstructableType<IStruct, ITypedStruct> structType) {
this.structType = structType;
fieldMapping = structType.fieldMapping();
}
public ITypedStruct convert(Object val, Multiplicity m) throws MetadataException {
if ( val != null ) {
if ( val instanceof Struct) {
Struct s = (Struct) val;
if ( s.typeName != structType.getName() ) {
throw new ValueConversionException(structType, val);
}
ITypedStruct ts = createInstance();
for(Map.Entry<String,AttributeInfo> e : fieldMapping.fields.entrySet() ) {
String attrKey = e.getKey();
AttributeInfo i = e.getValue();
Object aVal = s.get(attrKey);
try {
ts.set(attrKey, aVal);
} catch(ValueConversionException ve) {
throw new ValueConversionException(structType, val, ve);
}
}
return ts;
} else if ( val instanceof StructInstance && ((StructInstance)val).getTypeName() == structType.getName() ) {
return (StructInstance) val;
} else {
throw new ValueConversionException(structType, val);
}
}
if (!m.nullAllowed() ) {
throw new ValueConversionException.NullConversionException(m);
}
return null;
}
public DataTypes.TypeCategory getTypeCategory() {
return DataTypes.TypeCategory.STRUCT;
}
public ITypedStruct createInstance() {
return new StructInstance(structType.getName(),
fieldMapping,
new boolean[fieldMapping.fields.size()],
fieldMapping.numBools == 0 ? null : new boolean[fieldMapping.numBools],
fieldMapping.numBytes == 0 ? null : new byte[fieldMapping.numBytes],
fieldMapping.numShorts == 0 ? null : new short[fieldMapping.numShorts],
fieldMapping.numInts == 0 ? null : new int[fieldMapping.numInts],
fieldMapping.numLongs == 0 ? null : new long[fieldMapping.numLongs],
fieldMapping.numFloats == 0 ? null : new float[fieldMapping.numFloats],
fieldMapping.numDoubles == 0 ? null : new double[fieldMapping.numDoubles],
fieldMapping.numBigDecimals == 0 ? null : new BigDecimal[fieldMapping.numBigDecimals],
fieldMapping.numBigInts == 0 ? null : new BigInteger[fieldMapping.numBigInts],
fieldMapping.numDates == 0 ? null : new Date[fieldMapping.numDates],
fieldMapping.numStrings == 0 ? null : new String[fieldMapping.numStrings],
fieldMapping.numArrays == 0 ? null : new ImmutableList[fieldMapping.numArrays],
fieldMapping.numMaps == 0 ? null : new ImmutableMap[fieldMapping.numMaps],
fieldMapping.numStructs == 0 ? null : new StructInstance[fieldMapping.numStructs]);
}
public void output(IStruct s, Appendable buf, String prefix) throws MetadataException {
TypeUtils.outputVal("{", buf, prefix);
if ( s == null ) {
TypeUtils.outputVal("<null>\n", buf, "");
return;
}
TypeUtils.outputVal("\n", buf, "");
String fieldPrefix = prefix + "\t";
for(AttributeInfo i : fieldMapping.fields.values()) {
Object aVal = s.get(i.name);
TypeUtils.outputVal(i.name + " : ", buf, fieldPrefix);
i.dataType().output(aVal, buf, "");
TypeUtils.outputVal("\n", buf, "");
}
TypeUtils.outputVal("\n}\n", buf, "");
}
}
......@@ -18,12 +18,12 @@
package org.apache.metadata.dsl
import org.apache.metadata.MetadataService
import org.apache.metadata.{ITypedStruct, MetadataService}
import org.apache.metadata.storage.StructInstance
import org.apache.metadata.types.TypeSystem
import scala.language.dynamics
class DynamicTypedStruct(val ts : StructInstance) extends Dynamic {
class DynamicTypedStruct(val ts : ITypedStruct) extends Dynamic {
def selectDynamic(name: String) = ts.get(name)
def updateDynamic(name: String)(value: Any) {
var value1 = value
......
......@@ -82,7 +82,7 @@ package object dsl {
def createInstance(typeName : String) = {
new DynamicTypedStruct(
ts.getDataType(typeName).asInstanceOf[StructType].createInstance())
ts.getDataType(typeName).asInstanceOf[IConstructableType[IStruct, ITypedStruct]].createInstance())
}
implicit def dynTypedStructToTypedStruct(s : DynamicTypedStruct) = s.ts
......
......@@ -19,7 +19,7 @@
package org.apache.metadata.json
import org.apache.metadata.types.DataTypes.{MapType, TypeCategory, ArrayType}
import org.apache.metadata.{MetadataException, MetadataService}
import org.apache.metadata.{ITypedStruct, IStruct, MetadataException, MetadataService}
import org.apache.metadata.types._
import org.json4s.JsonAST.JInt
import org.json4s._
......@@ -27,7 +27,6 @@ import org.json4s.native.Serialization.{read, write => swrite}
import org.json4s.reflect.{ScalaType, Reflector}
import java.util.regex.Pattern
import java.util.Date
import org.apache.metadata.storage.StructInstance
import collection.JavaConversions._
import scala.collection.JavaConverters._
......@@ -45,7 +44,7 @@ class BigIntegerSerializer extends CustomSerializer[java.math.BigInteger](format
}
))
class TypedStructSerializer extends Serializer[StructInstance] {
class TypedStructSerializer extends Serializer[ITypedStruct] {
def extractList(lT : ArrayType, value : JArray)(implicit format: Formats) : Any = {
val dT = lT.getElemType
......@@ -69,15 +68,15 @@ class TypedStructSerializer extends Serializer[StructInstance] {
case value : JObject if dT.getTypeCategory eq TypeCategory.MAP =>
extractMap(dT.asInstanceOf[MapType], value.asInstanceOf[JObject])
case value : JObject =>
Extraction.extract[StructInstance](value)
Extraction.extract[ITypedStruct](value)
}
def deserialize(implicit format: Formats) = {
case (TypeInfo(clazz, ptype), json) if classOf[StructInstance].isAssignableFrom(clazz) => json match {
case (TypeInfo(clazz, ptype), json) if classOf[ITypedStruct].isAssignableFrom(clazz) => json match {
case JObject(fs) =>
val(typ, fields) = fs.partition(f => f._1 == Serialization.STRUCT_TYPE_FIELD_NAME)
val typName = typ(0)._2.asInstanceOf[JString].s
val sT = MetadataService.getCurrentTypeSystem().getDataType(typName).asInstanceOf[StructType]
val sT = MetadataService.getCurrentTypeSystem().getDataType(typName).asInstanceOf[IConstructableType[IStruct, ITypedStruct]]
val s = sT.createInstance()
fields.foreach { f =>
val fName = f._1
......@@ -85,7 +84,8 @@ class TypedStructSerializer extends Serializer[StructInstance] {
if ( fInfo != null ) {
//println(fName)
var v = f._2
if ( fInfo.dataType().isInstanceOf[StructType] ) {
if ( fInfo.dataType().getTypeCategory == TypeCategory.TRAIT ||
fInfo.dataType().getTypeCategory == TypeCategory.STRUCT) {
v = v match {
case JObject(sFields) =>
JObject(JField(Serialization.STRUCT_TYPE_FIELD_NAME, JString(fInfo.dataType.getName)) :: sFields)
......@@ -109,7 +109,7 @@ class TypedStructSerializer extends Serializer[StructInstance] {
//implicit def javaBigInteger2bigInt(x: java.math.BigInteger): BigInt = new BigInt(x)
def serialize(implicit format: Formats) = {
case e: StructInstance =>
case e: ITypedStruct =>
val fields = e.fieldMapping.fields.map {
case (fName, info) => {
var v = e.get(fName)
......@@ -119,7 +119,7 @@ class TypedStructSerializer extends Serializer[StructInstance] {
JField(fName, Extraction.decompose(v))
}
}.toList.map(_.asInstanceOf[JField])
JObject(JField(Serialization.STRUCT_TYPE_FIELD_NAME, JString(e.dataTypeName)) :: fields)
JObject(JField(Serialization.STRUCT_TYPE_FIELD_NAME, JString(e.getTypeName)) :: fields)
}
}
......
......@@ -38,7 +38,7 @@ public class StructTest extends BaseTest {
@Test
public void test1() throws MetadataException {
Struct s = createStruct(ms);
StructInstance ts = structType.convert(s, Multiplicity.REQUIRED);
ITypedStruct ts = structType.convert(s, Multiplicity.REQUIRED);
System.out.println(ts);
}
......@@ -49,7 +49,7 @@ public class StructTest extends BaseTest {
Struct s2 = new Struct(recursiveStructType.getName());
s2.set("a", 1);
s2.set("s", s1);
StructInstance ts = recursiveStructType.convert(s2, Multiplicity.REQUIRED);
ITypedStruct ts = recursiveStructType.convert(s2, Multiplicity.REQUIRED);
System.out.println(ts);
}
......
......@@ -64,7 +64,7 @@ public class TraitTest extends BaseTest {
s1.set("A.C.D.d", 3);
StructInstance ts = DType.convert(s1, Multiplicity.REQUIRED);
ITypedStruct ts = DType.convert(s1, Multiplicity.REQUIRED);
System.out.println(ts);
/*
......
......@@ -19,11 +19,10 @@
package org.apache.metadata.json
import com.google.common.collect.ImmutableList
import org.apache.metadata.Struct
import org.apache.metadata.{ITypedStruct, Struct, BaseTest}
import org.apache.metadata.storage.StructInstance
import org.apache.metadata.storage.StructInstance
import org.apache.metadata.types._
import org.apache.metadata.{Struct, BaseTest}
import org.json4s.NoTypeHints
import org.junit.Before
import org.junit.Test
......@@ -46,7 +45,7 @@ class SerializationTest extends BaseTest {
@Test def test1 {
val s: Struct = BaseTest.createStruct(ms)
val ts: StructInstance = structType.convert(s, Multiplicity.REQUIRED)
val ts: ITypedStruct = structType.convert(s, Multiplicity.REQUIRED)
println("Typed Struct :")
println(ts)
......@@ -65,7 +64,7 @@ class SerializationTest extends BaseTest {
@Test def test2 {
val s: Struct = BaseTest.createStruct(ms)
val ts: StructInstance = structType.convert(s, Multiplicity.REQUIRED)
val ts: ITypedStruct = structType.convert(s, Multiplicity.REQUIRED)
implicit val formats = org.json4s.native.Serialization.formats(NoTypeHints) + new TypedStructSerializer +
new BigDecimalSerializer + new BigIntegerSerializer
......@@ -108,7 +107,7 @@ class SerializationTest extends BaseTest {
s1.set("A.C.D.d", 3)
val s: Struct = BaseTest.createStruct(ms)
val ts: StructInstance = DType.convert(s1, Multiplicity.REQUIRED)
val ts: ITypedStruct = DType.convert(s1, Multiplicity.REQUIRED)
implicit val formats = org.json4s.native.Serialization.formats(NoTypeHints) + new TypedStructSerializer +
new BigDecimalSerializer + new BigIntegerSerializer
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment