Repository: atlas
Updated Branches:
  refs/heads/master a3374c747 -> 48b2eaa99


ATLAS-2457: updates to support time-boundary in AtlasClassification associations


Project: http://git-wip-us.apache.org/repos/asf/atlas/repo
Commit: http://git-wip-us.apache.org/repos/asf/atlas/commit/48b2eaa9
Tree: http://git-wip-us.apache.org/repos/asf/atlas/tree/48b2eaa9
Diff: http://git-wip-us.apache.org/repos/asf/atlas/diff/48b2eaa9

Branch: refs/heads/master
Commit: 48b2eaa99f91ec615f67fcde3183b262c765d698
Parents: a3374c7
Author: Madhan Neethiraj <mad...@apache.org>
Authored: Wed Feb 21 13:53:44 2018 -0800
Committer: Madhan Neethiraj <mad...@apache.org>
Committed: Wed Feb 21 18:04:59 2018 -0800

----------------------------------------------------------------------
 .../org/apache/atlas/repository/Constants.java  |   7 +-
 .../org/apache/atlas/model/TimeBoundary.java    | 120 +++++++++++++++++++
 .../model/instance/AtlasClassification.java     |  19 ++-
 .../store/graph/v1/EntityGraphMapper.java       |   8 +-
 .../store/graph/v1/EntityGraphRetriever.java    |  13 +-
 .../integration/EntityV2JerseyResourceIT.java   |  45 ++++++-
 6 files changed, 202 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/atlas/blob/48b2eaa9/common/src/main/java/org/apache/atlas/repository/Constants.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/atlas/repository/Constants.java 
b/common/src/main/java/org/apache/atlas/repository/Constants.java
index ae52880..b6c639a 100644
--- a/common/src/main/java/org/apache/atlas/repository/Constants.java
+++ b/common/src/main/java/org/apache/atlas/repository/Constants.java
@@ -116,8 +116,11 @@ public final class Constants {
     public static final String ATTRIBUTE_NAME_VERSION  = "version";
     public static final String TEMP_STRUCT_NAME_PREFIX = 
"__tempQueryResultStruct";
 
-    public static final String CLASSIFICATION_ENTITY_GUID = 
INTERNAL_PROPERTY_KEY_PREFIX + "entityGuid";
-    public static final String CLASSIFICATION_PROPAGATE_KEY = 
INTERNAL_PROPERTY_KEY_PREFIX + "propagate";
+    public static final String CLASSIFICATION_ENTITY_GUID                   = 
INTERNAL_PROPERTY_KEY_PREFIX + "entityGuid";
+    public static final String CLASSIFICATION_PROPAGATE_KEY                 = 
INTERNAL_PROPERTY_KEY_PREFIX + "propagate";
+    public static final String CLASSIFICATION_VALIDITY_PERIOD_STARTTIME_KEY = 
INTERNAL_PROPERTY_KEY_PREFIX + "vp_startTime";
+    public static final String CLASSIFICATION_VALIDITY_PERIOD_ENDTIME_KEY   = 
INTERNAL_PROPERTY_KEY_PREFIX + "vp_endTime";
+    public static final String CLASSIFICATION_VALIDITY_PERIOD_TIMEZONE_KEY  = 
INTERNAL_PROPERTY_KEY_PREFIX + "vp_timeZone";
 
     private Constants() {
     }

http://git-wip-us.apache.org/repos/asf/atlas/blob/48b2eaa9/intg/src/main/java/org/apache/atlas/model/TimeBoundary.java
----------------------------------------------------------------------
diff --git a/intg/src/main/java/org/apache/atlas/model/TimeBoundary.java 
b/intg/src/main/java/org/apache/atlas/model/TimeBoundary.java
new file mode 100644
index 0000000..882a33c
--- /dev/null
+++ b/intg/src/main/java/org/apache/atlas/model/TimeBoundary.java
@@ -0,0 +1,120 @@
+/**
+ * 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;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.databind.annotation.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.Objects;
+
+import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE;
+import static 
com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.PUBLIC_ONLY;
+
+/**
+ * Captures time-boundary details
+ */
+@JsonAutoDetect(getterVisibility=PUBLIC_ONLY, setterVisibility=PUBLIC_ONLY, 
fieldVisibility=NONE)
+@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
+@JsonIgnoreProperties(ignoreUnknown=true)
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.PROPERTY)
+public class TimeBoundary implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    public static final String TIME_FORMAT = "yyyy/MM/dd HH:mm:ss";
+
+    private String startTime;
+    private String endTime;
+    private String timeZone; // null for local-time; or a valid ID for 
TimeZone.getTimeZone(id)
+
+    public TimeBoundary() {
+        this(null, null, null);
+    }
+
+    public TimeBoundary(String startTime) {
+        this(startTime, null, null);
+    }
+
+    public TimeBoundary(String startTime, String endTime) {
+        this(startTime, endTime, null);
+    }
+
+    public TimeBoundary(String startTime, String endTime, String timeZone) {
+        this.startTime = startTime;
+        this.endTime   = endTime;
+        this.timeZone  = timeZone;
+    }
+
+    public String getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(String startTime) {
+        this.startTime = startTime;
+    }
+
+    public String getEndTime() {
+        return endTime;
+    }
+
+    public void setEndTime(String endTime) {
+        this.endTime = endTime;
+    }
+
+    public String getTimeZone() {
+        return timeZone;
+    }
+
+    public void setTimeZone(String timeZone) {
+        this.timeZone = timeZone;
+    }
+
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) { return true; }
+        if (o == null || getClass() != o.getClass()) { return false; }
+        TimeBoundary that = (TimeBoundary) o;
+        return Objects.equals(startTime, that.startTime) &&
+               Objects.equals(endTime, that.endTime) &&
+               Objects.equals(timeZone, that.timeZone);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(startTime, endTime, timeZone);
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder("TimeBoundary{");
+
+        sb.append("startTime='").append(startTime)
+          .append("; endTime='").append(endTime)
+          .append("; timeZone='").append(timeZone)
+          .append('}');
+
+        return sb.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/atlas/blob/48b2eaa9/intg/src/main/java/org/apache/atlas/model/instance/AtlasClassification.java
----------------------------------------------------------------------
diff --git 
a/intg/src/main/java/org/apache/atlas/model/instance/AtlasClassification.java 
b/intg/src/main/java/org/apache/atlas/model/instance/AtlasClassification.java
index a499f79..3d2ecef 100644
--- 
a/intg/src/main/java/org/apache/atlas/model/instance/AtlasClassification.java
+++ 
b/intg/src/main/java/org/apache/atlas/model/instance/AtlasClassification.java
@@ -34,6 +34,7 @@ import javax.xml.bind.annotation.XmlSeeAlso;
 
 import org.apache.atlas.model.PList;
 import org.apache.atlas.model.SearchFilter.SortType;
