http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/698a5652/intg/src/main/java/org/apache/atlas/model/typedef/AtlasStructDef.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/model/typedef/AtlasStructDef.java b/intg/src/main/java/org/apache/atlas/model/typedef/AtlasStructDef.java new file mode 100644 index 0000000..af42c05 --- /dev/null +++ b/intg/src/main/java/org/apache/atlas/model/typedef/AtlasStructDef.java @@ -0,0 +1,401 @@ +/** + * 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.atlas.model.typedef; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.ListIterator; +import java.util.Set; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.hadoop.util.StringUtils; +import org.codehaus.jackson.annotate.JsonAutoDetect; +import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.PUBLIC_ONLY; +import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.NONE; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.map.annotate.JsonSerialize; + + +/** + * class that captures details of a struct-type. + */ +@JsonAutoDetect(getterVisibility=PUBLIC_ONLY, setterVisibility=PUBLIC_ONLY, fieldVisibility=NONE) +@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown=true) +public class AtlasStructDef extends AtlasBaseTypeDef implements Serializable { + private static final long serialVersionUID = 1L; + + // do not update this list contents directly - the list might be in the middle of iteration in another thread + // to update list contents: 1) make a copy 2) update the copy 3) assign the copy to this member + private List<AtlasAttributeDef> attributeDefs; + + public AtlasStructDef() { + this(null, null, null, null); + } + + public AtlasStructDef(String name) { + this(name, null, null, null); + } + + public AtlasStructDef(String name, String description) { + this(name, description, null, null); + } + + public AtlasStructDef(String name, String description, String typeVersion) { + this(name, description, typeVersion, null); + } + + public AtlasStructDef(String name, String description, String typeVersion, List<AtlasAttributeDef> attributeDefs) { + super(name, description, typeVersion); + + setAttributeDefs(attributeDefs); + } + + public AtlasStructDef(AtlasStructDef other) { + super(other); + + setAttributeDefs(other != null ? other.getAttributeDefs() : null); + } + + public List<AtlasAttributeDef> getAttributeDefs() { + return attributeDefs; + } + + public void setAttributeDefs(List<AtlasAttributeDef> attributeDefs) { + if (this.attributeDefs != null && this.attributeDefs == attributeDefs) { + return; + } + + if (CollectionUtils.isEmpty(attributeDefs)) { + this.attributeDefs = Collections.emptyList(); + } else { + // if multiple attributes with same name are present, keep only the last entry + List<AtlasAttributeDef> tmpList = new ArrayList<AtlasAttributeDef>(attributeDefs.size()); + Set<String> attribNames = new HashSet<String>(); + + ListIterator<AtlasAttributeDef> iter = attributeDefs.listIterator(attributeDefs.size()); + while (iter.hasPrevious()) { + AtlasAttributeDef attributeDef = iter.previous(); + String attribName = attributeDef != null ? attributeDef.getName() : null; + + if (attribName != null) { + attribName = attribName.toLowerCase(); + + if (!attribNames.contains(attribName)) { + tmpList.add(new AtlasAttributeDef(attributeDef)); + + attribNames.add(attribName); + } + } + } + Collections.reverse(tmpList); + + this.attributeDefs = Collections.unmodifiableList(tmpList); + } + } + + public AtlasAttributeDef getAttribute(String attrName) { + return findAttribute(this.attributeDefs, attrName); + } + + public void addAttribute(AtlasAttributeDef attributeDef) { + if (attributeDef == null) { + return; + } + + List<AtlasAttributeDef> a = this.attributeDefs; + + List<AtlasAttributeDef> tmpList = new ArrayList<AtlasAttributeDef>(); + if (CollectionUtils.isNotEmpty(a)) { + // copy existing attributes, except ones having same name as the attribute being added + for (AtlasAttributeDef existingAttrDef : a) { + if (!StringUtils.equalsIgnoreCase(existingAttrDef.getName(), attributeDef.getName())) { + tmpList.add(existingAttrDef); + } + } + } + tmpList.add(new AtlasAttributeDef(attributeDef)); + + this.attributeDefs = Collections.unmodifiableList(tmpList); + } + + public void removeAttribute(String attrName) { + List<AtlasAttributeDef> a = this.attributeDefs; + + if (hasAttribute(a, attrName)) { + List<AtlasAttributeDef> tmpList = new ArrayList<AtlasAttributeDef>(); + + // copy existing attributes, except ones having same name as the attribute being removed + for (AtlasAttributeDef existingAttrDef : a) { + if (!StringUtils.equalsIgnoreCase(existingAttrDef.getName(), attrName)) { + tmpList.add(existingAttrDef); + } + } + + this.attributeDefs = Collections.unmodifiableList(tmpList); + } + } + + public boolean hasAttribute(String attrName) { + return getAttribute(attrName) != null; + } + + private static boolean hasAttribute(List<AtlasAttributeDef> attributeDefs, String attrName) { + return findAttribute(attributeDefs, attrName) != null; + } + + private static AtlasAttributeDef findAttribute(List<AtlasAttributeDef> attributeDefs, String attrName) { + AtlasAttributeDef ret = null; + + if (CollectionUtils.isNotEmpty(attributeDefs)) { + for (AtlasAttributeDef attributeDef : attributeDefs) { + if (StringUtils.equalsIgnoreCase(attributeDef.getName(), attrName)) { + ret = attributeDef; + break; + } + } + } + + return ret; + } + + @Override + public StringBuilder toString(StringBuilder sb) { + if (sb == null) { + sb = new StringBuilder(); + } + + sb.append("AtlasStructDef{"); + super.toString(sb); + sb.append(", attributeDefs=["); + dumpObjects(attributeDefs, sb); + sb.append("]"); + sb.append('}'); + + return sb; + } + + @Override + public boolean equals(Object o) { + if (this == o) { return true; } + if (o == null || getClass() != o.getClass()) { return false; } + if (!super.equals(o)) { return false; } + + AtlasStructDef that = (AtlasStructDef) o; + + if (attributeDefs != null ? !attributeDefs.equals(that.attributeDefs) : that.attributeDefs != null) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (attributeDefs != null ? attributeDefs.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return toString(new StringBuilder()).toString(); + } + + /** + * class that captures details of a struct-attribute. + */ + @JsonAutoDetect(getterVisibility=PUBLIC_ONLY, setterVisibility=PUBLIC_ONLY, fieldVisibility=NONE) + @JsonSerialize(include= JsonSerialize.Inclusion.NON_NULL) + @JsonIgnoreProperties(ignoreUnknown=true) + public static class AtlasAttributeDef implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * single-valued attribute or multi-valued attribute. + */ + public enum Cardinality { SINGLE, LIST, SET }; + + public static final int COUNT_NOT_SET = -1; + + private String name; + private String typeName; + private boolean isOptional; + private Cardinality cardinality; + private int valuesMinCount; + private int valuesMaxCount; + private boolean isUnique; + private boolean isIndexable; + + public AtlasAttributeDef() { this(null, null); } + + public AtlasAttributeDef(String name, String typeName) { + this(name, typeName, false, Cardinality.SINGLE, 1, 1, false, false); + } + + public AtlasAttributeDef(String name, String typeName, boolean isOptional, Cardinality cardinality, + int valuesMinCount, int valuesMaxCount, boolean isUnique, boolean isIndexable) { + setName(name); + setTypeName(typeName); + setOptional(isOptional); + setCardinality(cardinality); + setValuesMinCount(valuesMinCount); + setValuesMaxCount(valuesMaxCount); + setUnique(isUnique); + setIndexable(isIndexable); + } + + public AtlasAttributeDef(AtlasAttributeDef other) { + if (other != null) { + setName(other.getName()); + setTypeName(other.getTypeName()); + setOptional(other.isOptional()); + setCardinality(other.getCardinality()); + setValuesMinCount(other.getValuesMinCount()); + setValuesMaxCount(other.getValuesMaxCount()); + setUnique(other.isUnique()); + setIndexable(other.isIndexable()); + } + } + + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getTypeName() { + return typeName; + } + + public void setTypeName(String typeName) { + this.typeName = typeName; + } + + public boolean isOptional() { + return isOptional; + } + + public void setOptional(boolean optional) { isOptional = optional; } + + public void setCardinality(Cardinality cardinality) { + this.cardinality = cardinality; + } + + public Cardinality getCardinality() { + return cardinality; + } + + public int getValuesMinCount() { + return valuesMinCount; + } + + public void setValuesMinCount(int valuesMinCount) { + this.valuesMinCount = valuesMinCount; + } + + public int getValuesMaxCount() { + return valuesMaxCount; + } + + public void setValuesMaxCount(int valuesMaxCount) { + this.valuesMaxCount = valuesMaxCount; + } + + public boolean isUnique() { + return isUnique; + } + + public void setUnique(boolean unique) { + isUnique = unique; + } + + public boolean isIndexable() { + return isIndexable; + } + + public void setIndexable(boolean idexable) { + isIndexable = idexable; + } + + + public StringBuilder toString(StringBuilder sb) { + if (sb == null) { + sb = new StringBuilder(); + } + + sb.append("AtlasAttributeDef{"); + sb.append("name='").append(name).append('\''); + sb.append(", typeName='").append(typeName).append('\''); + sb.append(", isOptional=").append(isOptional); + sb.append(", cardinality=").append(cardinality); + sb.append(", valuesMinCount=").append(valuesMinCount); + sb.append(", valuesMaxCount=").append(valuesMaxCount); + sb.append(", isUnique=").append(isUnique); + sb.append(", isIndexable=").append(isIndexable); + sb.append('}'); + + return sb; + } + + @Override + public boolean equals(Object o) { + if (this == o) { return true; } + if (o == null || getClass() != o.getClass()) { return false; } + + AtlasAttributeDef that = (AtlasAttributeDef) o; + + if (name != null ? !name.equals(that.name) : that.name != null) { return false; } + if (typeName != null ? !typeName.equals(that.typeName) : that.typeName != null) { return false; } + if (isOptional != that.isOptional) { return false; } + if (cardinality != null ? !cardinality.equals(that.cardinality) : that.cardinality != null) { + return false; + } + if (valuesMinCount != that.valuesMinCount) { return false; } + if (valuesMaxCount != that.valuesMaxCount) { return false; } + if (isUnique != that.isUnique) { return false; } + if (isIndexable != that.isIndexable) { return false; } + + return true; + } + + @Override + public int hashCode() { + int result = name != null ? name.hashCode() : 0; + result = 31 * result + (typeName != null ? typeName.hashCode() : 0); + result = 31 * result + (isOptional ? 1 : 0); + result = 31 * result + (cardinality != null ? cardinality.hashCode() : 0); + result = 31 * result + valuesMinCount; + result = 31 * result + valuesMaxCount; + result = 31 * result + (isUnique ? 1 : 0); + result = 31 * result + (isIndexable ? 1 : 0); + return result; + } + + @Override + public String toString() { + return toString(new StringBuilder()).toString(); + } + } +}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/698a5652/intg/src/main/java/org/apache/atlas/type/AtlasArrayType.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/type/AtlasArrayType.java b/intg/src/main/java/org/apache/atlas/type/AtlasArrayType.java new file mode 100644 index 0000000..1473c3a --- /dev/null +++ b/intg/src/main/java/org/apache/atlas/type/AtlasArrayType.java @@ -0,0 +1,271 @@ +/** + * 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.atlas.type; + + +import org.apache.atlas.exception.AtlasBaseException; +import org.apache.atlas.model.typedef.AtlasBaseTypeDef; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Set; + +import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef.COUNT_NOT_SET; + +/** + * class that implements behaviour of an array-type. + */ +public class AtlasArrayType extends AtlasType { + private static final Logger LOG = LoggerFactory.getLogger(AtlasArrayType.class); + + private final String elementTypeName; + private final int minCount; + private final int maxCount; + + private AtlasType elementType; + + public AtlasArrayType(AtlasType elementType) { + this(elementType, COUNT_NOT_SET, COUNT_NOT_SET); + } + + public AtlasArrayType(AtlasType elementType, int minCount, int maxCount) { + super(AtlasBaseTypeDef.getArrayTypeName(elementType.getTypeName())); + + this.elementTypeName = elementType.getTypeName(); + this.minCount = minCount; + this.maxCount = maxCount; + this.elementType = elementType; + } + + public AtlasArrayType(String elementTypeName) { + this(elementTypeName, COUNT_NOT_SET, COUNT_NOT_SET); + } + + public AtlasArrayType(String elementTypeName, int minCount, int maxCount) { + super(AtlasBaseTypeDef.getArrayTypeName(elementTypeName)); + + this.elementTypeName = elementTypeName; + this.minCount = minCount; + this.maxCount = maxCount; + this.elementType = null; + } + + public AtlasArrayType(String elementTypeName, AtlasTypeRegistry typeRegistry) throws AtlasBaseException { + this(elementTypeName, COUNT_NOT_SET, COUNT_NOT_SET, typeRegistry); + } + + public AtlasArrayType(String elementTypeName, int minCount, int maxCount, AtlasTypeRegistry typeRegistry) + throws AtlasBaseException { + super(AtlasBaseTypeDef.getArrayTypeName(elementTypeName)); + + this.elementTypeName = elementTypeName; + this.minCount = minCount; + this.maxCount = maxCount; + + this.resolveReferences(typeRegistry); + } + + @Override + public void resolveReferences(AtlasTypeRegistry typeRegistry) throws AtlasBaseException { + elementType = typeRegistry.getType(elementTypeName); + + if (elementType == null) { + String msg = elementTypeName + ": unknown element-type for array"; + + LOG.error(msg); + + throw new AtlasBaseException(msg); + } + + elementType.resolveReferences(typeRegistry); + } + + @Override + public Collection<? extends Object> createDefaultValue() { + Collection<Object> ret = new ArrayList<Object>(); + + ret.add(elementType.createDefaultValue()); + + if (minCount != COUNT_NOT_SET) { + for (int i = 1; i < minCount; i++) { + ret.add(elementType.createDefaultValue()); + } + } + + return ret; + } + + @Override + public boolean isValidValue(Object obj) { + if (obj != null) { + if (obj instanceof List || obj instanceof Set) { + Collection objList = (Collection) obj; + + if (!isValidElementCount(objList.size())) { + return false; + } + + for (Object element : objList) { + if (!elementType.isValidValue(element)) { + return false; + } + } + } else if (obj.getClass().isArray()) { + int arrayLen = Array.getLength(obj); + + if (!isValidElementCount(arrayLen)) { + return false; + } + + for (int i = 0; i < arrayLen; i++) { + if (!elementType.isValidValue(Array.get(obj, i))) { + return false; + } + } + } else { + return false; // invalid type + } + } + + return true; + } + + @Override + public Collection<? extends Object> getNormalizedValue(Object obj) { + if (obj == null) { + return null; + } + + if (obj instanceof List || obj instanceof Set) { + List<Object> ret = new ArrayList<Object>(); + + Collection objList = (Collection) obj; + + if (!isValidElementCount(objList.size())) { + return null; + } + + for (Object element : objList) { + if (element != null) { + Object normalizedValue = elementType.getNormalizedValue(element); + + if (normalizedValue != null) { + ret.add(normalizedValue); + } else { + return null; // invalid element value + } + } else { + ret.add(element); + } + } + + return ret; + } else if (obj.getClass().isArray()) { + List<Object> ret = new ArrayList<Object>(); + + int arrayLen = Array.getLength(obj); + + if (!isValidElementCount(arrayLen)) { + return null; + } + + for (int i = 0; i < arrayLen; i++) { + Object element = Array.get(obj, i); + + if (element != null) { + Object normalizedValue = elementType.getNormalizedValue(element); + + if (normalizedValue != null) { + ret.add(normalizedValue); + } else { + return null; // invalid element value + } + } else { + ret.add(element); + } + } + + return ret; + } + + return null; + } + + @Override + public boolean validateValue(Object obj, String objName, List<String> messages) { + boolean ret = true; + + if (obj != null) { + if (obj instanceof List || obj instanceof Set) { + Collection objList = (Collection) obj; + + if (!isValidElementCount(objList.size())) { + ret = false; + + messages.add(objName + ": incorrect number of values. found=" + objList.size() + + "; expected: minCount=" + minCount + ", maxCount=" + maxCount); + } + + int idx = 0; + for (Object element : objList) { + ret = elementType.validateValue(element, objName + "[" + idx + "]", messages) && ret; + idx++; + } + } else if (obj.getClass().isArray()) { + int arrayLen = Array.getLength(obj); + + if (!isValidElementCount(arrayLen)) { + ret = false; + + messages.add(objName + ": incorrect number of values. found=" + arrayLen + + "; expected: minCount=" + minCount + ", maxCount=" + maxCount); + } + + for (int i = 0; i < arrayLen; i++) { + ret = elementType.validateValue(Array.get(obj, i), objName + "[" + i + "]", messages) && ret; + } + } else { + ret = false; + + messages.add(objName + "=" + obj + ": invalid value for type " + getTypeName()); + } + } + + return ret; + } + + private boolean isValidElementCount(int count) { + if (minCount != COUNT_NOT_SET) { + if (count < minCount) { + return false; + } + } + + if (maxCount != COUNT_NOT_SET) { + if (count > maxCount) { + return false; + } + } + + return true; + } +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/698a5652/intg/src/main/java/org/apache/atlas/type/AtlasBuiltInTypes.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/type/AtlasBuiltInTypes.java b/intg/src/main/java/org/apache/atlas/type/AtlasBuiltInTypes.java new file mode 100644 index 0000000..16a3df6 --- /dev/null +++ b/intg/src/main/java/org/apache/atlas/type/AtlasBuiltInTypes.java @@ -0,0 +1,547 @@ +/** + * 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.atlas.type; + + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.text.ParseException; +import java.util.Date; +import java.util.Map; + +import org.apache.atlas.model.instance.AtlasObjectId; +import org.apache.atlas.model.typedef.AtlasBaseTypeDef; +import org.apache.commons.lang.StringUtils; + + +/** + * Built-in types in Atlas. + */ +public class AtlasBuiltInTypes { + + /** + * class that implements behaviour of boolean type. + */ + public static class AtlasBooleanType extends AtlasType { + private static final Boolean DEFAULT_VALUE = Boolean.FALSE; + + public AtlasBooleanType() { + super(AtlasBaseTypeDef.ATLAS_TYPE_BOOLEAN); + } + + @Override + public Boolean createDefaultValue() { + return DEFAULT_VALUE; + } + + @Override + public boolean isValidValue(Object obj) { + return true; + } + + @Override + public Boolean getNormalizedValue(Object obj) { + if (obj != null) { + if (obj instanceof Boolean) { + return (Boolean)obj; + } else { + return Boolean.valueOf(obj.toString()); + } + } + + return null; + } + } + + /** + * class that implements behaviour of byte type. + */ + public static class AtlasByteType extends AtlasType { + private static final Byte DEFAULT_VALUE = new Byte((byte)0); + + public AtlasByteType() { + super(AtlasBaseTypeDef.ATLAS_TYPE_BYTE); + } + + @Override + public Byte createDefaultValue() { + return DEFAULT_VALUE; + } + + @Override + public boolean isValidValue(Object obj) { + if (obj == null || obj instanceof Number) { + return true; + } + + return getNormalizedValue(obj) != null; + } + + @Override + public Byte getNormalizedValue(Object obj) { + if (obj != null) { + if (obj instanceof Byte) { + return (Byte) obj; + } else if (obj instanceof Number) { + return ((Number) obj).byteValue(); + } else { + String strValue = obj.toString(); + + if (StringUtils.isNotEmpty(strValue)) { + return Byte.valueOf(strValue); + } + } + } + + return null; + } + } + + /** + * class that implements behaviour of short type. + */ + public static class AtlasShortType extends AtlasType { + private static final Short DEFAULT_VALUE = new Short((short)0); + + public AtlasShortType() { + super(AtlasBaseTypeDef.ATLAS_TYPE_SHORT); + } + + @Override + public Short createDefaultValue() { + return DEFAULT_VALUE; + } + + @Override + public boolean isValidValue(Object obj) { + if (obj == null || obj instanceof Number) { + return true; + } + + return getNormalizedValue(obj) != null; + } + + @Override + public Short getNormalizedValue(Object obj) { + if (obj != null) { + if (obj instanceof Short) { + return (Short)obj; + } else if (obj instanceof Number) { + return ((Number) obj).shortValue(); + } else { + try { + return Short.valueOf(obj.toString()); + } catch(NumberFormatException excp) { + // ignore + } + } + } + + return null; + } + } + + /** + * class that implements behaviour of integer type. + */ + public static class AtlasIntType extends AtlasType { + private static final Integer DEFAULT_VALUE = new Integer(0); + + public AtlasIntType() { + super(AtlasBaseTypeDef.ATLAS_TYPE_INT); + } + + @Override + public Integer createDefaultValue() { + return DEFAULT_VALUE; + } + + @Override + public boolean isValidValue(Object obj) { + if (obj == null || obj instanceof Number) { + return true; + } + + return getNormalizedValue(obj) != null; + } + + @Override + public Integer getNormalizedValue(Object obj) { + if (obj != null) { + if (obj instanceof Integer) { + return (Integer) obj; + } else if (obj instanceof Number) { + return ((Number) obj).intValue(); + } else { + try { + return Integer.valueOf(obj.toString()); + } catch (NumberFormatException excp) { + // ignore + } + } + } + + return null; + } + } + + /** + * class that implements behaviour of long type. + */ + public static class AtlasLongType extends AtlasType { + private static final Long DEFAULT_VALUE = new Long(0); + + public AtlasLongType() { + super(AtlasBaseTypeDef.ATLAS_TYPE_LONG); + } + + @Override + public Long createDefaultValue() { + return DEFAULT_VALUE; + } + + @Override + public boolean isValidValue(Object obj) { + if (obj == null || obj instanceof Number) { + return true; + } + + return getNormalizedValue(obj) != null; + } + + @Override + public Long getNormalizedValue(Object obj) { + if (obj != null) { + if (obj instanceof Long) { + return (Long) obj; + } else if (obj instanceof Number) { + return ((Number) obj).longValue(); + } else { + try { + return Long.valueOf(obj.toString()); + } catch (NumberFormatException excp) { + // ignore + } + } + } + + return null; + } + } + + /** + * class that implements behaviour of float type. + */ + public static class AtlasFloatType extends AtlasType { + private static final Float DEFAULT_VALUE = new Float(0); + + public AtlasFloatType() { + super(AtlasBaseTypeDef.ATLAS_TYPE_FLOAT); + } + + @Override + public Float createDefaultValue() { + return DEFAULT_VALUE; + } + + @Override + public boolean isValidValue(Object obj) { + if (obj == null || obj instanceof Number) { + return true; + } + + return getNormalizedValue(obj) != null; + } + + @Override + public Float getNormalizedValue(Object obj) { + if (obj != null) { + if (obj instanceof Float) { + return (Float) obj; + } else if (obj instanceof Number) { + return ((Number) obj).floatValue(); + } else { + try { + return Float.valueOf(obj.toString()); + } catch (NumberFormatException excp) { + // ignore + } + } + } + + return null; + } + } + + /** + * class that implements behaviour of double type. + */ + public static class AtlasDoubleType extends AtlasType { + private static final Double DEFAULT_VALUE = new Double(0); + + public AtlasDoubleType() { + super(AtlasBaseTypeDef.ATLAS_TYPE_DOUBLE); + } + + @Override + public Double createDefaultValue() { + return DEFAULT_VALUE; + } + + @Override + public boolean isValidValue(Object obj) { + if (obj == null || obj instanceof Number) { + return true; + } + + return getNormalizedValue(obj) != null; + } + + @Override + public Double getNormalizedValue(Object obj) { + Double ret; + + if (obj != null) { + if (obj instanceof Double) { + return (Double) obj; + } else if (obj instanceof Number) { + return ((Number) obj).doubleValue(); + } else { + try { + return Double.valueOf(obj.toString()); + } catch (NumberFormatException excp) { + // ignore + } + } + } + + return null; + } + } + + /** + * class that implements behaviour of Java BigInteger type. + */ + public static class AtlasBigIntegerType extends AtlasType { + private static final BigInteger DEFAULT_VALUE = BigInteger.ZERO; + + public AtlasBigIntegerType() { + super(AtlasBaseTypeDef.ATLAS_TYPE_BIGINTEGER); + } + + @Override + public BigInteger createDefaultValue() { + return DEFAULT_VALUE; + } + + @Override + public boolean isValidValue(Object obj) { + if (obj == null || obj instanceof Number) { + return true; + } + + return getNormalizedValue(obj) != null; + } + + @Override + public BigInteger getNormalizedValue(Object obj) { + if (obj != null) { + if (obj instanceof BigInteger) { + return (BigInteger) obj; + } else if (obj instanceof Number) { + return BigInteger.valueOf(((Number) obj).longValue()); + } else { + try { + return new BigInteger(obj.toString()); + } catch (NumberFormatException excp) { + // ignore + } + } + } + + return null; + } + } + + /** + * class that implements behaviour of Java BigDecimal type. + */ + public static class AtlasBigDecimalType extends AtlasType { + private static final BigDecimal DEFAULT_VALUE = BigDecimal.ZERO; + + public AtlasBigDecimalType() { + super(AtlasBaseTypeDef.ATLAS_TYPE_BIGDECIMAL); + } + + @Override + public BigDecimal createDefaultValue() { + return DEFAULT_VALUE; + } + + @Override + public boolean isValidValue(Object obj) { + if (obj == null || obj instanceof Number) { + return true; + } + + return getNormalizedValue(obj) != null; + } + + @Override + public BigDecimal getNormalizedValue(Object obj) { + if (obj != null) { + if (obj instanceof BigDecimal) { + return (BigDecimal) obj; + } else if (obj instanceof Number) { + return BigDecimal.valueOf(((Number) obj).longValue()); + } else { + try { + return new BigDecimal(obj.toString()); + } catch (NumberFormatException excp) { + // ignore + } + } + } + + return null; + } + } + + /** + * class that implements behaviour of Date type. + */ + public static class AtlasDateType extends AtlasType { + private static final Date DEFAULT_VALUE = new Date(0); + + public AtlasDateType() { + super(AtlasBaseTypeDef.ATLAS_TYPE_DATE); + } + + @Override + public Date createDefaultValue() { + return DEFAULT_VALUE; + } + + @Override + public boolean isValidValue(Object obj) { + if (obj == null || obj instanceof Date || obj instanceof Number) { + return true; + } + + return getNormalizedValue(obj) != null; + } + + @Override + public Date getNormalizedValue(Object obj) { + if (obj != null) { + if (obj instanceof Date) { + return (Date) obj; + } else if (obj instanceof Number) { + return new Date(((Number) obj).longValue()); + } else { + try { + return AtlasBaseTypeDef.DATE_FORMATTER.parse(obj.toString()); + } catch (ParseException excp) { + try { // try to read it as a number + long longDate = Long.valueOf(obj.toString()); + return new Date(longDate); + } catch (NumberFormatException e) { + // ignore + } + } + } + } + + return null; + } + } + + /** + * class that implements behaviour of String type. + */ + public static class AtlasStringType extends AtlasType { + private static final String DEFAULT_VALUE = ""; + + public AtlasStringType() { + super(AtlasBaseTypeDef.ATLAS_TYPE_STRING); + } + + @Override + public String createDefaultValue() { + return DEFAULT_VALUE; + } + + @Override + public boolean isValidValue(Object obj) { + return true; + } + + @Override + public String getNormalizedValue(Object obj) { + if (obj != null) { + return obj.toString(); + } + + return null; + } + } + + /** + * class that implements behaviour of Atlas object-id type. + */ + public static class AtlasObjectIdType extends AtlasType { + public AtlasObjectIdType() { + super(AtlasBaseTypeDef.ATLAS_TYPE_OBJECT_ID); + } + + @Override + public AtlasObjectId createDefaultValue() { + return new AtlasObjectId(AtlasBaseTypeDef.ATLAS_TYPE_ASSET, "test"); + } + + @Override + public boolean isValidValue(Object obj) { + if (obj == null || obj instanceof AtlasObjectId) { + return true; + } else if (obj instanceof Map) { + Map map = (Map)obj; + + return map.containsKey(AtlasObjectId.KEY_TYPENAME) && map.containsKey(AtlasObjectId.KEY_GUID); + } + + return getNormalizedValue(obj) != null; + } + + @Override + public AtlasObjectId getNormalizedValue(Object obj) { + if (obj != null) { + if (obj instanceof AtlasObjectId) { + return (AtlasObjectId) obj; + } else if (obj instanceof Map) { + Map map = (Map) obj; + + if (map.containsKey(AtlasObjectId.KEY_TYPENAME) && map.containsKey(AtlasObjectId.KEY_GUID)) { + return new AtlasObjectId(map); + } + } + } + + return null; + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/698a5652/intg/src/main/java/org/apache/atlas/type/AtlasClassificationType.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/type/AtlasClassificationType.java b/intg/src/main/java/org/apache/atlas/type/AtlasClassificationType.java new file mode 100644 index 0000000..e0a0c6d --- /dev/null +++ b/intg/src/main/java/org/apache/atlas/type/AtlasClassificationType.java @@ -0,0 +1,201 @@ +/** + * 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.atlas.type; + + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.atlas.exception.AtlasBaseException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.apache.atlas.model.instance.AtlasClassification; +import org.apache.atlas.model.typedef.AtlasClassificationDef; +import org.apache.commons.collections.CollectionUtils; + + +/** + * class that implements behaviour of a classification-type. + */ +public class AtlasClassificationType extends AtlasStructType { + private static final Logger LOG = LoggerFactory.getLogger(AtlasClassificationType.class); + + private final AtlasClassificationDef classificationDef; + + private List<AtlasClassificationType> superTypes = Collections.emptyList(); + private Set<String> allSuperTypes = Collections.emptySet(); + + public AtlasClassificationType(AtlasClassificationDef classificationDef) { + super(classificationDef); + + this.classificationDef = classificationDef; + } + + public AtlasClassificationType(AtlasClassificationDef classificationDef, AtlasTypeRegistry typeRegistry) + throws AtlasBaseException { + super(classificationDef); + + this.classificationDef = classificationDef; + + resolveReferences(typeRegistry); + } + + @Override + public void resolveReferences(AtlasTypeRegistry typeRegistry) throws AtlasBaseException { + super.resolveReferences(typeRegistry); + + List<AtlasClassificationType> s = new ArrayList<AtlasClassificationType>(); + Set<String> allS = new HashSet<String>(); + + for (String superTypeName : classificationDef.getSuperTypes()) { + AtlasType superType = typeRegistry.getType(superTypeName); + + if (superType != null && superType instanceof AtlasClassificationType) { + AtlasClassificationType superClassificationType = (AtlasClassificationType)superType; + + superClassificationType.resolveReferences(typeRegistry); + + s.add(superClassificationType); + allS.add(superTypeName); + + if (CollectionUtils.isNotEmpty(superClassificationType.getAllSuperTypes())) { + allS.addAll(superClassificationType.getAllSuperTypes()); + } + } else { + String msg = superTypeName + ((superType == null) ? ": unknown" : ": incompatible"); + + msg += (" supertype in classification " + classificationDef.getName()); + + LOG.error(msg); + + throw new AtlasBaseException(msg); + } + } + + this.superTypes = Collections.unmodifiableList(s); + this.allSuperTypes = allS; + } + + public Set<String> getSuperTypes() { + return classificationDef.getSuperTypes(); + } + + public Set<String> getAllSuperTypes() { return allSuperTypes; } + + public boolean isSuperTypeOf(AtlasClassificationType classificationType) { + return classificationType != null ? classificationType.getAllSuperTypes().contains(this.getTypeName()) : false; + } + + public boolean isSubTypeOf(AtlasClassificationType classificationType) { + return classificationType != null ? allSuperTypes.contains(classificationType.getTypeName()) : false; + } + + @Override + public AtlasClassification createDefaultValue() { + AtlasClassification ret = new AtlasClassification(classificationDef.getName()); + + populateDefaultValues(ret); + + return ret; + } + + @Override + public boolean isValidValue(Object obj) { + if (obj != null) { + for (AtlasClassificationType superType : superTypes) { + if (!superType.isValidValue(obj)) { + return false; + } + } + + return super.isValidValue(obj); + } + + return true; + } + + @Override + public Object getNormalizedValue(Object obj) { + Object ret = null; + + if (obj != null) { + if (isValidValue(obj)) { + if (obj instanceof AtlasClassification) { + normalizeAttributeValues((AtlasClassification) obj); + ret = obj; + } else if (obj instanceof Map) { + normalizeAttributeValues((Map) obj); + ret = obj; + } + } + } + + return ret; + } + + @Override + public boolean validateValue(Object obj, String objName, List<String> messages) { + boolean ret = true; + + if (obj != null) { + for (AtlasClassificationType superType : superTypes) { + ret = superType.validateValue(obj, objName, messages) && ret; + } + + ret = super.validateValue(obj, objName, messages) && ret; + } + + return ret; + } + + public void normalizeAttributeValues(AtlasClassification classification) { + if (classification != null) { + for (AtlasClassificationType superType : superTypes) { + superType.normalizeAttributeValues(classification); + } + + super.normalizeAttributeValues(classification); + } + } + + @Override + public void normalizeAttributeValues(Map<String, Object> obj) { + if (obj != null) { + for (AtlasClassificationType superType : superTypes) { + superType.normalizeAttributeValues(obj); + } + + super.normalizeAttributeValues(obj); + } + } + + public void populateDefaultValues(AtlasClassification classification) { + if (classification != null) { + for (AtlasClassificationType superType : superTypes) { + superType.populateDefaultValues(classification); + } + + super.populateDefaultValues(classification); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/698a5652/intg/src/main/java/org/apache/atlas/type/AtlasEntityType.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/type/AtlasEntityType.java b/intg/src/main/java/org/apache/atlas/type/AtlasEntityType.java new file mode 100644 index 0000000..e91fb99 --- /dev/null +++ b/intg/src/main/java/org/apache/atlas/type/AtlasEntityType.java @@ -0,0 +1,201 @@ +/** + * 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.atlas.type; + + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.atlas.exception.AtlasBaseException; +import org.apache.atlas.model.instance.AtlasEntity; +import org.apache.atlas.model.typedef.AtlasEntityDef; +import org.apache.commons.collections.CollectionUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * class that implements behaviour of an entity-type. + */ +public class AtlasEntityType extends AtlasStructType { + private static final Logger LOG = LoggerFactory.getLogger(AtlasEntityType.class); + + private final AtlasEntityDef entityDef; + + private List<AtlasEntityType> superTypes = Collections.emptyList(); + private Set<String> allSuperTypes = Collections.emptySet(); + + public AtlasEntityType(AtlasEntityDef entityDef) { + super(entityDef); + + this.entityDef = entityDef; + } + + public AtlasEntityType(AtlasEntityDef entityDef, AtlasTypeRegistry typeRegistry) throws AtlasBaseException { + super(entityDef); + + this.entityDef = entityDef; + + resolveReferences(typeRegistry); + } + + @Override + public void resolveReferences(AtlasTypeRegistry typeRegistry) throws AtlasBaseException { + super.resolveReferences(typeRegistry); + + List<AtlasEntityType> s = new ArrayList<AtlasEntityType>(); + Set<String> allS = new HashSet<String>(); + + for (String superTypeName : entityDef.getSuperTypes()) { + AtlasType superType = typeRegistry.getType(superTypeName); + + if (superType != null && superType instanceof AtlasEntityType) { + AtlasEntityType superEntityType = (AtlasEntityType)superType; + + superEntityType.resolveReferences(typeRegistry); + + s.add(superEntityType); + allS.add(superTypeName); + + if (CollectionUtils.isNotEmpty(superEntityType.getAllSuperTypes())) { + allS.addAll(superEntityType.getAllSuperTypes()); + } + } else { + String msg = superTypeName + ((superType == null) ? ": unknown" : ": incompatible"); + + msg += (" supertype in entity " + entityDef.getName()); + + LOG.error(msg); + + throw new AtlasBaseException(msg); + } + } + + this.superTypes = Collections.unmodifiableList(s); + this.allSuperTypes = Collections.unmodifiableSet(allS); + } + + public Set<String> getSuperTypes() { + return entityDef.getSuperTypes(); + } + + public Set<String> getAllSuperTypes() { + return allSuperTypes; + } + + public boolean isSuperTypeOf(AtlasEntityType entityType) { + return entityType != null ? entityType.getAllSuperTypes().contains(this.getTypeName()) : false; + } + + public boolean isSubTypeOf(AtlasEntityType entityType) { + return entityType != null ? allSuperTypes.contains(entityType.getTypeName()) : false; + } + + @Override + public AtlasEntity createDefaultValue() { + AtlasEntity ret = new AtlasEntity(entityDef.getName()); + + populateDefaultValues(ret); + + return ret; + } + + @Override + public boolean isValidValue(Object obj) { + if (obj != null) { + for (AtlasEntityType superType : superTypes) { + if (!superType.isValidValue(obj)) { + return false; + } + } + + return super.isValidValue(obj); + } + + return true; + } + + @Override + public Object getNormalizedValue(Object obj) { + Object ret = null; + + if (obj != null) { + if (isValidValue(obj)) { + if (obj instanceof AtlasEntity) { + normalizeAttributeValues((AtlasEntity) obj); + ret = obj; + } else if (obj instanceof Map) { + normalizeAttributeValues((Map) obj); + ret = obj; + } + } + } + + return ret; + } + + @Override + public boolean validateValue(Object obj, String objName, List<String> messages) { + boolean ret = true; + + if (obj != null) { + for (AtlasEntityType superType : superTypes) { + ret = superType.validateValue(obj, objName, messages) && ret; + } + + ret = super.validateValue(obj, objName, messages) && ret; + } + + return ret; + } + + public void normalizeAttributeValues(AtlasEntity ent) { + if (ent != null) { + for (AtlasEntityType superType : superTypes) { + superType.normalizeAttributeValues(ent); + } + + super.normalizeAttributeValues(ent); + } + } + + @Override + public void normalizeAttributeValues(Map<String, Object> obj) { + if (obj != null) { + for (AtlasEntityType superType : superTypes) { + superType.normalizeAttributeValues(obj); + } + + super.normalizeAttributeValues(obj); + } + } + + public void populateDefaultValues(AtlasEntity ent) { + if (ent != null) { + for (AtlasEntityType superType : superTypes) { + superType.populateDefaultValues(ent); + } + + super.populateDefaultValues(ent); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/698a5652/intg/src/main/java/org/apache/atlas/type/AtlasEnumType.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/type/AtlasEnumType.java b/intg/src/main/java/org/apache/atlas/type/AtlasEnumType.java new file mode 100644 index 0000000..34f5d49 --- /dev/null +++ b/intg/src/main/java/org/apache/atlas/type/AtlasEnumType.java @@ -0,0 +1,87 @@ +/** + * 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.atlas.type; + + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.apache.atlas.model.typedef.AtlasEnumDef; +import org.apache.atlas.model.typedef.AtlasEnumDef.AtlasEnumElementDef; + + +/** + * class that implements behaviour of an enum-type. + */ +public class AtlasEnumType extends AtlasType { + private final AtlasEnumDef enumDef; + private final Map<String, AtlasEnumElementDef> elementDefs; + private final String defaultValue; + + public AtlasEnumType(AtlasEnumDef enumDef) { + super(enumDef.getName()); + + Map<String, AtlasEnumElementDef> e = new HashMap<String, AtlasEnumElementDef>(); + + for (AtlasEnumElementDef elementDef : enumDef.getElementDefs()) { + e.put(elementDef.getValue().toLowerCase(), elementDef); + } + + String d = enumDef.getDefaultValue(); + + if (d == null) { + AtlasEnumElementDef defElem = enumDef.getElementDefs().size() > 0 ? enumDef.getElementDefs().get(0) : null; + + if (defElem != null) { + d = defElem.getValue(); + } + } + + this.enumDef = enumDef; + this.elementDefs = Collections.unmodifiableMap(e); + this.defaultValue = d; + } + + @Override + public Object createDefaultValue() { + return defaultValue; + } + + @Override + public boolean isValidValue(Object obj) { + if (obj != null) { + return elementDefs.containsKey(obj.toString().toLowerCase()); + } + + return true; + } + + @Override + public Object getNormalizedValue(Object obj) { + if (obj != null) { + AtlasEnumElementDef elementDef = elementDefs.get(obj.toString().toLowerCase()); + + if (elementDef != null) { + return elementDef.getValue(); + } + } + + return null; + } +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/698a5652/intg/src/main/java/org/apache/atlas/type/AtlasMapType.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/type/AtlasMapType.java b/intg/src/main/java/org/apache/atlas/type/AtlasMapType.java new file mode 100644 index 0000000..ca5bb21 --- /dev/null +++ b/intg/src/main/java/org/apache/atlas/type/AtlasMapType.java @@ -0,0 +1,189 @@ +/** + * 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.atlas.type; + + +import org.apache.atlas.exception.AtlasBaseException; +import org.apache.atlas.model.typedef.AtlasBaseTypeDef; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; + + +/** + * class that implements behaviour of a map-type. + */ +public class AtlasMapType extends AtlasType { + private static final Logger LOG = LoggerFactory.getLogger(AtlasEntityType.class); + + private final String keyTypeName; + private final String valueTypeName; + + private AtlasType keyType; + private AtlasType valueType; + + public AtlasMapType(String keyTypeName, String valueTypeName) { + super(AtlasBaseTypeDef.getMapTypeName(keyTypeName, valueTypeName)); + + this.keyTypeName = keyTypeName; + this.valueTypeName = valueTypeName; + } + + public AtlasMapType(AtlasType keyType, AtlasType valueType) { + super(AtlasBaseTypeDef.getMapTypeName(keyType.getTypeName(), valueType.getTypeName())); + + this.keyTypeName = keyType.getTypeName(); + this.valueTypeName = valueType.getTypeName(); + this.keyType = keyType; + this.valueType = valueType; + } + + public AtlasMapType(String keyTypeName, String valueTypeName, AtlasTypeRegistry typeRegistry) + throws AtlasBaseException { + super(AtlasBaseTypeDef.getMapTypeName(keyTypeName, valueTypeName)); + + this.keyTypeName = keyTypeName; + this.valueTypeName = valueTypeName; + + resolveReferences(typeRegistry); + } + + @Override + public void resolveReferences(AtlasTypeRegistry typeRegistry) throws AtlasBaseException { + this.keyType = typeRegistry.getType(keyTypeName); + this.valueType = typeRegistry.getType(valueTypeName); + + if (keyType == null) { + String msg = keyTypeName + ": unknown key-type for map"; + + LOG.error(msg); + + throw new AtlasBaseException(msg); + } + + if (valueType == null) { + String msg = valueTypeName + ": unknown value-type for map"; + + LOG.error(msg); + + throw new AtlasBaseException(msg); + } + + keyType.resolveReferences(typeRegistry); + valueType.resolveReferences(typeRegistry); + } + + @Override + public Map<Object, Object> createDefaultValue() { + Map<Object, Object> ret = new HashMap<Object, Object>(); + + ret.put(keyType.createDefaultValue(), valueType.createDefaultValue()); + + return ret; + } + + @Override + public boolean isValidValue(Object obj) { + if (obj != null) { + if (obj instanceof Map) { + Map<Object, Objects> map = (Map<Object, Objects>) obj; + + for (Map.Entry e : map.entrySet()) { + if (!keyType.isValidValue(e.getKey()) || !valueType.isValidValue(e.getValue())) { + return false; // invalid key/value + } + } + } else { + return false; // invalid type + } + } + + return true; + } + + @Override + public Map<Object, Object> getNormalizedValue(Object obj) { + if (obj == null) { + return null; + } + + if (obj instanceof Map) { + Map<Object, Object> ret = new HashMap<Object, Object>(); + + Map<Object, Objects> map = (Map<Object, Objects>) obj; + + for (Map.Entry e : map.entrySet()) { + Object normalizedKey = keyType.getNormalizedValue(e.getKey()); + + if (normalizedKey != null) { + Object value = e.getValue(); + + if (value != null) { + Object normalizedValue = valueType.getNormalizedValue(e.getValue()); + + if (normalizedValue != null) { + ret.put(normalizedKey, normalizedValue); + } else { + return null; // invalid value + } + } else { + ret.put(normalizedKey, value); + } + } else { + return null; // invalid key + } + } + + return ret; + } + + return null; + } + + @Override + public boolean validateValue(Object obj, String objName, List<String> messages) { + boolean ret = true; + + if (obj != null) { + if (obj instanceof Map) { + Map<Object, Objects> map = (Map<Object, Objects>) obj; + + for (Map.Entry e : map.entrySet()) { + Object key = e.getKey(); + + if (!keyType.isValidValue(key)) { + ret = false; + + messages.add(objName + "." + key + ": invalid key for type " + getTypeName()); + } else { + Object value = e.getValue(); + + ret = valueType.validateValue(value, objName + "." + key, messages) && ret; + } + } + } else { + ret = false; + + messages.add(objName + "=" + obj + ": invalid value for type " + getTypeName()); + } + } + + return ret; + } +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/698a5652/intg/src/main/java/org/apache/atlas/type/AtlasStructType.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/type/AtlasStructType.java b/intg/src/main/java/org/apache/atlas/type/AtlasStructType.java new file mode 100644 index 0000000..096f061 --- /dev/null +++ b/intg/src/main/java/org/apache/atlas/type/AtlasStructType.java @@ -0,0 +1,292 @@ +/** + * 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.atlas.type; + +import java.util.*; + +import org.apache.atlas.exception.AtlasBaseException; +import org.apache.atlas.model.instance.AtlasStruct; +import org.apache.atlas.model.typedef.AtlasStructDef; +import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef; +import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef.Cardinality; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * class that implements behaviour of a struct-type. + */ +public class AtlasStructType extends AtlasType { + private static final Logger LOG = LoggerFactory.getLogger(AtlasStructType.class); + + private final AtlasStructDef structDef; + + private Map<String, AtlasType> attrTypes = Collections.emptyMap(); + + public AtlasStructType(AtlasStructDef structDef) { + super(structDef.getName()); + + this.structDef = structDef; + } + + public AtlasStructType(AtlasStructDef structDef, AtlasTypeRegistry typeRegistry) throws AtlasBaseException { + super(structDef.getName()); + + this.structDef = structDef; + + this.resolveReferences(typeRegistry); + } + + @Override + public void resolveReferences(AtlasTypeRegistry typeRegistry) throws AtlasBaseException { + Map<String, AtlasType> a = new HashMap<String, AtlasType>(); + + for (AtlasAttributeDef attributeDef : structDef.getAttributeDefs()) { + AtlasType attrType = typeRegistry.getType(attributeDef.getTypeName()); + + if (attrType != null) { + Cardinality cardinality = attributeDef.getCardinality(); + + if (cardinality == Cardinality.LIST || cardinality == Cardinality.SET) { + attrType = new AtlasArrayType(attrType, + attributeDef.getValuesMinCount(), + attributeDef.getValuesMaxCount()); + } + + a.put(attributeDef.getName(), attrType); + } else { + String msg = attributeDef.getTypeName() + ": unknown type for attribute " + + structDef.getName() + "." + attributeDef.getName(); + + LOG.error(msg); + + throw new AtlasBaseException(msg); + } + } + + this.attrTypes = Collections.unmodifiableMap(a); + } + + @Override + public AtlasStruct createDefaultValue() { + AtlasStruct ret = new AtlasStruct(structDef.getName()); + + populateDefaultValues(ret); + + return ret; + } + + @Override + public boolean isValidValue(Object obj) { + if (obj != null) { + if (obj instanceof AtlasStruct) { + AtlasStruct structObj = (AtlasStruct) obj; + + for (AtlasAttributeDef attributeDef : structDef.getAttributeDefs()) { + if (!isAssignableValue(structObj.getAttribute(attributeDef.getName()), attributeDef)) { + return false; + } + } + } else if (obj instanceof Map) { + Map map = (Map) obj; + + for (AtlasAttributeDef attributeDef : structDef.getAttributeDefs()) { + if (!isAssignableValue(map.get(attributeDef.getName()), attributeDef)) { + return false; // no value for non-optinal attribute + } + } + } else { + return false; // invalid type + } + } + + return true; + } + + @Override + public Object getNormalizedValue(Object obj) { + Object ret = null; + + if (obj != null) { + if (isValidValue(obj)) { + if (obj instanceof AtlasStruct) { + normalizeAttributeValues((AtlasStruct) obj); + ret = obj; + } else if (obj instanceof Map) { + normalizeAttributeValues((Map) obj); + ret = obj; + } + } + } + + return ret; + } + + @Override + public boolean validateValue(Object obj, String objName, List<String> messages) { + boolean ret = true; + + if (obj != null) { + if (obj instanceof AtlasStruct) { + AtlasStruct structObj = (AtlasStruct) obj; + + for (AtlasAttributeDef attributeDef : structDef.getAttributeDefs()) { + String attrName = attributeDef.getName(); + AtlasType dataType = attrTypes.get(attributeDef.getName()); + + if (dataType != null) { + Object value = structObj.getAttribute(attrName); + String fieldName = objName + "." + attrName; + + if (value != null) { + ret = dataType.validateValue(value, fieldName, messages) && ret; + } else if (!attributeDef.isOptional()) { + ret = false; + + messages.add(fieldName + ": mandatory attribute value missing in type " + getTypeName()); + } + } + } + } else if (obj instanceof Map) { + Map map = (Map) obj; + + for (AtlasAttributeDef attributeDef : structDef.getAttributeDefs()) { + String attrName = attributeDef.getName(); + AtlasType dataType = attrTypes.get(attributeDef.getName()); + + if (dataType != null) { + Object value = map.get(attrName); + String fieldName = objName + "." + attrName; + + if (value != null) { + ret = dataType.validateValue(value, fieldName, messages) && ret; + } else if (!attributeDef.isOptional()) { + ret = false; + + messages.add(fieldName + ": mandatory attribute value missing in type " + getTypeName()); + } + } + } + } else { + ret = false; + + messages.add(objName + "=" + obj + ": invalid value for type " + getTypeName()); + } + } + + return ret; + } + + public void normalizeAttributeValues(AtlasStruct obj) { + if (obj != null) { + for (AtlasAttributeDef attributeDef : structDef.getAttributeDefs()) { + String attributeName = attributeDef.getName(); + + if (obj.hasAttribute(attributeName)) { + Object attributeValue = getNormalizedValue(obj.getAttribute(attributeName), attributeDef); + + obj.setAttribute(attributeName, attributeValue); + } else if (!attributeDef.isOptional()) { + obj.setAttribute(attributeName, createDefaultValue(attributeDef)); + } + } + } + } + + public void normalizeAttributeValues(Map<String, Object> obj) { + if (obj != null) { + for (AtlasAttributeDef attributeDef : structDef.getAttributeDefs()) { + String attributeName = attributeDef.getName(); + + if (obj.containsKey(attributeName)) { + Object attributeValue = getNormalizedValue(obj.get(attributeName), attributeDef); + + obj.put(attributeName, attributeValue); + } else if (!attributeDef.isOptional()) { + obj.put(attributeName, createDefaultValue(attributeDef)); + } + } + } + } + + public void populateDefaultValues(AtlasStruct obj) { + if (obj != null) { + Map<String, Object> attributes = obj.getAttributes(); + + if (attributes == null) { + attributes = new HashMap<String, Object>(); + } + + for (AtlasAttributeDef attributeDef : structDef.getAttributeDefs()) { + if (!attributeDef.isOptional()) { + attributes.put(attributeDef.getName(), createDefaultValue(attributeDef)); + } + } + + obj.setAttributes(attributes); + } + } + + private Object createDefaultValue(AtlasAttributeDef attributeDef) { + Object ret = null; + + if (attributeDef != null) { + AtlasType dataType = attrTypes.get(attributeDef.getName()); + + if (dataType != null) { + ret = dataType.createDefaultValue(); + } + } + + return ret; + } + + private boolean isAssignableValue(Object value, AtlasAttributeDef attributeDef) { + boolean ret = true; + + if (value != null) { + AtlasType attrType = attrTypes.get(attributeDef.getName()); + + if (attrType != null) { + if (!attrType.isValidValue(value)) { + ret = false; // invalid value + } + } + } else if (!attributeDef.isOptional()) { + ret = false; // mandatory attribute not present + } + + return ret; + } + + private Object getNormalizedValue(Object value, AtlasAttributeDef attributeDef) { + AtlasType attrType = attrTypes.get(attributeDef.getName()); + + if (attrType != null) { + if (value == null) { + if (!attributeDef.isOptional()) { + return attrType.createDefaultValue(); + } + } else { + return attrType.getNormalizedValue(value); + } + } + + return null; + } +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/698a5652/intg/src/main/java/org/apache/atlas/type/AtlasType.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/type/AtlasType.java b/intg/src/main/java/org/apache/atlas/type/AtlasType.java new file mode 100644 index 0000000..a3f1b02 --- /dev/null +++ b/intg/src/main/java/org/apache/atlas/type/AtlasType.java @@ -0,0 +1,73 @@ +/** + * 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.atlas.type; + + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import org.apache.atlas.exception.AtlasBaseException; +import org.apache.atlas.model.typedef.AtlasBaseTypeDef; + +import java.util.List; + + +/** + * base class that declares interface for all Atlas types. + */ +public abstract class AtlasType { + + private static final Gson GSON = + new GsonBuilder().setDateFormat(AtlasBaseTypeDef.SERIALIZED_DATE_FORMAT_STR).create(); + + private final String typeName; + + public AtlasType(String typeName) { + this.typeName = typeName; + } + + public void resolveReferences(AtlasTypeRegistry typeRegistry) throws AtlasBaseException { + + } + + public String getTypeName() { return typeName; } + + public abstract Object createDefaultValue(); + + public abstract boolean isValidValue(Object obj); + + public abstract Object getNormalizedValue(Object obj); + + public boolean validateValue(Object obj, String objName, List<String> messages) { + boolean ret = isValidValue(obj); + + if (!ret) { + messages.add(objName + "=" + obj + ": invalid value for type " + getTypeName()); + } + + return ret; + } + + + public static String toJson(Object obj) { + return GSON.toJson(obj); + } + + public static <T> T fromJson(String jsonStr, Class<T> type) { + return GSON.fromJson(jsonStr, type); + } +}
