http://git-wip-us.apache.org/repos/asf/atlas/blob/435fe3fb/intg/src/main/java/org/apache/atlas/model/notification/HookNotification.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/model/notification/HookNotification.java b/intg/src/main/java/org/apache/atlas/model/notification/HookNotification.java new file mode 100644 index 0000000..ea77a20 --- /dev/null +++ b/intg/src/main/java/org/apache/atlas/model/notification/HookNotification.java @@ -0,0 +1,103 @@ +/** + * 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.notification; + +import org.apache.commons.lang.StringUtils; +import org.codehaus.jackson.annotate.JsonAutoDetect; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.map.annotate.JsonSerialize; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; + +import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.NONE; +import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.PUBLIC_ONLY; + +/** + * Base type of hook message. + */ +@JsonAutoDetect(getterVisibility=PUBLIC_ONLY, setterVisibility=PUBLIC_ONLY, fieldVisibility=NONE) +@JsonSerialize(include=JsonSerialize.Inclusion.ALWAYS) +@JsonIgnoreProperties(ignoreUnknown=true) +@XmlRootElement +@XmlAccessorType(XmlAccessType.PROPERTY) +public class HookNotification implements Serializable { + private static final long serialVersionUID = 1L; + + public static final String UNKNOW_USER = "UNKNOWN"; + + /** + * Type of the hook message. + */ + public enum HookNotificationType { + TYPE_CREATE, TYPE_UPDATE, ENTITY_CREATE, ENTITY_PARTIAL_UPDATE, ENTITY_FULL_UPDATE, ENTITY_DELETE + } + + protected HookNotificationType type; + protected String user; + + public HookNotification() { + } + + public HookNotification(HookNotificationType type, String user) { + this.type = type; + this.user = user; + } + + public HookNotificationType getType() { + return type; + } + + public void setType(HookNotificationType type) { + this.type = type; + } + + public String getUser() { + if (StringUtils.isEmpty(user)) { + return UNKNOW_USER; + } + + return user; + } + + public void setUser(String user) { + this.user = user; + } + + public void normalize() { } + + @Override + public String toString() { + return toString(new StringBuilder()).toString(); + } + + public StringBuilder toString(StringBuilder sb) { + if (sb == null) { + sb = new StringBuilder(); + } + + sb.append("HookNotification{"); + sb.append("type=").append(type); + sb.append(", user=").append(user); + sb.append("}"); + + return sb; + } +}
http://git-wip-us.apache.org/repos/asf/atlas/blob/435fe3fb/intg/src/main/java/org/apache/atlas/model/notification/MessageVersion.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/model/notification/MessageVersion.java b/intg/src/main/java/org/apache/atlas/model/notification/MessageVersion.java new file mode 100644 index 0000000..1dafa94 --- /dev/null +++ b/intg/src/main/java/org/apache/atlas/model/notification/MessageVersion.java @@ -0,0 +1,170 @@ +/** + * 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.notification; + +import org.codehaus.jackson.annotate.JsonAutoDetect; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.map.annotate.JsonSerialize; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; + +import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.NONE; +import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.PUBLIC_ONLY; + +/** + * Represents the version of a notification message. + */ +@JsonAutoDetect(getterVisibility=PUBLIC_ONLY, setterVisibility=PUBLIC_ONLY, fieldVisibility=NONE) +@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown=true) +@XmlRootElement +@XmlAccessorType(XmlAccessType.PROPERTY) +public class MessageVersion implements Comparable<MessageVersion>, Serializable { + private static final long serialVersionUID = 1L; + + /** + * Used for message with no version (old format). + */ + public static final MessageVersion NO_VERSION = new MessageVersion("0"); + public static final MessageVersion VERSION_1 = new MessageVersion("1.0.0"); + + public static final MessageVersion CURRENT_VERSION = VERSION_1; + + private String version; + + + // ----- Constructors ---------------------------------------------------- + public MessageVersion() { + this.version = CURRENT_VERSION.version; + } + + /** + * Create a message version. + * + * @param version the version string + */ + public MessageVersion(String version) { + this.version = version; + + try { + getVersionParts(); + } catch (NumberFormatException e) { + throw new IllegalArgumentException(String.format("Invalid version string : %s.", version), e); + } + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + + // ----- Comparable ------------------------------------------------------ + + @Override + public int compareTo(MessageVersion that) { + if (that == null) { + return 1; + } + + Integer[] thisParts = getVersionParts(); + Integer[] thatParts = that.getVersionParts(); + + int length = Math.max(thisParts.length, thatParts.length); + + for (int i = 0; i < length; i++) { + + int comp = getVersionPart(thisParts, i) - getVersionPart(thatParts, i); + + if (comp != 0) { + return comp; + } + } + return 0; + } + + + // ----- Object overrides ------------------------------------------------ + + @Override + public boolean equals(Object that) { + if (this == that){ + return true; + } + + if (that == null || getClass() != that.getClass()) { + return false; + } + + return compareTo((MessageVersion) that) == 0; + } + + @Override + public int hashCode() { + return Arrays.hashCode(getVersionParts()); + } + + + @Override + public String toString() { + return "MessageVersion[version=" + version + "]"; + } + + // ----- helper methods -------------------------------------------------- + + /** + * Get the version parts array by splitting the version string. + * Strip the trailing zeros (i.e. '1.0.0' equals '1'). + * + * @return the version parts array + */ + public Integer[] getVersionParts() { + + String[] sParts = version.split("\\."); + ArrayList<Integer> iParts = new ArrayList<>(); + int trailingZeros = 0; + + for (String sPart : sParts) { + Integer iPart = new Integer(sPart); + + if (iPart == 0) { + ++trailingZeros; + } else { + for (int i = 0; i < trailingZeros; ++i) { + iParts.add(0); + } + trailingZeros = 0; + iParts.add(iPart); + } + } + return iParts.toArray(new Integer[iParts.size()]); + } + + public Integer getVersionPart(Integer[] versionParts, int i) { + return i < versionParts.length ? versionParts[i] : 0; + } +} http://git-wip-us.apache.org/repos/asf/atlas/blob/435fe3fb/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 index dc0d300..ce0a475 100644 --- a/intg/src/main/java/org/apache/atlas/type/AtlasType.java +++ b/intg/src/main/java/org/apache/atlas/type/AtlasType.java @@ -20,25 +20,56 @@ package org.apache.atlas.type; import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.model.TypeCategory; +import org.apache.atlas.model.notification.EntityNotification; +import org.apache.atlas.model.notification.EntityNotification.EntityNotificationType; +import org.apache.atlas.model.notification.HookNotification; +import org.apache.atlas.model.notification.HookNotification.HookNotificationType; import org.apache.atlas.model.typedef.AtlasBaseTypeDef; -import org.codehaus.jackson.map.DeserializationConfig; -import org.codehaus.jackson.map.ObjectMapper; +import org.apache.atlas.v1.model.notification.EntityNotificationV1; +import org.apache.atlas.v1.model.notification.HookNotificationV1.EntityCreateRequest; +import org.apache.atlas.v1.model.notification.HookNotificationV1.EntityDeleteRequest; +import org.apache.atlas.v1.model.notification.HookNotificationV1.EntityPartialUpdateRequest; +import org.apache.atlas.v1.model.notification.HookNotificationV1.EntityUpdateRequest; +import org.apache.atlas.v1.model.notification.HookNotificationV1.TypeRequest; +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.module.SimpleModule; +import org.codehaus.jackson.node.ObjectNode; +import org.codehaus.jackson.type.TypeReference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.IOException; +import java.text.ParseException; +import java.util.Date; import java.util.List; - - /** * base class that declares interface for all Atlas types. */ public abstract class AtlasType { + private static final Logger LOG = LoggerFactory.getLogger(AtlasStructType.class); private static final ObjectMapper mapper = new ObjectMapper() .configure(DeserializationConfig.Feature.USE_BIG_DECIMAL_FOR_FLOATS, true); + private static final ObjectMapper mapperV1 = new ObjectMapper() + .configure(DeserializationConfig.Feature.USE_BIG_DECIMAL_FOR_FLOATS, true); + + static { + SimpleModule atlasSerDeModule = new SimpleModule("AtlasSerDe", new Version(1, 0, 0, null)); + + atlasSerDeModule.addSerializer(Date.class, new DateSerializer()); + atlasSerDeModule.addDeserializer(Date.class, new DateDeserializer()); + atlasSerDeModule.addDeserializer(HookNotification.class, new HookNotificationDeserializer()); + atlasSerDeModule.addDeserializer(EntityNotification.class, new EntityNotificationDeserializer()); + + mapperV1.registerModule(atlasSerDeModule); + } + + private final String typeName; private final TypeCategory typeCategory; @@ -109,6 +140,8 @@ public abstract class AtlasType { try { ret = mapper.writeValueAsString(obj); }catch (IOException e){ + LOG.error("AtlasType.toJson()", e); + ret = null; } return ret; @@ -119,8 +152,134 @@ public abstract class AtlasType { try { ret = mapper.readValue(jsonStr, type); }catch (IOException e){ + LOG.error("AtlasType.fromJson()", e); + ret = null; } return ret; } + + public static String toV1Json(Object obj) { + String ret; + try { + ret = mapperV1.writeValueAsString(obj); + }catch (IOException e){ + LOG.error("AtlasType.toV1Json()", e); + + ret = null; + } + return ret; + } + + public static <T> T fromV1Json(String jsonStr, Class<T> type) { + T ret; + try { + ret = mapperV1.readValue(jsonStr, type); + }catch (IOException e){ + LOG.error("AtlasType.fromV1Json()", e); + + ret = null; + } + return ret; + } + + public static <T> T fromV1Json(String jsonStr, TypeReference<T> type) { + T ret; + try { + ret = mapperV1.readValue(jsonStr, type); + }catch (IOException e){ + LOG.error("AtlasType.toV1Json()", e); + + ret = null; + } + return ret; + } + + static class DateSerializer extends JsonSerializer<Date> { + @Override + public void serialize(Date value, JsonGenerator jgen, SerializerProvider provider) throws IOException { + if (value != null) { + jgen.writeString(AtlasBaseTypeDef.DATE_FORMATTER.format(value)); + } + } + } + + static class DateDeserializer extends JsonDeserializer<Date> { + @Override + public Date deserialize(JsonParser parser, DeserializationContext context) throws IOException { + Date ret = null; + + String value = parser.readValueAs(String.class); + + if (value != null) { + try { + ret = AtlasBaseTypeDef.DATE_FORMATTER.parse(value); + } catch (ParseException excp) { + } + } + + return ret; + } + } + + static class HookNotificationDeserializer extends JsonDeserializer<HookNotification> { + @Override + public HookNotification deserialize(JsonParser parser, DeserializationContext context) throws IOException { + HookNotification ret = null; + ObjectMapper mapper = (ObjectMapper) parser.getCodec(); + ObjectNode root = (ObjectNode) mapper.readTree(parser); + JsonNode typeNode = root != null ? root.get("type") : null; + String strType = typeNode != null ? typeNode.asText() : null; + HookNotificationType notificationType = strType != null ? HookNotificationType.valueOf(strType) : null; + + if (notificationType != null) { + switch (notificationType) { + case TYPE_CREATE: + case TYPE_UPDATE: + ret = mapper.readValue(root, TypeRequest.class); + break; + + case ENTITY_CREATE: + ret = mapper.readValue(root, EntityCreateRequest.class); + break; + + case ENTITY_PARTIAL_UPDATE: + ret = mapper.readValue(root, EntityPartialUpdateRequest.class); + break; + + case ENTITY_FULL_UPDATE: + ret = mapper.readValue(root, EntityUpdateRequest.class); + break; + + case ENTITY_DELETE: + ret = mapper.readValue(root, EntityDeleteRequest.class); + break; + } + } + + return ret; + } + } + + static class EntityNotificationDeserializer extends JsonDeserializer<EntityNotification> { + @Override + public EntityNotification deserialize(JsonParser parser, DeserializationContext context) throws IOException { + EntityNotification ret = null; + ObjectMapper mapper = (ObjectMapper) parser.getCodec(); + ObjectNode root = (ObjectNode) mapper.readTree(parser); + JsonNode typeNode = root != null ? root.get("type") : null; + String strType = typeNode != null ? typeNode.asText() : null; + EntityNotificationType notificationType = strType != null ? EntityNotificationType.valueOf(strType) : EntityNotificationType.ENTITY_NOTIFICATION_V1; + + if (root != null) { + switch (notificationType) { + case ENTITY_NOTIFICATION_V1: + ret = mapper.readValue(root, EntityNotificationV1.class); + break; + } + } + + return ret; + } + } } http://git-wip-us.apache.org/repos/asf/atlas/blob/435fe3fb/intg/src/main/java/org/apache/atlas/type/AtlasTypeRegistry.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/type/AtlasTypeRegistry.java b/intg/src/main/java/org/apache/atlas/type/AtlasTypeRegistry.java index bd4b0e9..5f55b43 100644 --- a/intg/src/main/java/org/apache/atlas/type/AtlasTypeRegistry.java +++ b/intg/src/main/java/org/apache/atlas/type/AtlasTypeRegistry.java @@ -846,8 +846,8 @@ public class AtlasTypeRegistry { boolean alreadyLockedByCurrentThread = typeRegistryUpdateLock.isHeldByCurrentThread(); if (!alreadyLockedByCurrentThread) { - if (LOG.isDebugEnabled()) { - LOG.debug("lockTypeRegistryForUpdate(): waiting for lock to be released by thread {}", lockedByThread); + if (lockedByThread != null) { + LOG.info("lockTypeRegistryForUpdate(): waiting for lock to be released by thread {}", lockedByThread); } } else { LOG.warn("lockTypeRegistryForUpdate(): already locked. currentLockCount={}", http://git-wip-us.apache.org/repos/asf/atlas/blob/435fe3fb/intg/src/main/java/org/apache/atlas/type/AtlasTypeUtil.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/type/AtlasTypeUtil.java b/intg/src/main/java/org/apache/atlas/type/AtlasTypeUtil.java index 5f3cefd..80c6a0c 100644 --- a/intg/src/main/java/org/apache/atlas/type/AtlasTypeUtil.java +++ b/intg/src/main/java/org/apache/atlas/type/AtlasTypeUtil.java @@ -17,17 +17,29 @@ */ package org.apache.atlas.type; -import com.google.common.collect.ImmutableSet; +import org.apache.atlas.model.instance.AtlasClassification; import org.apache.atlas.model.instance.AtlasEntity; import org.apache.atlas.model.instance.AtlasEntityHeader; import org.apache.atlas.model.instance.AtlasObjectId; -import org.apache.atlas.model.typedef.*; +import org.apache.atlas.model.instance.AtlasStruct; +import org.apache.atlas.model.typedef.AtlasBaseTypeDef; +import org.apache.atlas.model.typedef.AtlasClassificationDef; +import org.apache.atlas.model.typedef.AtlasEntityDef; +import org.apache.atlas.model.typedef.AtlasEnumDef; import org.apache.atlas.model.typedef.AtlasEnumDef.AtlasEnumElementDef; +import org.apache.atlas.model.typedef.AtlasRelationshipDef; import org.apache.atlas.model.typedef.AtlasRelationshipDef.PropagateTags; import org.apache.atlas.model.typedef.AtlasRelationshipDef.RelationshipCategory; +import org.apache.atlas.model.typedef.AtlasRelationshipEndDef; +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.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef; +import org.apache.atlas.model.typedef.AtlasTypeDefHeader; +import org.apache.atlas.model.typedef.AtlasTypesDef; +import org.apache.atlas.v1.model.typedef.AttributeDefinition; +import org.apache.atlas.v1.model.typedef.ClassTypeDefinition; +import org.apache.atlas.v1.model.typedef.Multiplicity; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; @@ -35,6 +47,7 @@ import org.apache.commons.lang.StringUtils; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; import static org.apache.atlas.model.typedef.AtlasBaseTypeDef.*; @@ -208,19 +221,19 @@ public class AtlasTypeUtil { return new AtlasEnumDef(name, description, "1.0", Arrays.asList(enumValues)); } - public static AtlasClassificationDef createTraitTypeDef(String name, ImmutableSet<String> superTypes, AtlasAttributeDef... attrDefs) { + public static AtlasClassificationDef createTraitTypeDef(String name, Set<String> superTypes, AtlasAttributeDef... attrDefs) { return createTraitTypeDef(name, null, superTypes, attrDefs); } - public static AtlasClassificationDef createTraitTypeDef(String name, String description, ImmutableSet<String> superTypes, AtlasAttributeDef... attrDefs) { + public static AtlasClassificationDef createTraitTypeDef(String name, String description, Set<String> superTypes, AtlasAttributeDef... attrDefs) { return createTraitTypeDef(name, description, "1.0", superTypes, attrDefs); } - public static AtlasClassificationDef createTraitTypeDef(String name, String description, String version, ImmutableSet<String> superTypes, AtlasAttributeDef... attrDefs) { + public static AtlasClassificationDef createTraitTypeDef(String name, String description, String version, Set<String> superTypes, AtlasAttributeDef... attrDefs) { return new AtlasClassificationDef(name, description, version, Arrays.asList(attrDefs), superTypes); } - public static AtlasClassificationDef createAtlasClassificationDef(String name, String description, String version, ImmutableSet<String> superTypes, ImmutableSet<String> entityTypes, AtlasAttributeDef... attrDefs) { + public static AtlasClassificationDef createAtlasClassificationDef(String name, String description, String version, Set<String> superTypes, Set<String> entityTypes, AtlasAttributeDef... attrDefs) { return new AtlasClassificationDef(name, description, version, Arrays.asList(attrDefs), superTypes, entityTypes, null); } @@ -232,18 +245,15 @@ public class AtlasTypeUtil { return new AtlasStructDef(name, description, "1.0", Arrays.asList(attrDefs)); } - public static AtlasEntityDef createClassTypeDef(String name, - ImmutableSet<String> superTypes, AtlasAttributeDef... attrDefs) { + public static AtlasEntityDef createClassTypeDef(String name, Set<String> superTypes, AtlasAttributeDef... attrDefs) { return createClassTypeDef(name, null, "1.0", superTypes, attrDefs); } - public static AtlasEntityDef createClassTypeDef(String name, String description, - ImmutableSet<String> superTypes, AtlasAttributeDef... attrDefs) { + public static AtlasEntityDef createClassTypeDef(String name, String description, Set<String> superTypes, AtlasAttributeDef... attrDefs) { return createClassTypeDef(name, description, "1.0", superTypes, attrDefs); } - public static AtlasEntityDef createClassTypeDef(String name, String description, String version, - ImmutableSet<String> superTypes, AtlasAttributeDef... attrDefs) { + public static AtlasEntityDef createClassTypeDef(String name, String description, String version, Set<String> superTypes, AtlasAttributeDef... attrDefs) { return new AtlasEntityDef(name, description, version, Arrays.asList(attrDefs), superTypes); } @@ -409,6 +419,129 @@ public class AtlasTypeUtil { return sb.toString(); } + public static ClassTypeDefinition toClassTypeDefinition(final AtlasEntityType entityType) { + ClassTypeDefinition ret = null; + + if (entityType != null) { + AtlasEntityDef entityDef = entityType.getEntityDef(); + ret = new ClassTypeDefinition(); + ret.setTypeName(entityDef.getName()); + ret.setTypeDescription(entityDef.getDescription()); + ret.setTypeVersion(entityDef.getTypeVersion()); + ret.setSuperTypes(entityDef.getSuperTypes()); + + if (MapUtils.isNotEmpty(entityType.getAllAttributes())) { + List<AttributeDefinition> attributeDefinitions = entityType.getAllAttributes() + .entrySet() + .stream() + .map(e -> toV1AttributeDefinition(e.getValue())) + .collect(Collectors.toList()); + + ret.setAttributeDefinitions(attributeDefinitions); + } + } + + return ret; + } + + public static AttributeDefinition toV1AttributeDefinition(AtlasStructType.AtlasAttribute attribute) { + AtlasAttributeDef attributeDef = attribute.getAttributeDef(); + AttributeDefinition ret = new AttributeDefinition(); + + ret.setName(attributeDef.getName()); + ret.setDataTypeName(attributeDef.getTypeName()); + ret.setIsUnique(attributeDef.getIsUnique()); + ret.setIsIndexable(attributeDef.getIsIndexable()); + ret.setIsComposite(attribute.isOwnedRef()); + ret.setReverseAttributeName(attribute.getInverseRefAttributeName()); + ret.setDefaultValue(attributeDef.getDefaultValue()); + ret.setDescription(attributeDef.getDescription()); + + final int lower; + final int upper; + + if (attributeDef.getCardinality() == AtlasAttributeDef.Cardinality.SINGLE) { + lower = attributeDef.getIsOptional() ? 0 : 1; + upper = 1; + } else { + if(attributeDef.getIsOptional()) { + lower = 0; + } else { + lower = attributeDef.getValuesMinCount() < 1 ? 1 : attributeDef.getValuesMinCount(); + } + + upper = attributeDef.getValuesMaxCount() < 2 ? Integer.MAX_VALUE : attributeDef.getValuesMaxCount(); + } + + Multiplicity multiplicity = new Multiplicity(); + multiplicity.setLower(lower); + multiplicity.setUpper(upper); + multiplicity.setIsUnique(AtlasAttributeDef.Cardinality.SET.equals(attributeDef.getCardinality())); + + ret.setMultiplicity(multiplicity); + + return ret; + } + + public static Map<String, Object> toMap(AtlasEntity entity) { + Map<String, Object> ret = null; + + if (entity != null) { + ret = new LinkedHashMap<>(); + + // Id type + ret.put("$typeName$", entity.getTypeName()); + ret.put("$id$", new LinkedHashMap<String, Object>(){{ + put("id", entity.getGuid()); + put("$typeName$", entity.getTypeName()); + put("version", entity.getVersion().intValue()); + put("state", entity.getStatus().name()); + }}); + + // System attributes + ret.put("$systemAttributes$", new LinkedHashMap<String, String>() {{ + put("createdBy", entity.getCreatedBy()); + put("modifiedBy", entity.getUpdatedBy()); + put("createdTime", entity.getCreateTime().toString()); + put("modifiedTime", entity.getUpdateTime().toString()); + }}); + + // Traits + if (CollectionUtils.isNotEmpty(entity.getClassifications())) { + Map<String, HashMap> traitDetails = entity.getClassifications() + .stream() + .collect(Collectors.toMap(AtlasStruct::getTypeName, AtlasTypeUtil::getNestedTraitDetails)); + ret.put("$traits$", traitDetails); + } + + // All attributes + if (MapUtils.isNotEmpty(entity.getAttributes())) { + for (Map.Entry<String, Object> entry : entity.getAttributes().entrySet()) { + if (entry.getValue() instanceof AtlasObjectId) { + ret.put(entry.getKey(), new LinkedHashMap<String, Object>(){{ + put("id", ((AtlasObjectId) entry.getValue()).getGuid()); + put("$typeName$", ((AtlasObjectId) entry.getValue()).getTypeName()); +// put("version", entity.getVersion().intValue()); +// put("state", entity.getStatus().name()); + }}); + } else { + ret.put(entry.getKey(), entry.getValue()); + } + } + } + + } + + return ret; + } + + private static HashMap getNestedTraitDetails(final AtlasClassification atlasClassification) { + return new HashMap<String, Object>() {{ + put("$typeName$", atlasClassification.getTypeName()); + putAll(atlasClassification.getAttributes()); + }}; + } + private static void dumpTypeNames(List<? extends AtlasBaseTypeDef> typeDefs, StringBuilder sb) { if (CollectionUtils.isNotEmpty(typeDefs)) { for (int i = 0; i < typeDefs.size(); i++) { http://git-wip-us.apache.org/repos/asf/atlas/blob/435fe3fb/intg/src/main/java/org/apache/atlas/typesystem/types/DataTypes.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/typesystem/types/DataTypes.java b/intg/src/main/java/org/apache/atlas/typesystem/types/DataTypes.java new file mode 100644 index 0000000..dba2d88 --- /dev/null +++ b/intg/src/main/java/org/apache/atlas/typesystem/types/DataTypes.java @@ -0,0 +1,35 @@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.typesystem.types; + +/* + * this enum must be in package org.apache.atlas.typesystem.types, since vertex property in GraphDB has reference to this type + */ +public class DataTypes { + public enum TypeCategory { + PRIMITIVE, + ENUM, + ARRAY, + MAP, + STRUCT, + TRAIT, + CLASS, + RELATIONSHIP + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/atlas/blob/435fe3fb/intg/src/main/java/org/apache/atlas/v1/model/instance/AtlasSystemAttributes.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/v1/model/instance/AtlasSystemAttributes.java b/intg/src/main/java/org/apache/atlas/v1/model/instance/AtlasSystemAttributes.java new file mode 100644 index 0000000..0b74365 --- /dev/null +++ b/intg/src/main/java/org/apache/atlas/v1/model/instance/AtlasSystemAttributes.java @@ -0,0 +1,156 @@ +/** + * 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.v1.model.instance; + +import org.codehaus.jackson.annotate.JsonAutoDetect; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.map.annotate.JsonSerialize; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.util.Date; +import java.util.Map; +import java.util.Objects; + +import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.NONE; +import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.PUBLIC_ONLY; + + +@JsonAutoDetect(getterVisibility=PUBLIC_ONLY, setterVisibility=PUBLIC_ONLY, fieldVisibility=NONE) +@JsonSerialize(include=JsonSerialize.Inclusion.ALWAYS) +@JsonIgnoreProperties(ignoreUnknown=true) +@XmlRootElement +@XmlAccessorType(XmlAccessType.PROPERTY) +public class AtlasSystemAttributes implements Serializable { + private static final long serialVersionUID = 1L; + + private String createdBy; + private String modifiedBy; + private Date createdTime; + private Date modifiedTime; + + + public AtlasSystemAttributes() { + } + + public AtlasSystemAttributes(AtlasSystemAttributes that) { + if (that != null) { + this.createdBy = that.createdBy; + this.modifiedBy = that.modifiedBy; + this.createdTime = that.createdTime; + this.modifiedTime = that.modifiedTime; + } + } + + public AtlasSystemAttributes(String createdBy, String modifiedBy, Date createdTime, Date modifiedTime){ + this.createdBy = createdBy; + this.modifiedBy = modifiedBy; + this.createdTime = createdTime; + this.modifiedTime = modifiedTime; + } + + public AtlasSystemAttributes(Map<String, Object> map) { + this(); + + if (map != null) { + this.createdBy = Id.asString(map.get("createdBy")); + this.modifiedBy = Id.asString(map.get("modifiedBy")); + this.createdTime = Id.asDate(map.get("createdTime")); + this.modifiedTime = Id.asDate(map.get("modifiedTime")); + } + } + + public String getCreatedBy(){ + return createdBy; + } + + public void setCreatedBy(String createdBy) { + this.createdBy = createdBy; + } + + public String getModifiedBy(){ + return modifiedBy; + } + + public void setModifiedBy(String modifiedBy) { + this.modifiedBy = modifiedBy; + } + + public Date getCreatedTime(){ + return createdTime; + } + + public void setCreatedTime(Date createdTime) { + this.createdTime = createdTime; + } + + public Date getModifiedTime(){ + return modifiedTime; + } + + public void setModifiedTime(Date modifiedTime) { + this.modifiedTime = modifiedTime; + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + AtlasSystemAttributes obj = (AtlasSystemAttributes) o; + + return Objects.equals(createdBy, obj.createdBy) && + Objects.equals(modifiedBy, obj.modifiedBy) && + Objects.equals(createdTime, obj.createdTime) && + Objects.equals(modifiedTime, obj.modifiedTime); + } + + @Override + public int hashCode() { + return Objects.hash(createdBy, modifiedBy, createdTime, modifiedTime); + } + + + @Override + public String toString() { + return toString(new StringBuilder()).toString(); + } + + public StringBuilder toString(StringBuilder sb) { + if (sb == null) { + sb = new StringBuilder(); + } + + sb.append("AtlasSystemAttributes{") + .append("createdBy=").append(createdBy) + .append(", modifiedBy=").append(modifiedBy) + .append(", createdTime=").append(createdTime) + .append(", modifiedTime=").append(modifiedTime) + .append("}"); + + return sb; + } +} http://git-wip-us.apache.org/repos/asf/atlas/blob/435fe3fb/intg/src/main/java/org/apache/atlas/v1/model/instance/Id.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/v1/model/instance/Id.java b/intg/src/main/java/org/apache/atlas/v1/model/instance/Id.java new file mode 100644 index 0000000..f3087d1 --- /dev/null +++ b/intg/src/main/java/org/apache/atlas/v1/model/instance/Id.java @@ -0,0 +1,270 @@ +/** + * 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.v1.model.instance; + + +import org.apache.atlas.model.typedef.AtlasBaseTypeDef; +import org.codehaus.jackson.annotate.JsonAutoDetect; +import org.codehaus.jackson.annotate.JsonIgnore; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.map.annotate.JsonSerialize; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.text.ParseException; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicLong; + +import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.NONE; +import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.PUBLIC_ONLY; + + +@JsonAutoDetect(getterVisibility=PUBLIC_ONLY, setterVisibility=PUBLIC_ONLY, fieldVisibility=NONE) +@JsonSerialize(include=JsonSerialize.Inclusion.ALWAYS) +@JsonIgnoreProperties(ignoreUnknown=true) +@XmlRootElement +@XmlAccessorType(XmlAccessType.PROPERTY) +public class Id implements Serializable { + private static final long serialVersionUID = 1L; + + @JsonIgnore + private static AtomicLong s_nextId = new AtomicLong(System.nanoTime()); + + public static final String JSON_CLASS_ID = "org.apache.atlas.typesystem.json.InstanceSerialization$_Id"; + + public enum EntityState { ACTIVE, DELETED } + + private String id; + private String typeName; + private int version; + private EntityState state; + + + public Id() { + } + + public Id(Id that) { + if (that != null) { + this.id = that.id; + this.typeName = that.typeName; + this.version = that.version; + this.state = that.state; + } + } + + public Id(String typeName) { + this("" + nextNegativeLong(), 0, typeName); + } + + public Id(String id, int version, String typeName) { + this(id, version, typeName, null); + } + + public Id(long id, int version, String typeName) { + this(id, version, typeName, null); + } + + public Id(long id, int version, String typeName, String state) { + this("" + id, version, typeName, state); + } + + public Id(String id, int version, String typeName, String state) { + this.id = id; + this.typeName = typeName; + this.version = version; + this.state = state == null ? EntityState.ACTIVE : EntityState.valueOf(state.toUpperCase()); + } + + public Id(Map<String, Object> map) { + this(); + + if (map != null) { + this.id = Id.asString(map.get("id")); + this.typeName = Id.asString(map.get("typeName")); + this.version = Id.asInt(map.get("id")); + this.state = Id.asEntityState(map.get("state")); + } + } + + // for serialization backward compatibility + public String getJsonClass() { + return JSON_CLASS_ID; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getTypeName() { + return typeName; + } + + public void setTypeName(String typeName) { + this.typeName = typeName; + } + + public int getVersion() { + return version; + } + + public void setVersion(int version) { + this.version = version; + } + + public EntityState getState() { + return state; + } + + public void setState(EntityState state) { + this.state = state; + } + + @JsonIgnore + public String _getId() { + return id; + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + + if (o == null || getClass() != o.getClass()) { + return false; + } + + Id obj = (Id) o; + + return version == obj.version && + Objects.equals(id, obj.id) && + Objects.equals(typeName, obj.typeName) && + Objects.equals(state, obj.state); + } + + @Override + public int hashCode() { + return Objects.hash(id, typeName, version, state); + } + + + @Override + public String toString() { + return asString(new StringBuilder()).toString(); + } + + public StringBuilder asString(StringBuilder sb) { + if (sb == null) { + sb = new StringBuilder(); + } + + sb.append("Id{") + .append("id=").append(id) + .append(", typeName=").append(typeName) + .append(", version=").append(version) + .append(", state=").append(state) + .append("}"); + + return sb; + } + + private static long nextNegativeLong() { + long ret = s_nextId.getAndDecrement(); + + if (ret > 0) { + ret *= -1; + } else if (ret == 0) { + ret = Long.MIN_VALUE; + } + + return ret; + } + + static String asString(Object val) { + return val == null ? null : val.toString(); + } + + static int asInt(Object val) { + if (val != null) { + if (val instanceof Number) { + return ((Number)val).intValue(); + } + + try { + return Integer.parseInt(val.toString()); + } catch (NumberFormatException excp) { + // ignore + } + } + + return 0; + } + + static Date asDate(Object val) { + if (val != null) { + if (val instanceof Date) { + return (Date) val; + } else if (val instanceof Number) { + return new Date(((Number)val).longValue()); + } + + try { + return AtlasBaseTypeDef.DATE_FORMATTER.parse(val.toString()); + } catch (ParseException excp) { + // ignore + } + } + + return null; + } + + static EntityState asEntityState(Object val) { + if (val != null) { + if (val instanceof EntityState) { + return (EntityState) val; + } + + try { + return EntityState.valueOf(val.toString()); + } catch (Exception excp) { + // ignore + } + } + + return EntityState.ACTIVE; + } + + static Map asMap(Object val) { + return (val instanceof Map) ? ((Map) val) : null; + } + + static List asList(Object val) { + return (val instanceof List) ? ((List) val) : null; + } +} http://git-wip-us.apache.org/repos/asf/atlas/blob/435fe3fb/intg/src/main/java/org/apache/atlas/v1/model/instance/Referenceable.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/v1/model/instance/Referenceable.java b/intg/src/main/java/org/apache/atlas/v1/model/instance/Referenceable.java new file mode 100644 index 0000000..f1d28d1 --- /dev/null +++ b/intg/src/main/java/org/apache/atlas/v1/model/instance/Referenceable.java @@ -0,0 +1,252 @@ +/** + * 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.v1.model.instance; + + + +import org.apache.atlas.model.typedef.AtlasBaseTypeDef; +import org.apache.commons.collections.MapUtils; +import org.codehaus.jackson.annotate.JsonAutoDetect; +import org.codehaus.jackson.annotate.JsonIgnore; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.map.annotate.JsonFilter; +import org.codehaus.jackson.map.annotate.JsonSerialize; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.NONE; +import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.PUBLIC_ONLY; + + +@JsonAutoDetect(getterVisibility=PUBLIC_ONLY, setterVisibility=PUBLIC_ONLY, fieldVisibility=NONE) +@JsonSerialize(include=JsonSerialize.Inclusion.ALWAYS) +@JsonIgnoreProperties(ignoreUnknown=true) +@XmlRootElement +@XmlAccessorType(XmlAccessType.PROPERTY) +public class Referenceable extends Struct implements Serializable { + private static final long serialVersionUID = 1L; + + public static final String JSON_CLASS_REFERENCE = "org.apache.atlas.typesystem.json.InstanceSerialization$_Reference"; + + private Id id; + private Map<String, Struct> traits = new HashMap<>(); + private List<String> traitNames = new ArrayList<>(); + private AtlasSystemAttributes systemAttributes; + + + public Referenceable() { + super(); + } + + public Referenceable(Referenceable that) { + super(that); + + if (that != null) { + this.id = new Id(that.id); + + if (that.traits != null) { + this.traits.putAll(that.traits); + } + + if (that.traitNames != null) { + this.traitNames.addAll(that.traitNames); + } + + this.systemAttributes = new AtlasSystemAttributes(that.systemAttributes); + } + } + + public Referenceable(String typeName, String... traitNames) { + super(typeName); + + this.id = new Id(typeName); + this.systemAttributes = null; + + if (traitNames != null) { + for (String traitName : traitNames) { + this.traitNames.add(traitName); + this.traits.put(traitName, new Struct(traitName)); + } + } + } + + public Referenceable(String typeName, Map<String, Object> values) { + this(new Id(typeName), typeName, values, null, null); + } + + public Referenceable(String guid, String typeName, Map<String, Object> values) { + this(new Id(guid, 0, typeName), typeName, values, null, null, null); + } + + public Referenceable(String guid, String typeName, Map<String, Object> values, AtlasSystemAttributes systemAttributes) { + this(new Id(guid, 0, typeName), typeName, values, systemAttributes, null, null); + } + + public Referenceable(String guid, String typeName, Map<String, Object> values, AtlasSystemAttributes systemAttributes, List<String> traitNames, Map<String, Struct> traits) { + this(new Id(guid, 0, typeName), typeName, values, systemAttributes, traitNames, traits); + } + + public Referenceable(String guid, String typeName, Map<String, Object> values, List<String> traitNames, Map<String, Struct> traits) { + this(new Id(guid, 0, typeName), typeName, values, null, traitNames, traits); + } + + public Referenceable(Id id, String typeName, Map<String, Object> values, List<String> traitNames, Map<String, Struct> traits) { + this(id, typeName, values, null, traitNames, traits); + } + + public Referenceable(Id id, String typeName, Map<String, Object> values, AtlasSystemAttributes systemAttributes, List<String> traitNames, Map<String, Struct> traits) { + super(typeName, values); + + this.id = id; + this.systemAttributes = systemAttributes; + + if (traitNames != null) { + this.traitNames = traitNames; + } + + if (traits != null) { + this.traits = traits; + } + } + + public Referenceable(Map<String, Object> map) { + super(map); + + if (map != null) { + this.id = new Id((Map)map.get("id")); + this.traitNames = Id.asList(map.get("traitNames")); + this.systemAttributes = new AtlasSystemAttributes((Map) map.get("systemAttributes")); + + Map traits = Id.asMap(map.get("traits")); + + if (MapUtils.isNotEmpty(traits)) { + this.traits = new HashMap<>(traits.size()); + + for (Object key : traits.keySet()) { + this.traits.put(Id.asString(key), new Struct(Id.asMap(traits.get(key)))); + } + } + } + } + + + // for serialization backward compatibility + public String getJsonClass() { + return JSON_CLASS_REFERENCE; + } + + public Id getId() { + return id; + } + + public void setId(Id id) { + this.id = id; + } + + public Map<String, Struct> getTraits() { + return traits; + } + + public void setTraits(Map<String, Struct> traits) { + this.traits = traits; + } + + public List<String> getTraitNames() { + return traitNames; + } + + public void setTraitNames(List<String> traitNames) { + this.traitNames = traitNames; + } + + public AtlasSystemAttributes getSystemAttributes() { + return systemAttributes; + } + + public void setSystemAttributes(AtlasSystemAttributes systemAttributes) { + this.systemAttributes = systemAttributes; + } + + @JsonIgnore + public Struct getTrait(String name) { + return traits != null ? traits.get(name) : null; + } + + @JsonIgnore + public String toShortString() { + return String.format("entity[type=%s guid=%s]", getTypeName(), id._getId()); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + + if (o == null || o.getClass() != getClass()) { + return false; + } + + Referenceable obj = (Referenceable)o; + + return Objects.equals(id, obj.id) && + Objects.equals(traits, obj.traits) && + Objects.equals(traitNames, obj.traitNames) && + Objects.equals(systemAttributes, obj.systemAttributes); + } + + @Override + public int hashCode() { + return Objects.hash(id, traits, traitNames, systemAttributes); + } + + + @Override + public StringBuilder toString(StringBuilder sb) { + if (sb == null) { + sb = new StringBuilder(); + } + + sb.append("Referenceable{"); + super.toString(sb); + sb.append(", id="); + if (id != null) { + id.asString(sb); + } + sb.append(", triats={"); + AtlasBaseTypeDef.dumpObjects(this.traits, sb); + sb.append("}, traitNames=["); + AtlasBaseTypeDef.dumpObjects(traitNames, sb); + sb.append("], systemAttributes="); + if (systemAttributes != null) { + systemAttributes.toString(sb); + } + sb.append("}"); + + return sb; + } +} http://git-wip-us.apache.org/repos/asf/atlas/blob/435fe3fb/intg/src/main/java/org/apache/atlas/v1/model/instance/Struct.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/v1/model/instance/Struct.java b/intg/src/main/java/org/apache/atlas/v1/model/instance/Struct.java new file mode 100644 index 0000000..5aebd4b --- /dev/null +++ b/intg/src/main/java/org/apache/atlas/v1/model/instance/Struct.java @@ -0,0 +1,211 @@ +/** + * 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.v1.model.instance; + + +import org.apache.atlas.model.typedef.AtlasBaseTypeDef; +import org.apache.commons.collections.MapUtils; +import org.codehaus.jackson.annotate.JsonAutoDetect; +import org.codehaus.jackson.annotate.JsonIgnore; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.map.annotate.JsonSerialize; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.util.*; + +import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.NONE; +import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.PUBLIC_ONLY; + + +@JsonAutoDetect(getterVisibility=PUBLIC_ONLY, setterVisibility=PUBLIC_ONLY, fieldVisibility=NONE) +@JsonSerialize(include=JsonSerialize.Inclusion.ALWAYS) +@JsonIgnoreProperties(ignoreUnknown=true) +@XmlRootElement +@XmlAccessorType(XmlAccessType.PROPERTY) +public class Struct implements Serializable { + private static final long serialVersionUID = 1L; + + public static final String JSON_CLASS_STRUCT = "org.apache.atlas.typesystem.json.InstanceSerialization$_Struct"; + + private String typeName; + private Map<String, Object> values; + + + public Struct() { + } + + public Struct(Struct that) { + if (that != null) { + this.typeName = that.typeName; + + if (that.values != null) { + this.values = new HashMap<>(that.values); + } + } + } + + public Struct(String typeName) { + this(typeName, null); + } + + public Struct(String typeName, Map<String, Object> values) { + this.typeName = typeName; + this.values = values; + } + + public Struct(Map<String, Object> map) { + this(); + + if (map != null) { + this.typeName = Id.asString(map.get("typeName")); + this.values = Id.asMap(map.get("values")); + + this.normailze(); + } + } + + // for serialization backward compatibility + public String getJsonClass() { + return JSON_CLASS_STRUCT; + } + + public String getTypeName() { + return typeName; + } + + public void setTypeName(String typeName) { + this.typeName = typeName; + } + + public Map<String, Object> getValues() { + return values; + } + + public void setValues(Map<String, Object> values) { + this.values = values; + } + + @JsonIgnore + public Map<String, Object> getValuesMap() { + return values; + } + + @JsonIgnore + public void set(String attrName, Object attrValue) { + if (values == null) { + values = new HashMap<>(); + } + + values.put(attrName, attrValue); + } + + @JsonIgnore + public Object get(String attrName) { + return values != null ? values.get(attrName) : null; + } + + @JsonIgnore + public void setNull(String attrName) { + if (values != null) { + values.remove(attrName); + } + } + + public void normailze() { + if (MapUtils.isEmpty(values)) { + return; + } + + for (Map.Entry<String, Object> entry : values.entrySet()) { + entry.setValue(normalizeAttributeValue(entry.getValue())); + } + } + + private Object normalizeAttributeValue(Object value) { + if (value instanceof Map) { + Map mapValue = (Map) value; + String jsonClass = (String)mapValue.get("jsonClass"); + + if (jsonClass != null) { + if (Id.JSON_CLASS_ID.equals(jsonClass)) { + value = new Id(mapValue); + } else if (Struct.JSON_CLASS_STRUCT.equals(jsonClass)) { + value = new Struct(mapValue); + } else if (Referenceable.JSON_CLASS_REFERENCE.equals(jsonClass)) { + value = new Referenceable(mapValue); + } + } + } else if (value instanceof List) { + List<Object> listValue = (List) value; + List<Object> normalizedValue = new ArrayList<>(listValue.size()); + + for (Object val : listValue) { + normalizedValue.add(normalizeAttributeValue(val)); + } + + value = normalizedValue; + } + + return value; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + + if (o == null || o.getClass() != getClass()) { + return false; + } + + Struct obj = (Struct)o; + + return Objects.equals(typeName, obj.typeName) && + Objects.equals(values, obj.values); + } + + @Override + public int hashCode() { + return Objects.hash(typeName, values); + } + + @Override + public String toString() { + return toString(new StringBuilder()).toString(); + } + + public StringBuilder toString(StringBuilder sb) { + if (sb == null) { + sb = new StringBuilder(); + } + + sb.append("Struct{"); + sb.append("typeName=").append(typeName); + sb.append(", values={"); + AtlasBaseTypeDef.dumpObjects(values, sb); + sb.append("}"); + sb.append("}"); + + return sb; + } +} http://git-wip-us.apache.org/repos/asf/atlas/blob/435fe3fb/intg/src/main/java/org/apache/atlas/v1/model/lineage/DataSetLineageResponse.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/v1/model/lineage/DataSetLineageResponse.java b/intg/src/main/java/org/apache/atlas/v1/model/lineage/DataSetLineageResponse.java new file mode 100644 index 0000000..b073bac --- /dev/null +++ b/intg/src/main/java/org/apache/atlas/v1/model/lineage/DataSetLineageResponse.java @@ -0,0 +1,65 @@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.v1.model.lineage; + +import org.codehaus.jackson.annotate.JsonAutoDetect; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.map.annotate.JsonSerialize; + +import java.util.Objects; + +import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.NONE; +import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.PUBLIC_ONLY; + +@JsonAutoDetect(getterVisibility = PUBLIC_ONLY, setterVisibility = PUBLIC_ONLY, fieldVisibility = NONE) +@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class DataSetLineageResponse extends LineageResponse { + private String tableName; + + public DataSetLineageResponse() { + } + + public DataSetLineageResponse(final DataSetLineageResponse other) { + super(other); + this.tableName = other.tableName; + } + + public String getTableName() { + return tableName; + } + + public void setTableName(final String tableName) { + this.tableName = tableName; + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + final DataSetLineageResponse that = (DataSetLineageResponse) o; + return Objects.equals(tableName, that.tableName); + } + + @Override + public int hashCode() { + + return Objects.hash(super.hashCode(), tableName); + } +} http://git-wip-us.apache.org/repos/asf/atlas/blob/435fe3fb/intg/src/main/java/org/apache/atlas/v1/model/lineage/LineageResponse.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/v1/model/lineage/LineageResponse.java b/intg/src/main/java/org/apache/atlas/v1/model/lineage/LineageResponse.java new file mode 100644 index 0000000..aadbba1 --- /dev/null +++ b/intg/src/main/java/org/apache/atlas/v1/model/lineage/LineageResponse.java @@ -0,0 +1,75 @@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.v1.model.lineage; + +import org.apache.atlas.v1.model.instance.Struct; +import org.codehaus.jackson.annotate.JsonAutoDetect; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.map.annotate.JsonSerialize; + +import java.util.Objects; + +import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.NONE; +import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.PUBLIC_ONLY; + +@JsonAutoDetect(getterVisibility = PUBLIC_ONLY, setterVisibility = PUBLIC_ONLY, fieldVisibility = NONE) +@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class LineageResponse { + private String requestId; + private Struct results; + + public LineageResponse() { + } + + public LineageResponse(final LineageResponse other) { + this.requestId = other.requestId; + this.results = other.results; + } + + public Struct getResults() { + return results; + } + + public void setResults(final Struct results) { + this.results = results; + } + + public String getRequestId() { + return requestId; + } + + public void setRequestId(final String requestId) { + this.requestId = requestId; + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + final LineageResponse that = (LineageResponse) o; + return Objects.equals(requestId, that.requestId) && + Objects.equals(results, that.results); + } + + @Override + public int hashCode() { + + return Objects.hash(requestId, results); + } +} http://git-wip-us.apache.org/repos/asf/atlas/blob/435fe3fb/intg/src/main/java/org/apache/atlas/v1/model/lineage/SchemaResponse.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/v1/model/lineage/SchemaResponse.java b/intg/src/main/java/org/apache/atlas/v1/model/lineage/SchemaResponse.java new file mode 100644 index 0000000..e17553e --- /dev/null +++ b/intg/src/main/java/org/apache/atlas/v1/model/lineage/SchemaResponse.java @@ -0,0 +1,116 @@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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.v1.model.lineage; + +import org.apache.atlas.v1.model.typedef.ClassTypeDefinition; +import org.codehaus.jackson.annotate.JsonAutoDetect; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.map.annotate.JsonSerialize; + +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.NONE; +import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.PUBLIC_ONLY; + +@JsonAutoDetect(getterVisibility = PUBLIC_ONLY, setterVisibility = PUBLIC_ONLY, fieldVisibility = NONE) +@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class SchemaResponse { + private String requestId; + private String tableName; + private SchemaDetails results; + + public SchemaResponse() { + } + + public String getTableName() { + return tableName; + } + + public void setTableName(final String tableName) { + this.tableName = tableName; + } + + public String getRequestId() { + return requestId; + } + + public void setRequestId(final String requestId) { + this.requestId = requestId; + } + + public SchemaDetails getResults() { + return results; + } + + public void setResults(final SchemaDetails results) { + this.results = results; + } + + /** + * Represents the column schema for a given hive table + */ + @JsonAutoDetect(getterVisibility = PUBLIC_ONLY, setterVisibility = PUBLIC_ONLY, fieldVisibility = NONE) + @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) + @JsonIgnoreProperties(ignoreUnknown = true) + public static class SchemaDetails { + private ClassTypeDefinition dataType; // Data type of the (hive) columns + private List<Map<String, Object>> rows; // Column instances for the given table + + public SchemaDetails() { + } + + public SchemaDetails(final SchemaDetails other) { + this.dataType = other.dataType; + this.rows = other.rows; + } + + public ClassTypeDefinition getDataType() { + return dataType; + } + + public void setDataType(final ClassTypeDefinition dataType) { + this.dataType = dataType; + } + + public List<Map<String, Object>> getRows() { + return rows; + } + + public void setRows(final List<Map<String, Object>> rows) { + this.rows = rows; + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + final SchemaDetails that = (SchemaDetails) o; + return Objects.equals(dataType, that.dataType) && + Objects.equals(rows, that.rows); + } + + @Override + public int hashCode() { + + return Objects.hash(dataType, rows); + } + } +} http://git-wip-us.apache.org/repos/asf/atlas/blob/435fe3fb/intg/src/main/java/org/apache/atlas/v1/model/notification/EntityNotificationV1.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/v1/model/notification/EntityNotificationV1.java b/intg/src/main/java/org/apache/atlas/v1/model/notification/EntityNotificationV1.java new file mode 100644 index 0000000..549dbe3 --- /dev/null +++ b/intg/src/main/java/org/apache/atlas/v1/model/notification/EntityNotificationV1.java @@ -0,0 +1,231 @@ +/** + * 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.v1.model.notification; + +import org.apache.atlas.model.notification.EntityNotification; +import org.apache.atlas.model.typedef.AtlasBaseTypeDef; +import org.apache.atlas.v1.model.instance.Referenceable; +import org.apache.atlas.v1.model.instance.Struct; +import org.apache.atlas.type.AtlasClassificationType; +import org.apache.atlas.type.AtlasTypeRegistry; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.codehaus.jackson.annotate.JsonAutoDetect; +import org.codehaus.jackson.annotate.JsonIgnore; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.map.annotate.JsonSerialize; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.NONE; +import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.PUBLIC_ONLY; + +/** + * Entity notification + */ +@JsonAutoDetect(getterVisibility=PUBLIC_ONLY, setterVisibility=PUBLIC_ONLY, fieldVisibility=NONE) +@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown=true) +@XmlRootElement +@XmlAccessorType(XmlAccessType.PROPERTY) +public class EntityNotificationV1 extends EntityNotification implements Serializable { + private static final long serialVersionUID = 1L; + + public enum OperationType { + ENTITY_CREATE, + ENTITY_UPDATE, + ENTITY_DELETE, + TRAIT_ADD, + TRAIT_DELETE, + TRAIT_UPDATE + } + + private Referenceable entity; + private OperationType operationType; + private List<Struct> traits; + + + // ----- Constructors ------------------------------------------------------ + + /** + * No-arg constructor for serialization. + */ + public EntityNotificationV1() { + } + + /** + * Construct an EntityNotificationV1. + * + * @param entity the entity subject of the notification + * @param operationType the type of operation that caused the notification + * @param traits the traits for the given entity + */ + public EntityNotificationV1(Referenceable entity, OperationType operationType, List<Struct> traits) { + this.entity = entity; + this.operationType = operationType; + this.traits = traits; + } + + /** + * Construct an EntityNotificationV1. + * + * @param entity the entity subject of the notification + * @param operationType the type of operation that caused the notification + * @param typeRegistry the Atlas type system + */ + public EntityNotificationV1(Referenceable entity, OperationType operationType, AtlasTypeRegistry typeRegistry) { + this(entity, operationType, getAllTraits(entity, typeRegistry)); + } + + public Referenceable getEntity() { + return entity; + } + + public void setEntity(Referenceable entity) { + this.entity = entity; + } + + public OperationType getOperationType() { + return operationType; + } + + public void setOperationType(OperationType operationType) { + this.operationType = operationType; + } + + public List<Struct> getTraits() { + return traits; + } + + public void setTraits(List<Struct> traits) { + this.traits = traits; + } + + @JsonIgnore + public List<Struct> getAllTraits() { + return traits; + } + + public void normalize() { + super.normalize(); + + if (entity != null) { + entity.normailze(); + } + + if (traits != null) { + for (Struct trait : traits) { + if (trait != null) { + trait.normailze(); + } + } + } + } + + // ----- Object overrides -------------------------------------------------- + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + EntityNotificationV1 that = (EntityNotificationV1) o; + return Objects.equals(entity, that.entity) && + operationType == that.operationType && + Objects.equals(traits, that.traits); + } + + @Override + public int hashCode() { + return Objects.hash(entity, operationType, traits); + } + + @Override + public StringBuilder toString(StringBuilder sb) { + if (sb == null) { + sb = new StringBuilder(); + } + + sb.append("EntityNotificationV1{"); + super.toString(sb); + sb.append(", entity="); + if (entity != null) { + entity.toString(sb); + } else { + sb.append(entity); + } + sb.append(", operationType=").append(operationType); + sb.append(", traits=["); + AtlasBaseTypeDef.dumpObjects(traits, sb); + sb.append("]"); + sb.append("}"); + + return sb; + } + + + // ----- helper methods ---------------------------------------------------- + + private static List<Struct> getAllTraits(Referenceable entityDefinition, AtlasTypeRegistry typeRegistry) { + List<Struct> ret = new LinkedList<>(); + + for (String traitName : entityDefinition.getTraitNames()) { + Struct trait = entityDefinition.getTrait(traitName); + AtlasClassificationType traitType = typeRegistry.getClassificationTypeByName(traitName); + Set<String> superTypeNames = traitType != null ? traitType.getAllSuperTypes() : null; + + ret.add(trait); + + if (CollectionUtils.isNotEmpty(superTypeNames)) { + for (String superTypeName : superTypeNames) { + Struct superTypeTrait = new Struct(superTypeName); + + if (MapUtils.isNotEmpty(trait.getValues())) { + AtlasClassificationType superType = typeRegistry.getClassificationTypeByName(superTypeName); + + if (superType != null && MapUtils.isNotEmpty(superType.getAllAttributes())) { + Map<String, Object> superTypeTraitAttributes = new HashMap<>(); + + for (Map.Entry<String, Object> attrEntry : trait.getValues().entrySet()) { + String attrName = attrEntry.getKey(); + + if (superType.getAllAttributes().containsKey(attrName)) { + superTypeTraitAttributes.put(attrName, attrEntry.getValue()); + } + } + + superTypeTrait.setValues(superTypeTraitAttributes); + } + } + + ret.add(superTypeTrait); + } + } + } + + return ret; + } +}