+import org.apache.atlas.model.TimeBoundary;
 
 import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE;
 import static 
com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.PUBLIC_ONLY;
@@ -50,8 +51,10 @@ import static 
com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.PUBLIC_
 public class AtlasClassification extends AtlasStruct implements Serializable {
     private static final long serialVersionUID = 1L;
 
-    private String  entityGuid = null;
-    private boolean propagate  = true;
+    private String       entityGuid     = null;
+    private boolean      propagate      = true;
+    private TimeBoundary validityPeriod = null;
+
 
     public AtlasClassification() {
         this(null, null);
@@ -96,6 +99,14 @@ public class AtlasClassification extends AtlasStruct 
implements Serializable {
         this.propagate = propagate;
     }
 
+    public TimeBoundary getValidityPeriod() {
+        return validityPeriod;
+    }
+
+    public void setValidityPeriod(TimeBoundary validityPeriod) {
+        this.validityPeriod = validityPeriod;
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) { return true; }
@@ -103,7 +114,8 @@ public class AtlasClassification extends AtlasStruct 
implements Serializable {
         if (!super.equals(o)) { return false; }
         AtlasClassification that = (AtlasClassification) o;
         return propagate == that.propagate &&
-               Objects.equals(entityGuid, that.entityGuid);
+               Objects.equals(entityGuid, that.entityGuid) &&
+               Objects.equals(validityPeriod, that.validityPeriod);
     }
 
     @Override
@@ -117,6 +129,7 @@ public class AtlasClassification extends AtlasStruct 
implements Serializable {
         super.toString(sb);
         sb.append("entityGuid='").append(entityGuid).append('\'');
         sb.append(", propagate=").append(propagate);
+        sb.append(", validityPeriod=").append(validityPeriod);
         sb.append('}');
         return sb.toString();
     }

http://git-wip-us.apache.org/repos/asf/atlas/blob/48b2eaa9/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphMapper.java
----------------------------------------------------------------------
diff --git 
a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphMapper.java
 
b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphMapper.java
index 0224bf0..80c64b1 100644
--- 
a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphMapper.java
+++ 
b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphMapper.java
@@ -22,6 +22,7 @@ import org.apache.atlas.AtlasErrorCode;
 import org.apache.atlas.AtlasException;
 import org.apache.atlas.RequestContextV1;
 import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.TimeBoundary;
 import org.apache.atlas.model.TypeCategory;
 import org.apache.atlas.model.instance.AtlasClassification;
 import org.apache.atlas.model.instance.AtlasEntity;
@@ -53,7 +54,6 @@ import 
org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdg
 import org.apache.atlas.type.AtlasType;
 import org.apache.atlas.type.AtlasTypeRegistry;
 import org.apache.atlas.type.AtlasTypeUtil;
-import org.apache.atlas.util.AtlasGremlinQueryProvider;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.IteratorUtils;
 import org.apache.commons.collections.MapUtils;
@@ -1592,6 +1592,12 @@ public class EntityGraphMapper {
                                         AtlasEntityType entityType, 
AtlasVertex parentInstanceVertex, AtlasVertex traitInstanceVertex)
                                         throws AtlasBaseException {
 
+        TimeBoundary validityPeriod = classification.getValidityPeriod();
+
+        AtlasGraphUtilsV1.setProperty(traitInstanceVertex, 
Constants.CLASSIFICATION_VALIDITY_PERIOD_STARTTIME_KEY, validityPeriod != null 
? validityPeriod.getStartTime() : null);
+        AtlasGraphUtilsV1.setProperty(traitInstanceVertex, 
Constants.CLASSIFICATION_VALIDITY_PERIOD_ENDTIME_KEY, validityPeriod != null ? 
validityPeriod.getEndTime() : null);
+        AtlasGraphUtilsV1.setProperty(traitInstanceVertex, 
Constants.CLASSIFICATION_VALIDITY_PERIOD_TIMEZONE_KEY, validityPeriod != null ? 
validityPeriod.getTimeZone() : null);
+
         // map all the attributes to this newly created AtlasVertex
         mapAttributes(classification, traitInstanceVertex, operation, context);
 

http://git-wip-us.apache.org/repos/asf/atlas/blob/48b2eaa9/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphRetriever.java
----------------------------------------------------------------------
diff --git 
a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphRetriever.java
 
b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphRetriever.java
index d01fb9f..45c7d39 100644
--- 
a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphRetriever.java
+++ 
b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphRetriever.java
@@ -19,6 +19,7 @@ package org.apache.atlas.repository.store.graph.v1;
 
 import org.apache.atlas.AtlasErrorCode;
 import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.TimeBoundary;
 import org.apache.atlas.model.instance.AtlasClassification;
 import org.apache.atlas.model.instance.AtlasEntity;
 import org.apache.atlas.model.instance.AtlasEntity.AtlasEntitiesWithExtInfo;
@@ -68,9 +69,7 @@ import java.util.Map;
 import java.util.Set;
 
 import static org.apache.atlas.model.typedef.AtlasBaseTypeDef.*;
-import static org.apache.atlas.repository.Constants.CLASSIFICATION_ENTITY_GUID;
-import static 
org.apache.atlas.repository.Constants.CLASSIFICATION_PROPAGATE_KEY;
-import static 
org.apache.atlas.repository.Constants.PROPAGATED_TRAIT_NAMES_PROPERTY_KEY;
+import static org.apache.atlas.repository.Constants.*;
 import static org.apache.atlas.repository.graph.GraphHelper.EDGE_LABEL_PREFIX;
 import static org.apache.atlas.repository.graph.GraphHelper.edgeExists;
 import static 
org.apache.atlas.repository.graph.GraphHelper.getAdjacentEdgesByLabel;
@@ -219,6 +218,14 @@ public final class EntityGraphRetriever {
         ret.setEntityGuid(AtlasGraphUtilsV1.getProperty(classificationVertex, 
CLASSIFICATION_ENTITY_GUID, String.class));
         ret.setPropagate(AtlasGraphUtilsV1.getProperty(classificationVertex, 
CLASSIFICATION_PROPAGATE_KEY, Boolean.class));
 
+        String vpStartTime = 
AtlasGraphUtilsV1.getProperty(classificationVertex, 
CLASSIFICATION_VALIDITY_PERIOD_STARTTIME_KEY, String.class);
+        String vpEndTime   = 
AtlasGraphUtilsV1.getProperty(classificationVertex, 
CLASSIFICATION_VALIDITY_PERIOD_ENDTIME_KEY, String.class);
+        String vpTimeZone  = 
AtlasGraphUtilsV1.getProperty(classificationVertex, 
CLASSIFICATION_VALIDITY_PERIOD_TIMEZONE_KEY, String.class);
+
+        if (vpStartTime != null || vpEndTime != null || vpTimeZone != null) {
+            ret.setValidityPeriod(new TimeBoundary(vpStartTime, vpEndTime, 
vpTimeZone));
+        }
+
         mapAttributes(classificationVertex, ret, null);
 
         return ret;

http://git-wip-us.apache.org/repos/asf/atlas/blob/48b2eaa9/webapp/src/test/java/org/apache/atlas/web/integration/EntityV2JerseyResourceIT.java
----------------------------------------------------------------------
diff --git 
a/webapp/src/test/java/org/apache/atlas/web/integration/EntityV2JerseyResourceIT.java
 
b/webapp/src/test/java/org/apache/atlas/web/integration/EntityV2JerseyResourceIT.java
index dabb2ef..1d666a6 100755
--- 
a/webapp/src/test/java/org/apache/atlas/web/integration/EntityV2JerseyResourceIT.java
+++ 
b/webapp/src/test/java/org/apache/atlas/web/integration/EntityV2JerseyResourceIT.java
@@ -24,6 +24,7 @@ import com.sun.jersey.api.client.ClientResponse;
 import org.apache.atlas.AtlasClient;
 import org.apache.atlas.AtlasServiceException;
 import org.apache.atlas.EntityAuditEvent;
+import org.apache.atlas.model.TimeBoundary;
 import org.apache.atlas.model.instance.AtlasClassification;
 import 
org.apache.atlas.model.instance.AtlasClassification.AtlasClassifications;
 import org.apache.atlas.model.instance.AtlasEntity;
@@ -38,7 +39,7 @@ import org.apache.atlas.model.typedef.AtlasTypesDef;
 import org.apache.atlas.type.AtlasTypeUtil;
 import org.apache.atlas.v1.typesystem.types.utils.TypesUtil;
 import org.apache.commons.lang.RandomStringUtils;
-import org.joda.time.DateTime;
+import org.apache.hadoop.util.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.Assert;
@@ -448,6 +449,48 @@ public class EntityV2JerseyResourceIT extends 
BaseResourceIT {
         assertEntityAudit(createHiveTable().getGuid(), 
EntityAuditEvent.EntityAuditAction.TAG_ADD);
     }
 
+    @Test(dependsOnMethods = "testGetTraitNames")
+    public void testAddTraitWithValidityPeriod() throws Exception {
+        traitName = "PII_Trait" + randomString();
+
+        AtlasClassificationDef piiTrait = 
AtlasTypeUtil.createTraitTypeDef(traitName, Collections.<String>emptySet());
+        AtlasTypesDef          typesDef = new 
AtlasTypesDef(Collections.emptyList(), Collections.emptyList(), 
Collections.singletonList(piiTrait), Collections.emptyList());
+
+        createType(typesDef);
+
+        String              tableGuid      = createHiveTable().getGuid();
+        AtlasClassification classification = new 
AtlasClassification(piiTrait.getName());
+        TimeBoundary        validityPeriod = new TimeBoundary("2018/03/01 
00:00:00", "2018/04/01 00:00:00", "GMT");
+
+        classification.setEntityGuid(tableGuid);
+        classification.setValidityPeriod(validityPeriod);
+
+        atlasClientV2.addClassifications(tableGuid, 
Collections.singletonList(classification));
+
+        assertEntityAudit(tableGuid, 
EntityAuditEvent.EntityAuditAction.TAG_ADD);
+
+        AtlasClassifications classifications = 
atlasClientV2.getClassifications(tableGuid);
+
+        assertNotNull(classifications);
+        assertNotNull(classifications.getList());
+        assertTrue(classifications.getList().size() > 1);
+
+        boolean foundClassification = false;
+        for (AtlasClassification entityClassification : 
classifications.getList()) {
+            if 
(StringUtils.equalsIgnoreCase(entityClassification.getTypeName(), 
piiTrait.getName())) {
+                foundClassification = true;
+
+                assertEquals(entityClassification.getTypeName(), 
piiTrait.getName());
+                assertEquals(entityClassification.getValidityPeriod(), 
validityPeriod);
+                assertEquals(entityClassification, classification);
+
+                break;
+            }
+        }
+
+        assertTrue(foundClassification, "classification '" + 
piiTrait.getName() + "' is missing for entity '" + tableGuid + "'");
+    }
+
     @Test(dependsOnMethods = "testSubmitEntity")
     public void testGetTraitDefinitionForEntity() throws Exception{
         traitName = "PII_Trait" + randomString();

Reply via email to