Commit 48b2eaa9 by Madhan Neethiraj

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

parent a3374c74
......@@ -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() {
}
......
/**
* 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();
}
}
......@@ -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();
}
......
......@@ -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);
......
......@@ -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;
......
......@@ -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();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment