Commit 774975c9 by Vimal Committed by Madhan Neethiraj

ATLAS-916: Return System Attributes in get entity definition

parent 95083cb0
...@@ -138,5 +138,11 @@ public class DefaultPropertyMapper implements PropertyMapper { ...@@ -138,5 +138,11 @@ public class DefaultPropertyMapper implements PropertyMapper {
m_qualifiedToCleanMap.put(Constants.STATE_PROPERTY_KEY, "state"); m_qualifiedToCleanMap.put(Constants.STATE_PROPERTY_KEY, "state");
m_cleanToQualifiedMap.put("state", Constants.STATE_PROPERTY_KEY); m_cleanToQualifiedMap.put("state", Constants.STATE_PROPERTY_KEY);
m_qualifiedToCleanMap.put(Constants.CREATED_BY_KEY, "created_by");
m_cleanToQualifiedMap.put("created_by", Constants.CREATED_BY_KEY);
m_qualifiedToCleanMap.put(Constants.MODIFIED_BY_KEY, "modified_by");
m_cleanToQualifiedMap.put("modified_by", Constants.MODIFIED_BY_KEY);
} }
} }
...@@ -63,6 +63,8 @@ public final class Constants { ...@@ -63,6 +63,8 @@ public final class Constants {
public static final String VERSION_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "version"; public static final String VERSION_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "version";
public static final String STATE_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "state"; public static final String STATE_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "state";
public static final String CREATED_BY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "createdBy";
public static final String MODIFIED_BY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "modifiedBy";
public static final String TIMESTAMP_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "timestamp"; public static final String TIMESTAMP_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "timestamp";
......
...@@ -9,6 +9,7 @@ ATLAS-1060 Add composite indexes for exact match performance improvements for al ...@@ -9,6 +9,7 @@ ATLAS-1060 Add composite indexes for exact match performance improvements for al
ATLAS-1127 Modify creation and modification timestamps to Date instead of Long(sumasai) ATLAS-1127 Modify creation and modification timestamps to Date instead of Long(sumasai)
ALL CHANGES: ALL CHANGES:
ATLAS-916 Return System Attributes in get entity definition (svimal2106)
ATLAS-1242 update TypesResource API implementation to use new v2 TypesREST API ATLAS-1242 update TypesResource API implementation to use new v2 TypesREST API
ATLAS-1306 bootstrap type-load ignores model file contents if a type in the file already exists ATLAS-1306 bootstrap type-load ignores model file contents if a type in the file already exists
ATLAS-1299 The project org.apache.atlas:atlas-hbase-client-shaded - build error (shwethags) ATLAS-1299 The project org.apache.atlas:atlas-hbase-client-shaded - build error (shwethags)
......
...@@ -397,6 +397,7 @@ public abstract class DeleteHandler { ...@@ -397,6 +397,7 @@ public abstract class DeleteHandler {
RequestContext requestContext = RequestContext.get(); RequestContext requestContext = RequestContext.get();
GraphHelper.setProperty(outVertex, Constants.MODIFICATION_TIMESTAMP_PROPERTY_KEY, GraphHelper.setProperty(outVertex, Constants.MODIFICATION_TIMESTAMP_PROPERTY_KEY,
requestContext.getRequestTime()); requestContext.getRequestTime());
GraphHelper.setProperty(outVertex, Constants.MODIFIED_BY_KEY, requestContext.getUser());
requestContext.recordEntityUpdate(outId); requestContext.recordEntityUpdate(outId);
} }
} }
......
...@@ -238,6 +238,7 @@ public class GraphBackedMetadataRepository implements MetadataRepository { ...@@ -238,6 +238,7 @@ public class GraphBackedMetadataRepository implements MetadataRepository {
GraphHelper.addProperty(instanceVertex, Constants.TRAIT_NAMES_PROPERTY_KEY, traitName); GraphHelper.addProperty(instanceVertex, Constants.TRAIT_NAMES_PROPERTY_KEY, traitName);
GraphHelper.setProperty(instanceVertex, Constants.MODIFICATION_TIMESTAMP_PROPERTY_KEY, GraphHelper.setProperty(instanceVertex, Constants.MODIFICATION_TIMESTAMP_PROPERTY_KEY,
RequestContext.get().getRequestTime()); RequestContext.get().getRequestTime());
GraphHelper.setProperty(instanceVertex, Constants.MODIFIED_BY_KEY, RequestContext.get().getUser());
} catch (RepositoryException e) { } catch (RepositoryException e) {
throw e; throw e;
...@@ -293,6 +294,7 @@ public class GraphBackedMetadataRepository implements MetadataRepository { ...@@ -293,6 +294,7 @@ public class GraphBackedMetadataRepository implements MetadataRepository {
} }
GraphHelper.setProperty(instanceVertex, Constants.MODIFICATION_TIMESTAMP_PROPERTY_KEY, GraphHelper.setProperty(instanceVertex, Constants.MODIFICATION_TIMESTAMP_PROPERTY_KEY,
RequestContext.get().getRequestTime()); RequestContext.get().getRequestTime());
GraphHelper.setProperty(instanceVertex, Constants.MODIFIED_BY_KEY, RequestContext.get().getUser());
} }
@Override @Override
......
...@@ -88,7 +88,7 @@ import static org.apache.atlas.model.typedef.AtlasBaseTypeDef.ATLAS_TYPE_STRING; ...@@ -88,7 +88,7 @@ import static org.apache.atlas.model.typedef.AtlasBaseTypeDef.ATLAS_TYPE_STRING;
/** /**
* Adds index for properties of a given type when its added before any instances are added. * Adds index for properties of a given type when its added before any instances are added.
*/ */
public class GraphBackedSearchIndexer implements SearchIndexer, ActiveStateChangeHandler, public class GraphBackedSearchIndexer implements SearchIndexer, ActiveStateChangeHandler,
TypeDefChangeListener { TypeDefChangeListener {
private static final Logger LOG = LoggerFactory.getLogger(GraphBackedSearchIndexer.class); private static final Logger LOG = LoggerFactory.getLogger(GraphBackedSearchIndexer.class);
...@@ -154,17 +154,26 @@ public class GraphBackedSearchIndexer implements SearchIndexer, ActiveStateChang ...@@ -154,17 +154,26 @@ public class GraphBackedSearchIndexer implements SearchIndexer, ActiveStateChang
createIndexes(management, Constants.GUID_PROPERTY_KEY, String.class, true, createIndexes(management, Constants.GUID_PROPERTY_KEY, String.class, true,
AtlasCardinality.SINGLE, true, true); AtlasCardinality.SINGLE, true, true);
// create a composite index for entity creation timestamp // Add creation_timestamp property to Vertex Index (mixed index)
createIndexes(management, Constants.TIMESTAMP_PROPERTY_KEY, Long.class, false, AtlasCardinality.SINGLE, true, true); createIndexes(management, Constants.TIMESTAMP_PROPERTY_KEY, Long.class, false, AtlasCardinality.SINGLE, false, false);
// Add modification_timestamp property to Vertex Index (mixed index)
createIndexes(management, Constants.MODIFICATION_TIMESTAMP_PROPERTY_KEY, Long.class, false,
AtlasCardinality.SINGLE, false, false);
// create a mixed index for entity state. Set systemProperty flag deliberately to false // create a mixed index for entity state. Set systemProperty flag deliberately to false
// so that it doesnt create a composite index which has issues with // so that it doesnt create a composite index which has issues with
// titan 0.5.4 - Refer https://groups.google.com/forum/#!searchin/aureliusgraphs/hemanth/aureliusgraphs/bx7T843mzXU/fjAsclx7GAAJ // titan 0.5.4 - Refer https://groups.google.com/forum/#!searchin/aureliusgraphs/hemanth/aureliusgraphs/bx7T843mzXU/fjAsclx7GAAJ
createIndexes(management, Constants.STATE_PROPERTY_KEY, String.class, false, AtlasCardinality.SINGLE, false, false); createIndexes(management, Constants.STATE_PROPERTY_KEY, String.class, false, AtlasCardinality.SINGLE, false, false);
// create a composite index for entity modification timestamp // Create a composite and mixed index for created by property
createIndexes(management, Constants.MODIFICATION_TIMESTAMP_PROPERTY_KEY, Long.class, false, createIndexes(management, Constants.CREATED_BY_KEY, String.class, false,
AtlasCardinality.SINGLE, false, false); AtlasCardinality.SINGLE, true, true);
// Create a composite and mixed index for modified by property
createIndexes(management, Constants.MODIFIED_BY_KEY, String.class, false,
AtlasCardinality.SINGLE, true, true);
// create a composite and mixed index for type since it can be combined with other keys // create a composite and mixed index for type since it can be combined with other keys
createIndexes(management, Constants.ENTITY_TYPE_PROPERTY_KEY, String.class, false, AtlasCardinality.SINGLE, createIndexes(management, Constants.ENTITY_TYPE_PROPERTY_KEY, String.class, false, AtlasCardinality.SINGLE,
......
...@@ -27,6 +27,7 @@ import java.util.List; ...@@ -27,6 +27,7 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.Stack; import java.util.Stack;
import java.util.UUID; import java.util.UUID;
import java.util.Date;
import org.apache.atlas.ApplicationProperties; import org.apache.atlas.ApplicationProperties;
import org.apache.atlas.AtlasException; import org.apache.atlas.AtlasException;
...@@ -159,6 +160,8 @@ public final class GraphHelper { ...@@ -159,6 +160,8 @@ public final class GraphHelper {
setProperty(vertexWithoutIdentity, Constants.MODIFICATION_TIMESTAMP_PROPERTY_KEY, setProperty(vertexWithoutIdentity, Constants.MODIFICATION_TIMESTAMP_PROPERTY_KEY,
RequestContext.get().getRequestTime()); RequestContext.get().getRequestTime());
setProperty(vertexWithoutIdentity, Constants.CREATED_BY_KEY, RequestContext.get().getUser());
setProperty(vertexWithoutIdentity, Constants.MODIFIED_BY_KEY, RequestContext.get().getUser());
return vertexWithoutIdentity; return vertexWithoutIdentity;
} }
...@@ -169,6 +172,8 @@ public final class GraphHelper { ...@@ -169,6 +172,8 @@ public final class GraphHelper {
setProperty(edge, Constants.STATE_PROPERTY_KEY, Id.EntityState.ACTIVE.name()); setProperty(edge, Constants.STATE_PROPERTY_KEY, Id.EntityState.ACTIVE.name());
setProperty(edge, Constants.TIMESTAMP_PROPERTY_KEY, RequestContext.get().getRequestTime()); setProperty(edge, Constants.TIMESTAMP_PROPERTY_KEY, RequestContext.get().getRequestTime());
setProperty(edge, Constants.MODIFICATION_TIMESTAMP_PROPERTY_KEY, RequestContext.get().getRequestTime()); setProperty(edge, Constants.MODIFICATION_TIMESTAMP_PROPERTY_KEY, RequestContext.get().getRequestTime());
setProperty(edge, Constants.CREATED_BY_KEY, RequestContext.get().getUser());
setProperty(edge, Constants.MODIFIED_BY_KEY, RequestContext.get().getUser());
LOG.debug("Added {}", string(edge)); LOG.debug("Added {}", string(edge));
return edge; return edge;
...@@ -517,6 +522,24 @@ public final class GraphHelper { ...@@ -517,6 +522,24 @@ public final class GraphHelper {
return element.getProperty(Constants.STATE_PROPERTY_KEY, String.class); return element.getProperty(Constants.STATE_PROPERTY_KEY, String.class);
} }
//Added conditions in fetching system attributes to handle test failures in GremlinTest where these properties are not set
public static String getCreatedByAsString(AtlasElement element){
return element.getProperty(Constants.CREATED_BY_KEY, String.class);
}
public static String getModifiedByAsString(AtlasElement element){
return element.getProperty(Constants.MODIFIED_BY_KEY, String.class);
}
public static long getCreatedTime(AtlasElement element){
return element.getProperty(Constants.TIMESTAMP_PROPERTY_KEY, Long.class);
}
public static long getModifiedTime(AtlasElement element){
return element.getProperty(Constants.MODIFICATION_TIMESTAMP_PROPERTY_KEY, Long.class);
}
/** /**
* For the given type, finds an unique attribute and checks if there is an existing instance with the same * For the given type, finds an unique attribute and checks if there is an existing instance with the same
* unique value * unique value
...@@ -857,7 +880,9 @@ public final class GraphHelper { ...@@ -857,7 +880,9 @@ public final class GraphHelper {
switch (field) { switch (field) {
case Constants.STATE_PROPERTY_KEY: case Constants.STATE_PROPERTY_KEY:
case Constants.GUID_PROPERTY_KEY: case Constants.GUID_PROPERTY_KEY:
return TypesUtil.newAttributeInfo(field, DataTypes.STRING_TYPE); case Constants.CREATED_BY_KEY:
case Constants.MODIFIED_BY_KEY:
return TypesUtil.newAttributeInfo(field, DataTypes.STRING_TYPE);
case Constants.TIMESTAMP_PROPERTY_KEY: case Constants.TIMESTAMP_PROPERTY_KEY:
case Constants.MODIFICATION_TIMESTAMP_PROPERTY_KEY: case Constants.MODIFICATION_TIMESTAMP_PROPERTY_KEY:
......
...@@ -36,7 +36,10 @@ import org.apache.atlas.repository.graphdb.AtlasVertex; ...@@ -36,7 +36,10 @@ import org.apache.atlas.repository.graphdb.AtlasVertex;
import org.apache.atlas.typesystem.ITypedInstance; import org.apache.atlas.typesystem.ITypedInstance;
import org.apache.atlas.typesystem.ITypedReferenceableInstance; import org.apache.atlas.typesystem.ITypedReferenceableInstance;
import org.apache.atlas.typesystem.ITypedStruct; import org.apache.atlas.typesystem.ITypedStruct;
import org.apache.atlas.typesystem.Referenceable;
import org.apache.atlas.typesystem.persistence.AtlasSystemAttributes;
import org.apache.atlas.typesystem.persistence.Id; import org.apache.atlas.typesystem.persistence.Id;
import org.apache.atlas.typesystem.persistence.ReferenceableInstance;
import org.apache.atlas.typesystem.types.AttributeInfo; import org.apache.atlas.typesystem.types.AttributeInfo;
import org.apache.atlas.typesystem.types.ClassType; import org.apache.atlas.typesystem.types.ClassType;
import org.apache.atlas.typesystem.types.DataTypes; import org.apache.atlas.typesystem.types.DataTypes;
...@@ -70,6 +73,13 @@ public final class GraphToTypedInstanceMapper { ...@@ -70,6 +73,13 @@ public final class GraphToTypedInstanceMapper {
String typeName = GraphHelper.getSingleValuedProperty(instanceVertex, Constants.ENTITY_TYPE_PROPERTY_KEY, String.class); String typeName = GraphHelper.getSingleValuedProperty(instanceVertex, Constants.ENTITY_TYPE_PROPERTY_KEY, String.class);
List<String> traits = GraphHelper.getTraitNames(instanceVertex); List<String> traits = GraphHelper.getTraitNames(instanceVertex);
String state = GraphHelper.getStateAsString(instanceVertex); String state = GraphHelper.getStateAsString(instanceVertex);
String createdBy = GraphHelper.getCreatedByAsString(instanceVertex);
String modifiedBy = GraphHelper.getModifiedByAsString(instanceVertex);
Date createdTime = new Date(GraphHelper.getCreatedTime(instanceVertex));
Date modifiedTime = new Date(GraphHelper.getModifiedTime(instanceVertex));
AtlasSystemAttributes systemAttributes = new AtlasSystemAttributes(createdBy, modifiedBy, createdTime, modifiedTime);
LOG.debug("Found createdBy : {} modifiedBy : {} createdTime: {} modifedTime: {}", createdBy, modifiedBy, createdTime, modifiedTime);
Id id = new Id(guid, (Integer) GraphHelper.getProperty(instanceVertex, Constants.VERSION_PROPERTY_KEY), Id id = new Id(guid, (Integer) GraphHelper.getProperty(instanceVertex, Constants.VERSION_PROPERTY_KEY),
typeName, state); typeName, state);
...@@ -77,7 +87,7 @@ public final class GraphToTypedInstanceMapper { ...@@ -77,7 +87,7 @@ public final class GraphToTypedInstanceMapper {
ClassType classType = typeSystem.getDataType(ClassType.class, typeName); ClassType classType = typeSystem.getDataType(ClassType.class, typeName);
ITypedReferenceableInstance typedInstance = ITypedReferenceableInstance typedInstance =
classType.createInstance(id, traits.toArray(new String[traits.size()])); classType.createInstance(id, systemAttributes, traits.toArray(new String[traits.size()]));
mapVertexToInstance(instanceVertex, typedInstance, classType.fieldMapping().fields); mapVertexToInstance(instanceVertex, typedInstance, classType.fieldMapping().fields);
mapVertexToInstanceTraits(instanceVertex, typedInstance, traits); mapVertexToInstanceTraits(instanceVertex, typedInstance, traits);
......
...@@ -27,6 +27,7 @@ import org.apache.atlas.typesystem.persistence.Id; ...@@ -27,6 +27,7 @@ import org.apache.atlas.typesystem.persistence.Id;
import org.apache.atlas.typesystem.types.TypeSystem; import org.apache.atlas.typesystem.types.TypeSystem;
import static org.apache.atlas.repository.Constants.MODIFICATION_TIMESTAMP_PROPERTY_KEY; import static org.apache.atlas.repository.Constants.MODIFICATION_TIMESTAMP_PROPERTY_KEY;
import static org.apache.atlas.repository.Constants.MODIFIED_BY_KEY;
import static org.apache.atlas.repository.Constants.STATE_PROPERTY_KEY; import static org.apache.atlas.repository.Constants.STATE_PROPERTY_KEY;
public class SoftDeleteHandler extends DeleteHandler { public class SoftDeleteHandler extends DeleteHandler {
...@@ -45,6 +46,7 @@ public class SoftDeleteHandler extends DeleteHandler { ...@@ -45,6 +46,7 @@ public class SoftDeleteHandler extends DeleteHandler {
GraphHelper.setProperty(instanceVertex, STATE_PROPERTY_KEY, Id.EntityState.DELETED.name()); GraphHelper.setProperty(instanceVertex, STATE_PROPERTY_KEY, Id.EntityState.DELETED.name());
GraphHelper.setProperty(instanceVertex, MODIFICATION_TIMESTAMP_PROPERTY_KEY, GraphHelper.setProperty(instanceVertex, MODIFICATION_TIMESTAMP_PROPERTY_KEY,
RequestContext.get().getRequestTime()); RequestContext.get().getRequestTime());
GraphHelper.setProperty(instanceVertex, MODIFIED_BY_KEY, RequestContext.get().getUser());
} }
} }
} }
...@@ -59,6 +61,7 @@ public class SoftDeleteHandler extends DeleteHandler { ...@@ -59,6 +61,7 @@ public class SoftDeleteHandler extends DeleteHandler {
GraphHelper.setProperty(edge, STATE_PROPERTY_KEY, Id.EntityState.DELETED.name()); GraphHelper.setProperty(edge, STATE_PROPERTY_KEY, Id.EntityState.DELETED.name());
GraphHelper GraphHelper
.setProperty(edge, MODIFICATION_TIMESTAMP_PROPERTY_KEY, RequestContext.get().getRequestTime()); .setProperty(edge, MODIFICATION_TIMESTAMP_PROPERTY_KEY, RequestContext.get().getRequestTime());
GraphHelper.setProperty(edge, MODIFIED_BY_KEY, RequestContext.get().getUser());
} }
} }
} }
......
...@@ -187,6 +187,8 @@ public final class TypedInstanceToGraphMapper { ...@@ -187,6 +187,8 @@ public final class TypedInstanceToGraphMapper {
} }
GraphHelper.setProperty(instanceVertex, Constants.MODIFICATION_TIMESTAMP_PROPERTY_KEY, GraphHelper.setProperty(instanceVertex, Constants.MODIFICATION_TIMESTAMP_PROPERTY_KEY,
RequestContext.get().getRequestTime()); RequestContext.get().getRequestTime());
GraphHelper.setProperty(instanceVertex, Constants.MODIFIED_BY_KEY, RequestContext.get().getUser());
LOG.debug("Setting modifiedBy: {} and modifiedTime: {}", RequestContext.get().getUser(), RequestContext.get().getRequestTime());
} }
void mapAttributeToVertex(ITypedInstance typedInstance, AtlasVertex instanceVertex, void mapAttributeToVertex(ITypedInstance typedInstance, AtlasVertex instanceVertex,
......
...@@ -59,6 +59,8 @@ import java.util.Iterator; ...@@ -59,6 +59,8 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.Date;
import java.text.SimpleDateFormat;
import javax.inject.Inject; import javax.inject.Inject;
...@@ -67,6 +69,7 @@ import static org.apache.atlas.typesystem.types.utils.TypesUtil.createOptionalAt ...@@ -67,6 +69,7 @@ import static org.apache.atlas.typesystem.types.utils.TypesUtil.createOptionalAt
import static org.apache.atlas.typesystem.types.utils.TypesUtil.createRequiredAttrDef; import static org.apache.atlas.typesystem.types.utils.TypesUtil.createRequiredAttrDef;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
@Guice(modules = RepositoryMetadataModule.class) @Guice(modules = RepositoryMetadataModule.class)
public class GraphBackedDiscoveryServiceTest extends BaseRepositoryTest { public class GraphBackedDiscoveryServiceTest extends BaseRepositoryTest {
...@@ -167,6 +170,24 @@ public class GraphBackedDiscoveryServiceTest extends BaseRepositoryTest { ...@@ -167,6 +170,24 @@ public class GraphBackedDiscoveryServiceTest extends BaseRepositoryTest {
assertNotNull(rows); assertNotNull(rows);
assertEquals(rows.length(), 1); assertEquals(rows.length(), 1);
//Assert system attributes are not null
JSONObject sys_attributes = (JSONObject)rows.getJSONObject(0).get("$systemAttributes$");
assertNotNull(sys_attributes.get("createdBy"));
assertNotNull(sys_attributes.get("modifiedBy"));
assertNotNull(sys_attributes.get("createdTime"));
assertNotNull(sys_attributes.get("modifiedTime"));
//Assert that createdTime and modifiedTime are valid dates
String createdTime = (String) sys_attributes.get("createdTime");
String modifiedTime = (String) sys_attributes.get("modifiedTime");
final String outputFormat = "EEE MMM dd HH:mm:ss z yyyy";
SimpleDateFormat df = new SimpleDateFormat(outputFormat);
Date createdDate = df.parse(createdTime);
Date modifiedDate = df.parse(modifiedTime);
assertNotNull(createdDate);
assertNotNull(modifiedDate);
final String testTs = "\"2011-11-01T02:35:58.440Z\""; final String testTs = "\"2011-11-01T02:35:58.440Z\"";
dslQuery = "Department where " + Constants.TIMESTAMP_PROPERTY_KEY + " > " + testTs; dslQuery = "Department where " + Constants.TIMESTAMP_PROPERTY_KEY + " > " + testTs;
jsonResults = searchByDSL(dslQuery); jsonResults = searchByDSL(dslQuery);
...@@ -191,6 +212,27 @@ public class GraphBackedDiscoveryServiceTest extends BaseRepositoryTest { ...@@ -191,6 +212,27 @@ public class GraphBackedDiscoveryServiceTest extends BaseRepositoryTest {
assertNotNull(rows); assertNotNull(rows);
assertEquals(rows.length(), 1); assertEquals(rows.length(), 1);
dslQuery = "from Department select " + Constants.CREATED_BY_KEY;
jsonResults = searchByDSL(dslQuery);
assertNotNull(jsonResults);
results = new JSONObject(jsonResults);
assertEquals(results.length(), 3);
rows = results.getJSONArray("rows");
assertNotNull(rows);
assertEquals(rows.length(), 1);
dslQuery = "from Department select " + Constants.MODIFIED_BY_KEY;
jsonResults = searchByDSL(dslQuery);
assertNotNull(jsonResults);
results = new JSONObject(jsonResults);
assertEquals(results.length(), 3);
rows = results.getJSONArray("rows");
assertNotNull(rows);
assertEquals(rows.length(), 1);
} }
@Test @Test
......
...@@ -43,6 +43,7 @@ import org.apache.atlas.typesystem.Referenceable; ...@@ -43,6 +43,7 @@ import org.apache.atlas.typesystem.Referenceable;
import org.apache.atlas.typesystem.Struct; import org.apache.atlas.typesystem.Struct;
import org.apache.atlas.typesystem.exception.EntityNotFoundException; import org.apache.atlas.typesystem.exception.EntityNotFoundException;
import org.apache.atlas.typesystem.exception.TraitNotFoundException; import org.apache.atlas.typesystem.exception.TraitNotFoundException;
import org.apache.atlas.typesystem.persistence.AtlasSystemAttributes;
import org.apache.atlas.typesystem.persistence.Id; import org.apache.atlas.typesystem.persistence.Id;
import org.apache.atlas.typesystem.types.AttributeDefinition; import org.apache.atlas.typesystem.types.AttributeDefinition;
import org.apache.atlas.typesystem.types.ClassType; import org.apache.atlas.typesystem.types.ClassType;
...@@ -207,6 +208,11 @@ public class GraphBackedMetadataRepositoryTest { ...@@ -207,6 +208,11 @@ public class GraphBackedMetadataRepositoryTest {
//entity state should be active by default //entity state should be active by default
Assert.assertEquals(entity.getId().getState(), Id.EntityState.ACTIVE); Assert.assertEquals(entity.getId().getState(), Id.EntityState.ACTIVE);
//System attributes created time and modified time should not be null
AtlasSystemAttributes systemAttributes = entity.getSystemAttributes();
Assert.assertNotNull(systemAttributes.createdTime);
Assert.assertNotNull(systemAttributes.modifiedTime);
} }
@Test(expectedExceptions = EntityNotFoundException.class) @Test(expectedExceptions = EntityNotFoundException.class)
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
package org.apache.atlas.typesystem; package org.apache.atlas.typesystem;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import org.apache.atlas.typesystem.persistence.AtlasSystemAttributes;
import org.apache.atlas.typesystem.persistence.Id; import org.apache.atlas.typesystem.persistence.Id;
/** /**
...@@ -32,4 +33,6 @@ public interface IReferenceableInstance extends IStruct { ...@@ -32,4 +33,6 @@ public interface IReferenceableInstance extends IStruct {
Id getId(); Id getId();
IStruct getTrait(String typeName); IStruct getTrait(String typeName);
AtlasSystemAttributes getSystemAttributes();
} }
...@@ -22,6 +22,7 @@ import com.google.common.collect.ImmutableList; ...@@ -22,6 +22,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import org.apache.atlas.AtlasException; import org.apache.atlas.AtlasException;
import org.apache.atlas.classification.InterfaceAudience; import org.apache.atlas.classification.InterfaceAudience;
import org.apache.atlas.typesystem.persistence.AtlasSystemAttributes;
import org.apache.atlas.typesystem.persistence.Id; import org.apache.atlas.typesystem.persistence.Id;
import java.util.HashMap; import java.util.HashMap;
...@@ -36,6 +37,7 @@ public class Referenceable extends Struct implements IReferenceableInstance { ...@@ -36,6 +37,7 @@ public class Referenceable extends Struct implements IReferenceableInstance {
private Id id; private Id id;
private final ImmutableMap<String, IStruct> traits; private final ImmutableMap<String, IStruct> traits;
private final ImmutableList<String> traitNames; private final ImmutableList<String> traitNames;
private AtlasSystemAttributes systemAttributes;
public Referenceable(String typeName, String... traitNames) { public Referenceable(String typeName, String... traitNames) {
super(typeName); super(typeName);
...@@ -46,6 +48,7 @@ public class Referenceable extends Struct implements IReferenceableInstance { ...@@ -46,6 +48,7 @@ public class Referenceable extends Struct implements IReferenceableInstance {
b.put(t, new Struct(t)); b.put(t, new Struct(t));
} }
traits = b.build(); traits = b.build();
this.systemAttributes = new AtlasSystemAttributes();
} }
public Referenceable(String typeName, Map<String, Object> values) { public Referenceable(String typeName, Map<String, Object> values) {
...@@ -53,6 +56,7 @@ public class Referenceable extends Struct implements IReferenceableInstance { ...@@ -53,6 +56,7 @@ public class Referenceable extends Struct implements IReferenceableInstance {
id = new Id(typeName); id = new Id(typeName);
traitNames = ImmutableList.of(); traitNames = ImmutableList.of();
traits = ImmutableMap.of(); traits = ImmutableMap.of();
this.systemAttributes = new AtlasSystemAttributes();
} }
public Referenceable(String guid, String typeName, Map<String, Object> values) { public Referenceable(String guid, String typeName, Map<String, Object> values) {
...@@ -60,6 +64,7 @@ public class Referenceable extends Struct implements IReferenceableInstance { ...@@ -60,6 +64,7 @@ public class Referenceable extends Struct implements IReferenceableInstance {
id = new Id(guid, 0, typeName); id = new Id(guid, 0, typeName);
traitNames = ImmutableList.of(); traitNames = ImmutableList.of();
traits = ImmutableMap.of(); traits = ImmutableMap.of();
this.systemAttributes = new AtlasSystemAttributes();
} }
/** /**
...@@ -75,6 +80,7 @@ public class Referenceable extends Struct implements IReferenceableInstance { ...@@ -75,6 +80,7 @@ public class Referenceable extends Struct implements IReferenceableInstance {
id = new Id(guid, 0, typeName); id = new Id(guid, 0, typeName);
traitNames = ImmutableList.copyOf(_traitNames); traitNames = ImmutableList.copyOf(_traitNames);
traits = ImmutableMap.copyOf(_traits); traits = ImmutableMap.copyOf(_traits);
this.systemAttributes = new AtlasSystemAttributes();
} }
/** /**
...@@ -90,6 +96,23 @@ public class Referenceable extends Struct implements IReferenceableInstance { ...@@ -90,6 +96,23 @@ public class Referenceable extends Struct implements IReferenceableInstance {
this.id = id; this.id = id;
traitNames = ImmutableList.copyOf(_traitNames); traitNames = ImmutableList.copyOf(_traitNames);
traits = ImmutableMap.copyOf(_traits); traits = ImmutableMap.copyOf(_traits);
this.systemAttributes = new AtlasSystemAttributes();
}
/**
* Not public - only use during deserialization
* @param id entity id
* @param typeName the type name
* @param values the entity attribute values
*/
@InterfaceAudience.Private
public Referenceable(Id id, String typeName, Map<String, Object> values, List<String> _traitNames,
Map<String, IStruct> _traits, AtlasSystemAttributes systemAttributes) {
super(typeName, values);
this.id = id;
traitNames = ImmutableList.copyOf(_traitNames);
traits = ImmutableMap.copyOf(_traits);
this.systemAttributes = systemAttributes;
} }
/** /**
...@@ -130,6 +153,11 @@ public class Referenceable extends Struct implements IReferenceableInstance { ...@@ -130,6 +153,11 @@ public class Referenceable extends Struct implements IReferenceableInstance {
return traits.get(typeName); return traits.get(typeName);
} }
@Override
public AtlasSystemAttributes getSystemAttributes(){
return systemAttributes;
}
/** /**
* Matches traits, values associated with this Referenceable and skips the id match * Matches traits, values associated with this Referenceable and skips the id match
* @param o The Referenceable which needs to be matched with * @param o The Referenceable which needs to be matched with
......
/**
* 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.persistence;
import org.apache.atlas.typesystem.types.TypeSystem;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class AtlasSystemAttributes {
public String createdBy;
public String modifiedBy;
public Date createdTime;
public Date modifiedTime;
public SimpleDateFormat simpleDateFormat = TypeSystem.getInstance().getDateFormat();
public AtlasSystemAttributes(String createdBy, String modifiedBy, Date createdTime, Date modifiedTime){
this.createdBy = createdBy;
this.modifiedBy = modifiedBy;
this.createdTime = createdTime;
this.modifiedTime = modifiedTime;
}
public AtlasSystemAttributes(){
super();
}
public AtlasSystemAttributes(String createdBy, String modifiedBy, String createdTime, String modifiedTime){
this.createdBy = createdBy;
this.modifiedBy = modifiedBy;
try{
this.createdTime = simpleDateFormat.parse(createdTime);
}catch (ParseException e){
//this.createdTime = new Date(0);
}
try{
this.modifiedTime = simpleDateFormat.parse(modifiedTime);
}catch (ParseException e){
//this.modifiedTime = new Date(0);
}
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
AtlasSystemAttributes sys_attr = (AtlasSystemAttributes) o;
if (!createdBy.equals(sys_attr.createdBy)) {
return false;
}
if (!modifiedBy.equals(sys_attr.modifiedBy)) {
return false;
}
if (!createdTime.equals(sys_attr.createdTime)) {
return false;
}
if(!modifiedTime.equals(sys_attr.modifiedTime)){
return false;
}
return true;
}
@Override
public int hashCode() {
int result = createdBy.hashCode();
result = 31 * result + modifiedBy.hashCode();
result = 31 * result + createdTime.hashCode();
result = 31 * result + modifiedTime.hashCode();
return result;
}
public String getCreatedBy(){
return createdBy;
}
public String getModifiedBy(){
return modifiedBy;
}
public Date getCreatedTime(){
return createdTime;
}
public Date getModifiedTime(){
return modifiedTime;
}
}
...@@ -45,6 +45,7 @@ public class Id implements ITypedReferenceableInstance { ...@@ -45,6 +45,7 @@ public class Id implements ITypedReferenceableInstance {
public final int version; public final int version;
public EntityState state; public EntityState state;
private static AtomicLong s_nextId = new AtomicLong(System.nanoTime()); private static AtomicLong s_nextId = new AtomicLong(System.nanoTime());
public final AtlasSystemAttributes systemAttributes;
public Id(String id, int version, String typeName, String state) { public Id(String id, int version, String typeName, String state) {
id = ParamChecker.notEmpty(id, "id"); id = ParamChecker.notEmpty(id, "id");
...@@ -58,6 +59,7 @@ public class Id implements ITypedReferenceableInstance { ...@@ -58,6 +59,7 @@ public class Id implements ITypedReferenceableInstance {
} else { } else {
this.state = EntityState.valueOf(state.toUpperCase()); this.state = EntityState.valueOf(state.toUpperCase());
} }
this.systemAttributes = new AtlasSystemAttributes();
} }
public Id(String id, int version, String typeName) { public Id(String id, int version, String typeName) {
...@@ -105,6 +107,11 @@ public class Id implements ITypedReferenceableInstance { ...@@ -105,6 +107,11 @@ public class Id implements ITypedReferenceableInstance {
return String.format("id[type=%s guid=%s state=%s]", typeName, id, state); return String.format("id[type=%s guid=%s state=%s]", typeName, id, state);
} }
@Override
public AtlasSystemAttributes getSystemAttributes(){
return systemAttributes;
}
public String getClassName() { public String getClassName() {
return typeName; return typeName;
} }
......
...@@ -45,9 +45,10 @@ public class ReferenceableInstance extends StructInstance implements ITypedRefer ...@@ -45,9 +45,10 @@ public class ReferenceableInstance extends StructInstance implements ITypedRefer
private final ImmutableMap<String, ITypedStruct> traits; private final ImmutableMap<String, ITypedStruct> traits;
private final ImmutableList<String> traitNames; private final ImmutableList<String> traitNames;
private Id id; private Id id;
private AtlasSystemAttributes systemAttributes;
public ReferenceableInstance(Id id, String dataTypeName, FieldMapping fieldMapping, boolean[] nullFlags, public ReferenceableInstance(Id id, String dataTypeName, AtlasSystemAttributes systemAttributes, FieldMapping fieldMapping, boolean[] nullFlags,
boolean[] bools, byte[] bytes, short[] shorts, int[] ints, long[] longs, float[] floats, double[] doubles, boolean[] bools, byte[] bytes, short[] shorts, int[] ints, long[] longs, float[] floats, double[] doubles,
BigDecimal[] bigDecimals, BigInteger[] bigIntegers, Date[] dates, String[] strings, BigDecimal[] bigDecimals, BigInteger[] bigIntegers, Date[] dates, String[] strings,
ImmutableList<Object>[] arrays, ImmutableMap<Object, Object>[] maps, StructInstance[] structs, ImmutableList<Object>[] arrays, ImmutableMap<Object, Object>[] maps, StructInstance[] structs,
...@@ -61,6 +62,12 @@ public class ReferenceableInstance extends StructInstance implements ITypedRefer ...@@ -61,6 +62,12 @@ public class ReferenceableInstance extends StructInstance implements ITypedRefer
b.add(t); b.add(t);
} }
this.traitNames = b.build(); this.traitNames = b.build();
if(systemAttributes == null){
this.systemAttributes = new AtlasSystemAttributes();
}
else{
this.systemAttributes = systemAttributes;
}
} }
@Override @Override
...@@ -78,6 +85,11 @@ public class ReferenceableInstance extends StructInstance implements ITypedRefer ...@@ -78,6 +85,11 @@ public class ReferenceableInstance extends StructInstance implements ITypedRefer
return traits.get(typeName); return traits.get(typeName);
} }
@Override
public AtlasSystemAttributes getSystemAttributes(){
return systemAttributes;
}
/** /**
* @nopub * @nopub
* @param id * @param id
......
...@@ -31,6 +31,7 @@ import org.apache.atlas.typesystem.ITypedReferenceableInstance; ...@@ -31,6 +31,7 @@ import org.apache.atlas.typesystem.ITypedReferenceableInstance;
import org.apache.atlas.typesystem.ITypedStruct; import org.apache.atlas.typesystem.ITypedStruct;
import org.apache.atlas.typesystem.Referenceable; import org.apache.atlas.typesystem.Referenceable;
import org.apache.atlas.typesystem.Struct; import org.apache.atlas.typesystem.Struct;
import org.apache.atlas.typesystem.persistence.AtlasSystemAttributes;
import org.apache.atlas.typesystem.persistence.Id; import org.apache.atlas.typesystem.persistence.Id;
import org.apache.atlas.typesystem.persistence.ReferenceableInstance; import org.apache.atlas.typesystem.persistence.ReferenceableInstance;
import org.apache.atlas.typesystem.persistence.StructInstance; import org.apache.atlas.typesystem.persistence.StructInstance;
...@@ -132,7 +133,7 @@ public class ClassType extends HierarchicalType<ClassType, IReferenceableInstanc ...@@ -132,7 +133,7 @@ public class ClassType extends HierarchicalType<ClassType, IReferenceableInstanc
} }
ITypedReferenceableInstance tr = ITypedReferenceableInstance tr =
r != null ? createInstanceWithTraits(id, r, r.getTraits().toArray(new String[0])) : r != null ? createInstanceWithTraits(id, null, r, r.getTraits().toArray(new String[0])) :
createInstance(id); createInstance(id);
if (id != null && id.isAssigned()) { if (id != null && id.isAssigned()) {
...@@ -180,10 +181,14 @@ public class ClassType extends HierarchicalType<ClassType, IReferenceableInstanc ...@@ -180,10 +181,14 @@ public class ClassType extends HierarchicalType<ClassType, IReferenceableInstanc
} }
public ITypedReferenceableInstance createInstance(Id id, String... traitNames) throws AtlasException { public ITypedReferenceableInstance createInstance(Id id, String... traitNames) throws AtlasException {
return createInstanceWithTraits(id, null, traitNames); return createInstanceWithTraits(id, null, null, traitNames);
} }
public ITypedReferenceableInstance createInstanceWithTraits(Id id, Referenceable r, String... traitNames) public ITypedReferenceableInstance createInstance(Id id, AtlasSystemAttributes systemAttributes, String... traitNames) throws AtlasException{
return createInstanceWithTraits(id, systemAttributes, null, traitNames);
}
public ITypedReferenceableInstance createInstanceWithTraits(Id id, AtlasSystemAttributes systemAttributes, Referenceable r, String... traitNames)
throws AtlasException { throws AtlasException {
ImmutableMap.Builder<String, ITypedStruct> b = new ImmutableBiMap.Builder<String, ITypedStruct>(); ImmutableMap.Builder<String, ITypedStruct> b = new ImmutableBiMap.Builder<String, ITypedStruct>();
...@@ -197,7 +202,7 @@ public class ClassType extends HierarchicalType<ClassType, IReferenceableInstanc ...@@ -197,7 +202,7 @@ public class ClassType extends HierarchicalType<ClassType, IReferenceableInstanc
} }
} }
return new ReferenceableInstance(id == null ? new Id(getName()) : id, getName(), fieldMapping, return new ReferenceableInstance(id == null ? new Id(getName()) : id, getName(), systemAttributes, fieldMapping,
new boolean[fieldMapping.fields.size()], new boolean[fieldMapping.fields.size()],
fieldMapping.numBools == 0 ? null : new boolean[fieldMapping.numBools], fieldMapping.numBools == 0 ? null : new boolean[fieldMapping.numBools],
fieldMapping.numBytes == 0 ? null : new byte[fieldMapping.numBytes], fieldMapping.numBytes == 0 ? null : new byte[fieldMapping.numBytes],
......
...@@ -21,23 +21,26 @@ package org.apache.atlas.typesystem.json ...@@ -21,23 +21,26 @@ package org.apache.atlas.typesystem.json
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import org.apache.atlas.typesystem._ import org.apache.atlas.typesystem._
import org.apache.atlas.typesystem.persistence.Id import org.apache.atlas.typesystem.persistence.{AtlasSystemAttributes, Id}
import org.apache.atlas.typesystem.types._ import org.apache.atlas.typesystem.types._
import org.json4s._ import org.json4s._
import org.json4s.native.Serialization._ import org.json4s.native.Serialization._
import scala.collection.JavaConversions._ import scala.collection.JavaConversions._
import scala.collection.JavaConverters._ import scala.collection.JavaConverters._
import java.util.Date
object InstanceSerialization { object InstanceSerialization {
case class _Id(id : String, version : Int, typeName : String, state : Option[String]) case class _Id(id : String, version : Int, typeName : String, state : Option[String])
case class _AtlasSystemAttributes(createdBy: Option[String], modifiedBy: Option[String], createdTime: Option[Date], modifiedTime: Option[Date])
case class _Struct(typeName : String, values : Map[String, AnyRef]) case class _Struct(typeName : String, values : Map[String, AnyRef])
case class _Reference(id : Option[_Id], case class _Reference(id : Option[_Id],
typeName : String, typeName : String,
values : Map[String, AnyRef], values : Map[String, AnyRef],
traitNames : List[String], traitNames : List[String],
traits : Map[String, _Struct]) traits : Map[String, _Struct],
systemAttributes : Option[_AtlasSystemAttributes])
def Try[B](x : => B) : Option[B] = { def Try[B](x : => B) : Option[B] = {
try { Some(x) } catch { case _ : Throwable => None } try { Some(x) } catch { case _ : Throwable => None }
...@@ -71,6 +74,14 @@ object InstanceSerialization { ...@@ -71,6 +74,14 @@ object InstanceSerialization {
jsonMap.get("id").filter(_.isInstanceOf[String]).flatMap(v => Some(v.asInstanceOf[String])) jsonMap.get("id").filter(_.isInstanceOf[String]).flatMap(v => Some(v.asInstanceOf[String]))
} }
def createdBy: Option[String] = {
jsonMap.get("createdBy").filter(_.isInstanceOf[String]).flatMap(v => Some(v.asInstanceOf[String]))
}
def modifiedBy: Option[String] = {
jsonMap.get("modifiedBy").filter(_.isInstanceOf[String]).flatMap(v => Some(v.asInstanceOf[String]))
}
/** /**
* validate and extract 'state' attribute from Map * validate and extract 'state' attribute from Map
* @return * @return
...@@ -91,6 +102,14 @@ object InstanceSerialization { ...@@ -91,6 +102,14 @@ object InstanceSerialization {
} }
} }
def createdTime: Option[Date] = {
jsonMap.get("createdTime").filter(_.isInstanceOf[String]).flatMap(v => Some(v.asInstanceOf[Date]))
}
def modifiedTime: Option[Date] = {
jsonMap.get("modifiedTime").filter(_.isInstanceOf[String]).flatMap(v => Some(v.asInstanceOf[Date]))
}
/** /**
* A Map is an Id if: * A Map is an Id if:
* - it has the correct [[format.typeHintFieldName]] * - it has the correct [[format.typeHintFieldName]]
...@@ -109,6 +128,15 @@ object InstanceSerialization { ...@@ -109,6 +128,15 @@ object InstanceSerialization {
} yield _Id(i, v, typNm, s) } yield _Id(i, v, typNm, s)
} }
def convertSystemAttributes: Option[_AtlasSystemAttributes] = {
for {
c <- Some(createdBy)
m <- Some(modifiedBy)
c_t <- Some(createdTime)
m_t <- Some(modifiedTime)
} yield _AtlasSystemAttributes(c, m, c_t, m_t)
}
/** /**
* validate and extract 'typeName' attribute from Map * validate and extract 'typeName' attribute from Map
* @return * @return
...@@ -232,7 +260,8 @@ object InstanceSerialization { ...@@ -232,7 +260,8 @@ object InstanceSerialization {
values <- valuesMap values <- valuesMap
traitNms <- traitNames traitNms <- traitNames
ts <- traits ts <- traits
} yield _Reference(i, typNm, values, traitNms.toList, ts) s_attr <- Some(convertSystemAttributes)
} yield _Reference(i, typNm, values, traitNms.toList, ts, s_attr)
} }
/** /**
...@@ -259,16 +288,22 @@ object InstanceSerialization { ...@@ -259,16 +288,22 @@ object InstanceSerialization {
def asJava(v : Any)(implicit format: Formats) : Any = v match { def asJava(v : Any)(implicit format: Formats) : Any = v match {
case i : _Id => new Id(i.id, i.version, i.typeName, i.state.orNull) case i : _Id => new Id(i.id, i.version, i.typeName, i.state.orNull)
case s : _Struct => new Struct(s.typeName, asJava(s.values).asInstanceOf[java.util.Map[String, Object]]) case s : _Struct => new Struct(s.typeName, asJava(s.values).asInstanceOf[java.util.Map[String, Object]])
case s_attr : _AtlasSystemAttributes => new AtlasSystemAttributes(s_attr.createdBy.orNull, s_attr.modifiedBy.orNull, s_attr.createdTime.orNull, s_attr.modifiedTime.orNull)
case r : _Reference => { case r : _Reference => {
val id = r.id match { val id = r.id match {
case Some(i) => new Id(i.id, i.version, i.typeName, i.state.orNull) case Some(i) => new Id(i.id, i.version, i.typeName, i.state.orNull)
case None => new Id(r.typeName) case None => new Id(r.typeName)
} }
val s_attr = r.systemAttributes match {
case Some(s) => new AtlasSystemAttributes(s.createdBy.orNull, s.modifiedBy.orNull, s.createdTime.orNull, s.modifiedTime.orNull)
case None => new AtlasSystemAttributes()
}
new Referenceable(id, new Referenceable(id,
r.typeName, r.typeName,
asJava(r.values).asInstanceOf[java.util.Map[String, Object]], asJava(r.values).asInstanceOf[java.util.Map[String, Object]],
asJava(r.traitNames).asInstanceOf[java.util.List[String]], asJava(r.traitNames).asInstanceOf[java.util.List[String]],
asJava(r.traits).asInstanceOf[java.util.Map[String, IStruct]]) asJava(r.traits).asInstanceOf[java.util.Map[String, IStruct]], s_attr)
} }
case l : List[_] => l.map(e => asJava(e)).toList.asJava case l : List[_] => l.map(e => asJava(e)).toList.asJava
case m : Map[_, _] if Try{m.asInstanceOf[Map[String,_]]}.isDefined => { case m : Map[_, _] if Try{m.asInstanceOf[Map[String,_]]}.isDefined => {
...@@ -284,6 +319,7 @@ object InstanceSerialization { ...@@ -284,6 +319,7 @@ object InstanceSerialization {
def asScala(v : Any) : Any = v match { def asScala(v : Any) : Any = v match {
case i : Id => _Id(i._getId(), i.getVersion, i.getClassName, Some(i.getStateAsString)) case i : Id => _Id(i._getId(), i.getVersion, i.getClassName, Some(i.getStateAsString))
case s_attr: AtlasSystemAttributes => _AtlasSystemAttributes(Some(s_attr.createdBy), Some(s_attr.modifiedBy), Some(s_attr.createdTime), Some(s_attr.modifiedTime))
case r : IReferenceableInstance => { case r : IReferenceableInstance => {
val traits = r.getTraits.map { tName => val traits = r.getTraits.map { tName =>
val t = r.getTrait(tName).asInstanceOf[IStruct] val t = r.getTrait(tName).asInstanceOf[IStruct]
...@@ -292,7 +328,7 @@ object InstanceSerialization { ...@@ -292,7 +328,7 @@ object InstanceSerialization {
_Reference(Some(asScala(r.getId).asInstanceOf[_Id]), _Reference(Some(asScala(r.getId).asInstanceOf[_Id]),
r.getTypeName, asScala(r.getValuesMap).asInstanceOf[Map[String, AnyRef]], r.getTypeName, asScala(r.getValuesMap).asInstanceOf[Map[String, AnyRef]],
asScala(r.getTraits).asInstanceOf[List[String]], asScala(r.getTraits).asInstanceOf[List[String]],
traits.asInstanceOf[Map[String, _Struct]]) traits.asInstanceOf[Map[String, _Struct]], Some(asScala(r.getSystemAttributes).asInstanceOf[_AtlasSystemAttributes]))
} }
case s : IStruct => _Struct(s.getTypeName, asScala(s.getValuesMap).asInstanceOf[Map[String, AnyRef]]) case s : IStruct => _Struct(s.getTypeName, asScala(s.getValuesMap).asInstanceOf[Map[String, AnyRef]])
case l : java.util.List[_] => l.asScala.map(e => asScala(e)).toList case l : java.util.List[_] => l.asScala.map(e => asScala(e)).toList
......
...@@ -19,15 +19,16 @@ ...@@ -19,15 +19,16 @@
package org.apache.atlas.typesystem.json package org.apache.atlas.typesystem.json
import org.apache.atlas.typesystem._ import org.apache.atlas.typesystem._
import org.apache.atlas.typesystem.persistence.{Id, ReferenceableInstance, StructInstance} import org.apache.atlas.typesystem.persistence.{AtlasSystemAttributes, Id, ReferenceableInstance, StructInstance}
import org.apache.atlas.typesystem.types.DataTypes.{ArrayType, MapType, TypeCategory} import org.apache.atlas.typesystem.types.DataTypes.{ArrayType, MapType, TypeCategory}
import org.apache.atlas.typesystem.types._ import org.apache.atlas.typesystem.types._
import org.json4s.JsonAST.JInt import org.json4s.JsonAST.JInt
import org.json4s._ import org.json4s.{JsonAST, _}
import org.json4s.native.Serialization._ import org.json4s.native.Serialization._
import scala.collection.JavaConversions._ import scala.collection.JavaConversions._
import scala.collection.JavaConverters._ import scala.collection.JavaConverters._
import java.util.Date
class BigDecimalSerializer extends CustomSerializer[java.math.BigDecimal](format => ( class BigDecimalSerializer extends CustomSerializer[java.math.BigDecimal](format => (
{ {
...@@ -60,6 +61,7 @@ class IdSerializer extends CustomSerializer[Id](format => ( { ...@@ -60,6 +61,7 @@ class IdSerializer extends CustomSerializer[Id](format => ( {
case JObject(JField(Serialization.STRUCT_TYPE_FIELD_NAME, JString(typeName)) :: case JObject(JField(Serialization.STRUCT_TYPE_FIELD_NAME, JString(typeName)) ::
JField("id", JString(id)) :: JField("id", JString(id)) ::
JField("version", JString(version)) :: Nil) => new Id(id, version.toInt, typeName) JField("version", JString(version)) :: Nil) => new Id(id, version.toInt, typeName)
}, { }, {
case id: Id => JObject(JField("id", JString(id.id)), case id: Id => JObject(JField("id", JString(id.id)),
JField(Serialization.STRUCT_TYPE_FIELD_NAME, JString(id.typeName)), JField(Serialization.STRUCT_TYPE_FIELD_NAME, JString(id.typeName)),
...@@ -117,12 +119,14 @@ class TypedReferenceableInstanceSerializer() ...@@ -117,12 +119,14 @@ class TypedReferenceableInstanceSerializer()
var typField: Option[JField] = None var typField: Option[JField] = None
var idField: Option[JField] = None var idField: Option[JField] = None
var traitsField: Option[JField] = None var traitsField: Option[JField] = None
var sysAttrField: Option[JField] = None
var fields: List[JField] = Nil var fields: List[JField] = Nil
fs.foreach { f: JField => f._1 match { fs.foreach { f: JField => f._1 match {
case Serialization.STRUCT_TYPE_FIELD_NAME => typField = Some(f) case Serialization.STRUCT_TYPE_FIELD_NAME => typField = Some(f)
case Serialization.ID_TYPE_FIELD_NAME => idField = Some(f) case Serialization.ID_TYPE_FIELD_NAME => idField = Some(f)
case Serialization.TRAIT_TYPE_FIELD_NAME => traitsField = Some(f) case Serialization.TRAIT_TYPE_FIELD_NAME => traitsField = Some(f)
case Serialization.SYSTEM_ATTR_FIELD_NAME => sysAttrField = Some(f)
case _ => fields = fields :+ f case _ => fields = fields :+ f
} }
} }
...@@ -141,7 +145,8 @@ class TypedReferenceableInstanceSerializer() ...@@ -141,7 +145,8 @@ class TypedReferenceableInstanceSerializer()
val sT = typSystem.getDataType( val sT = typSystem.getDataType(
classOf[ClassType], typName).asInstanceOf[ClassType] classOf[ClassType], typName).asInstanceOf[ClassType]
val id = Serialization.deserializeId(idField.get._2) val id = Serialization.deserializeId(idField.get._2)
val s = sT.createInstance(id, traitNames: _*) val s_attr = Serialization.deserializeSystemAttributes(sysAttrField.get._2)
val s = sT.createInstance(id, s_attr, traitNames: _*)
Serialization.deserializeFields(typSystem, sT, s, fields) Serialization.deserializeFields(typSystem, sT, s, fields)
traitsField.map { t => traitsField.map { t =>
...@@ -169,10 +174,11 @@ class TypedReferenceableInstanceSerializer() ...@@ -169,10 +174,11 @@ class TypedReferenceableInstanceSerializer()
case id: Id => Serialization.serializeId(id) case id: Id => Serialization.serializeId(id)
case e: ITypedReferenceableInstance => case e: ITypedReferenceableInstance =>
val idJ = JField(Serialization.ID_TYPE_FIELD_NAME, Serialization.serializeId(e.getId)) val idJ = JField(Serialization.ID_TYPE_FIELD_NAME, Serialization.serializeId(e.getId))
val s_attrJ = JField(Serialization.SYSTEM_ATTR_FIELD_NAME, Serialization.serializeSystemAttributes(e.getSystemAttributes))
var fields = Serialization.serializeFields(e) var fields = Serialization.serializeFields(e)
val traitsJ: List[JField] = e.getTraits.map(tName => JField(tName, Extraction.decompose(e.getTrait(tName)))).toList val traitsJ: List[JField] = e.getTraits.map(tName => JField(tName, Extraction.decompose(e.getTrait(tName)))).toList
fields = idJ :: fields fields = idJ :: s_attrJ :: fields
if (traitsJ.size > 0) { if (traitsJ.size > 0) {
fields = fields :+ JField(Serialization.TRAIT_TYPE_FIELD_NAME, JObject(traitsJ: _*)) fields = fields :+ JField(Serialization.TRAIT_TYPE_FIELD_NAME, JObject(traitsJ: _*))
} }
...@@ -186,6 +192,7 @@ object Serialization { ...@@ -186,6 +192,7 @@ object Serialization {
val STRUCT_TYPE_FIELD_NAME = "$typeName$" val STRUCT_TYPE_FIELD_NAME = "$typeName$"
val ID_TYPE_FIELD_NAME = "$id$" val ID_TYPE_FIELD_NAME = "$id$"
val TRAIT_TYPE_FIELD_NAME = "$traits$" val TRAIT_TYPE_FIELD_NAME = "$traits$"
val SYSTEM_ATTR_FIELD_NAME = "$systemAttributes$"
def extractList(lT: ArrayType, value: JArray)(implicit format: Formats): Any = { def extractList(lT: ArrayType, value: JArray)(implicit format: Formats): Any = {
val dT = lT.getElemType val dT = lT.getElemType
...@@ -218,6 +225,22 @@ object Serialization { ...@@ -218,6 +225,22 @@ object Serialization {
JField(Serialization.STRUCT_TYPE_FIELD_NAME, JString(id.typeName)), JField(Serialization.STRUCT_TYPE_FIELD_NAME, JString(id.typeName)),
JField("version", JInt(id.version)), JField("state", JString(id.state.name()))) JField("version", JInt(id.version)), JField("state", JString(id.state.name())))
//Handling serialization issues with null values
//See https://github.com/json4s/json4s/issues/358
def parseString(s: Any) = s match {
case s:String => JString(s)
case s:Date => JString(s.toString)
case _ => JString("")
}
def serializeSystemAttributes(s_attr: AtlasSystemAttributes) = JObject(
JField("createdBy", parseString(s_attr.modifiedBy)),
JField("modifiedBy", parseString(s_attr.modifiedBy)),
JField("createdTime", parseString(s_attr.createdTime)),
JField("modifiedTime", parseString(s_attr.modifiedTime))
)
def serializeFields(e: ITypedInstance)(implicit format: Formats) = e.fieldMapping.fields.map { def serializeFields(e: ITypedInstance)(implicit format: Formats) = e.fieldMapping.fields.map {
case (fName, info) => { case (fName, info) => {
var v = e.get(fName) var v = e.get(fName)
...@@ -272,6 +295,13 @@ object Serialization { ...@@ -272,6 +295,13 @@ object Serialization {
JField("state", JString(state)) :: Nil) => new Id(id, version.toInt, typeName, state) JField("state", JString(state)) :: Nil) => new Id(id, version.toInt, typeName, state)
} }
def deserializeSystemAttributes(value: JValue)(implicit format : Formats) = value match {
case JObject(JField("createdBy", JString(createdBy))::
JField("modifiedBy", JString(modifiedBy))::
JField("createdTime", JString(createdTime))::
JField("modifiedTime", JString(modifiedTime))::Nil) => new AtlasSystemAttributes(createdBy, modifiedBy, createdTime, modifiedTime)
}
def toJson(value: ITypedReferenceableInstance): String = { def toJson(value: ITypedReferenceableInstance): String = {
implicit val formats = org.json4s.native.Serialization.formats(NoTypeHints) + new TypedStructSerializer + implicit val formats = org.json4s.native.Serialization.formats(NoTypeHints) + new TypedStructSerializer +
new TypedReferenceableInstanceSerializer + new BigDecimalSerializer + new BigIntegerSerializer new TypedReferenceableInstanceSerializer + new BigDecimalSerializer + new BigIntegerSerializer
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment