Commit 02e4e86b by Sarath Subramanian Committed by Madhan Neethiraj

ATLAS-1959: Enhance relationship attributes to support cardinality mappings

parent f74e43c2
...@@ -102,15 +102,15 @@ ...@@ -102,15 +102,15 @@
"endDef1": { "endDef1": {
"type": "DataSet", "type": "DataSet",
"name": "sourceToProcesses", "name": "sourceToProcesses",
"isContainer": "false", "isContainer": false,
"cardinality": "SET" "cardinality": "SET"
}, },
"endDef2": { "endDef2": {
"type": "Process", "type": "Process",
"name": "inputs", "name": "inputs",
"isContainer": "true", "isContainer": true,
"cardinality": "SET", "cardinality": "SET",
"legacyLabel": "__Process.inputs" "isLegacyAttribute": true
}, },
"propagateTags": "NONE" "propagateTags": "NONE"
}, },
...@@ -121,14 +121,14 @@ ...@@ -121,14 +121,14 @@
"endDef1": { "endDef1": {
"type": "Process", "type": "Process",
"name": "outputs", "name": "outputs",
"isContainer": "true", "isContainer": true,
"cardinality": "SET", "cardinality": "SET",
"legacyLabel": "__Process.outputs" "isLegacyAttribute": true
}, },
"endDef2": { "endDef2": {
"type": "DataSet", "type": "DataSet",
"name": "sinkFromProcesses", "name": "sinkFromProcesses",
"isContainer": "false", "isContainer": false,
"cardinality": "SET" "cardinality": "SET"
}, },
"propagateTags": "NONE" "propagateTags": "NONE"
......
...@@ -530,15 +530,15 @@ ...@@ -530,15 +530,15 @@
"endDef1": { "endDef1": {
"type": "hive_db", "type": "hive_db",
"name": "tables", "name": "tables",
"isContainer": "true", "isContainer": true,
"cardinality": "SET" "cardinality": "SET"
}, },
"endDef2": { "endDef2": {
"type": "hive_table", "type": "hive_table",
"name": "db", "name": "db",
"isContainer": "false", "isContainer": false,
"cardinality": "SINGLE", "cardinality": "SINGLE",
"legacyLabel": "__hive_table.db" "isLegacyAttribute": true
}, },
"propagateTags": "ONE_TO_TWO" "propagateTags": "ONE_TO_TWO"
}, },
...@@ -549,16 +549,16 @@ ...@@ -549,16 +549,16 @@
"endDef1": { "endDef1": {
"type": "hive_table", "type": "hive_table",
"name": "columns", "name": "columns",
"isContainer": "true", "isContainer": true,
"cardinality": "SET", "cardinality": "SET",
"legacyLabel": "__hive_table.columns" "isLegacyAttribute": true
}, },
"endDef2": { "endDef2": {
"type": "hive_column", "type": "hive_column",
"name": "table", "name": "table",
"isContainer": "false", "isContainer": false,
"cardinality": "SINGLE", "cardinality": "SINGLE",
"legacyLabel": "__hive_column.table" "isLegacyAttribute": true
}, },
"propagateTags": "ONE_TO_TWO" "propagateTags": "ONE_TO_TWO"
}, },
...@@ -569,16 +569,16 @@ ...@@ -569,16 +569,16 @@
"endDef1": { "endDef1": {
"type": "hive_table", "type": "hive_table",
"name": "partitionKeys", "name": "partitionKeys",
"isContainer": "true", "isContainer": true,
"cardinality": "SET", "cardinality": "SET",
"legacyLabel": "__hive_table.partitionKeys" "isLegacyAttribute": true
}, },
"endDef2": { "endDef2": {
"type": "hive_column", "type": "hive_column",
"name": "table", "name": "table",
"isContainer": "false", "isContainer": false,
"cardinality": "SINGLE", "cardinality": "SINGLE",
"legacyLabel": "__hive_column.table" "isLegacyAttribute": true
}, },
"propagateTags": "ONE_TO_TWO" "propagateTags": "ONE_TO_TWO"
}, },
...@@ -589,16 +589,16 @@ ...@@ -589,16 +589,16 @@
"endDef1": { "endDef1": {
"type": "hive_table", "type": "hive_table",
"name": "sd", "name": "sd",
"isContainer": "true", "isContainer": true,
"cardinality": "SINGLE", "cardinality": "SINGLE",
"legacyLabel": "__hive_table.sd" "isLegacyAttribute": true
}, },
"endDef2": { "endDef2": {
"type": "hive_storagedesc", "type": "hive_storagedesc",
"name": "table", "name": "table",
"isContainer": "false", "isContainer": false,
"cardinality": "SINGLE", "cardinality": "SINGLE",
"legacyLabel": "__hive_storagedesc.table" "isLegacyAttribute": true
}, },
"propagateTags": "ONE_TO_TWO" "propagateTags": "ONE_TO_TWO"
}, },
...@@ -609,15 +609,15 @@ ...@@ -609,15 +609,15 @@
"endDef1": { "endDef1": {
"type": "hive_process", "type": "hive_process",
"name": "columnLineages", "name": "columnLineages",
"isContainer": "true", "isContainer": true,
"cardinality": "SET" "cardinality": "SET"
}, },
"endDef2": { "endDef2": {
"type": "hive_column_lineage", "type": "hive_column_lineage",
"name": "query", "name": "query",
"isContainer": "false", "isContainer": false,
"cardinality": "SINGLE", "cardinality": "SINGLE",
"legacyLabel": "__hive_column_lineage.query" "isLegacyAttribute": true
}, },
"propagateTags": "NONE" "propagateTags": "NONE"
} }
......
...@@ -152,14 +152,14 @@ ...@@ -152,14 +152,14 @@
"endDef1": { "endDef1": {
"type": "falcon_feed", "type": "falcon_feed",
"name": "stored-in", "name": "stored-in",
"isContainer": "false", "isContainer": false,
"cardinality": "SINGLE", "cardinality": "SINGLE",
"legacyLabel": "__falcon_feed.stored-in" "isLegacyAttribute": true
}, },
"endDef2": { "endDef2": {
"type": "falcon_cluster", "type": "falcon_cluster",
"name": "feeds", "name": "feeds",
"isContainer": "true", "isContainer": true,
"cardinality": "SET" "cardinality": "SET"
}, },
"propagateTags": "NONE" "propagateTags": "NONE"
...@@ -171,15 +171,15 @@ ...@@ -171,15 +171,15 @@
"endDef1": { "endDef1": {
"type": "falcon_cluster", "type": "falcon_cluster",
"name": "processes", "name": "processes",
"isContainer": "true", "isContainer": true,
"cardinality": "SET" "cardinality": "SET"
}, },
"endDef2": { "endDef2": {
"type": "falcon_process", "type": "falcon_process",
"name": "runs-on", "name": "runs-on",
"isContainer": "false", "isContainer": false,
"cardinality": "SINGLE", "cardinality": "SINGLE",
"legacyLabel": "__falcon_process.runs-on" "isLegacyAttribute": true
}, },
"propagateTags": "NONE" "propagateTags": "NONE"
}, },
...@@ -190,15 +190,15 @@ ...@@ -190,15 +190,15 @@
"endDef1": { "endDef1": {
"type": "falcon_cluster", "type": "falcon_cluster",
"name": "feedCreations", "name": "feedCreations",
"isContainer": "true", "isContainer": true,
"cardinality": "SET" "cardinality": "SET"
}, },
"endDef2": { "endDef2": {
"type": "falcon_feed_creation", "type": "falcon_feed_creation",
"name": "stored-in", "name": "stored-in",
"isContainer": "false", "isContainer": false,
"cardinality": "SINGLE", "cardinality": "SINGLE",
"legacyLabel": "__falcon_feed_creation.stored-in" "isLegacyAttribute": true
}, },
"propagateTags": "NONE" "propagateTags": "NONE"
} }
......
...@@ -105,16 +105,16 @@ ...@@ -105,16 +105,16 @@
"endDef1": { "endDef1": {
"type": "hbase_table", "type": "hbase_table",
"name": "column_families", "name": "column_families",
"isContainer": "true", "isContainer": true,
"cardinality": "SET", "cardinality": "SET",
"legacyLabel": "__hbase_table.column_families" "isLegacyAttribute": true
}, },
"endDef2": { "endDef2": {
"type": "hbase_column_family", "type": "hbase_column_family",
"name": "table", "name": "table",
"isContainer": "false", "isContainer": false,
"cardinality": "SINGLE", "cardinality": "SINGLE",
"legacyLabel": "__hbase_column_family.table" "isLegacyAttribute": true
}, },
"propagateTags": "ONE_TO_TWO" "propagateTags": "ONE_TO_TWO"
}, },
...@@ -125,16 +125,16 @@ ...@@ -125,16 +125,16 @@
"endDef1": { "endDef1": {
"type": "hbase_column_family", "type": "hbase_column_family",
"name": "columns", "name": "columns",
"isContainer": "true", "isContainer": true,
"cardinality": "SET", "cardinality": "SET",
"legacyLabel": "__hbase_column_family.columns" "isLegacyAttribute": true
}, },
"endDef2": { "endDef2": {
"type": "hbase_column", "type": "hbase_column",
"name": "column_family", "name": "column_family",
"isContainer": "false", "isContainer": false,
"cardinality": "SINGLE", "cardinality": "SINGLE",
"legacyLabel": "__hbase_column.column_family" "isLegacyAttribute": true
}, },
"propagateTags": "ONE_TO_TWO" "propagateTags": "ONE_TO_TWO"
} }
......
...@@ -151,14 +151,14 @@ ...@@ -151,14 +151,14 @@
"endDef1": { "endDef1": {
"type": "storm_topology", "type": "storm_topology",
"name": "nodes", "name": "nodes",
"isContainer": "false", "isContainer": false,
"cardinality": "SET", "cardinality": "SET",
"legacyLabel": "__storm_topology.nodes" "isLegacyAttribute": true
}, },
"endDef2": { "endDef2": {
"type": "storm_node", "type": "storm_node",
"name": "topolgies", "name": "topolgies",
"isContainer": "false", "isContainer": false,
"cardinality": "SET" "cardinality": "SET"
}, },
"propagateTags": "NONE" "propagateTags": "NONE"
......
...@@ -177,7 +177,7 @@ public class AtlasEntity extends AtlasStruct implements Serializable { ...@@ -177,7 +177,7 @@ public class AtlasEntity extends AtlasStruct implements Serializable {
this.relationshipAttributes = relationshipAttributes; this.relationshipAttributes = relationshipAttributes;
} }
public void addRelationshipAttribute(String name, Object value) { public void setRelationshipAttribute(String name, Object value) {
Map<String, Object> r = this.relationshipAttributes; Map<String, Object> r = this.relationshipAttributes;
if (r != null) { if (r != null) {
...@@ -190,6 +190,18 @@ public class AtlasEntity extends AtlasStruct implements Serializable { ...@@ -190,6 +190,18 @@ public class AtlasEntity extends AtlasStruct implements Serializable {
} }
} }
public Object getRelationshipAttribute(String name) {
Map<String, Object> a = this.relationshipAttributes;
return a != null ? a.get(name) : null;
}
public boolean hasRelationshipAttribute(String name) {
Map<String, Object> r = this.relationshipAttributes;
return r != null ? r.containsKey(name) : false;
}
public List<AtlasClassification> getClassifications() { return classifications; } public List<AtlasClassification> getClassifications() { return classifications; }
public void setClassifications(List<AtlasClassification> classifications) { this.classifications = classifications; } public void setClassifications(List<AtlasClassification> classifications) { this.classifications = classifications; }
......
...@@ -176,8 +176,6 @@ public class AtlasRelationship extends AtlasStruct implements Serializable { ...@@ -176,8 +176,6 @@ public class AtlasRelationship extends AtlasStruct implements Serializable {
return "-" + Long.toString(s_nextId.getAndIncrement()); return "-" + Long.toString(s_nextId.getAndIncrement());
} }
public String getRelationshipLabel() { return "r:" + super.getTypeName(); }
private void init() { private void init() {
init(nextInternalId(), null, null, null, null, null, null, null, null, 0L); init(nextInternalId(), null, null, null, null, null, null, null, null, 0L);
} }
......
...@@ -219,6 +219,8 @@ public class AtlasRelationshipDef extends AtlasStructDef implements java.io.Seri ...@@ -219,6 +219,8 @@ public class AtlasRelationshipDef extends AtlasStructDef implements java.io.Seri
return this.endDef2; return this.endDef2;
} }
public String getRelationshipLabel() { return "r:" + super.getName(); }
public AtlasRelationshipDef(AtlasRelationshipDef other) throws AtlasBaseException { public AtlasRelationshipDef(AtlasRelationshipDef other) throws AtlasBaseException {
super(other); super(other);
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
package org.apache.atlas.model.typedef; package org.apache.atlas.model.typedef;
import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef.Cardinality; import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef.Cardinality;
import org.apache.commons.lang.StringUtils;
import org.codehaus.jackson.annotate.JsonAutoDetect; import org.codehaus.jackson.annotate.JsonAutoDetect;
import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.codehaus.jackson.map.annotate.JsonSerialize; import org.codehaus.jackson.map.annotate.JsonSerialize;
...@@ -61,9 +60,9 @@ public class AtlasRelationshipEndDef implements Serializable { ...@@ -61,9 +60,9 @@ public class AtlasRelationshipEndDef implements Serializable {
*/ */
private Cardinality cardinality; private Cardinality cardinality;
/** /**
* legacy edge label name of the endpoint * When set this indicates that this end is is a legacy attribute
*/ */
private String legacyLabel; private boolean isLegacyAttribute;
/** /**
* Base constructor * Base constructor
...@@ -97,15 +96,15 @@ public class AtlasRelationshipEndDef implements Serializable { ...@@ -97,15 +96,15 @@ public class AtlasRelationshipEndDef implements Serializable {
* - whether the end is a container or not * - whether the end is a container or not
*/ */
public AtlasRelationshipEndDef(String typeName, String name, Cardinality cardinality, boolean isContainer) { public AtlasRelationshipEndDef(String typeName, String name, Cardinality cardinality, boolean isContainer) {
this(typeName, name, cardinality, isContainer, null); this(typeName, name, cardinality, isContainer, false);
} }
public AtlasRelationshipEndDef(String typeName, String name, Cardinality cardinality, boolean isContainer, String legacyLabel) { public AtlasRelationshipEndDef(String typeName, String name, Cardinality cardinality, boolean isContainer, boolean isLegacyAttribute) {
setType(typeName); setType(typeName);
setName(name); setName(name);
setCardinality(cardinality); setCardinality(cardinality);
setIsContainer(isContainer); setIsContainer(isContainer);
setLegacyLabel(legacyLabel); setIsLegacyAttribute(isLegacyAttribute);
} }
/** /**
...@@ -118,7 +117,7 @@ public class AtlasRelationshipEndDef implements Serializable { ...@@ -118,7 +117,7 @@ public class AtlasRelationshipEndDef implements Serializable {
setName(other.getName()); setName(other.getName());
setIsContainer(other.getIsContainer()); setIsContainer(other.getIsContainer());
setCardinality(other.getCardinality()); setCardinality(other.getCardinality());
setLegacyLabel(other.getLegacyLabel()); setIsLegacyAttribute(other.isLegacyAttribute);
} }
} }
...@@ -166,11 +165,9 @@ public class AtlasRelationshipEndDef implements Serializable { ...@@ -166,11 +165,9 @@ public class AtlasRelationshipEndDef implements Serializable {
return this.cardinality; return this.cardinality;
} }
public String getLegacyLabel() { return legacyLabel; } public boolean getIsLegacyAttribute() { return isLegacyAttribute; }
public void setLegacyLabel(String legacyLabel) { this.legacyLabel = legacyLabel; } public void setIsLegacyAttribute(boolean legacyAttribute) { isLegacyAttribute = legacyAttribute; }
public boolean hasLegacyRelation() { return StringUtils.isNotEmpty(getLegacyLabel()) ? true : false; }
public StringBuilder toString(StringBuilder sb) { public StringBuilder toString(StringBuilder sb) {
if (sb == null) { if (sb == null) {
...@@ -182,7 +179,7 @@ public class AtlasRelationshipEndDef implements Serializable { ...@@ -182,7 +179,7 @@ public class AtlasRelationshipEndDef implements Serializable {
sb.append(", name==>'").append(name).append('\''); sb.append(", name==>'").append(name).append('\'');
sb.append(", isContainer==>'").append(isContainer).append('\''); sb.append(", isContainer==>'").append(isContainer).append('\'');
sb.append(", cardinality==>'").append(cardinality).append('\''); sb.append(", cardinality==>'").append(cardinality).append('\'');
sb.append(", legacyLabel==>'").append(legacyLabel).append('\''); sb.append(", isLegacyAttribute==>'").append(isLegacyAttribute).append('\'');
sb.append('}'); sb.append('}');
return sb; return sb;
...@@ -200,12 +197,12 @@ public class AtlasRelationshipEndDef implements Serializable { ...@@ -200,12 +197,12 @@ public class AtlasRelationshipEndDef implements Serializable {
Objects.equals(name, that.name) && Objects.equals(name, that.name) &&
isContainer == that.isContainer && isContainer == that.isContainer &&
cardinality == that.cardinality && cardinality == that.cardinality &&
Objects.equals(legacyLabel, that.legacyLabel); isLegacyAttribute == that.isLegacyAttribute;
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(type, getName(), isContainer, cardinality, legacyLabel); return Objects.hash(type, getName(), isContainer, cardinality, isLegacyAttribute);
} }
@Override @Override
......
...@@ -191,6 +191,8 @@ public class AtlasEntityType extends AtlasStructType { ...@@ -191,6 +191,8 @@ public class AtlasEntityType extends AtlasStructType {
public Map<String, AtlasAttribute> getRelationshipAttributes() { return relationshipAttributes; } public Map<String, AtlasAttribute> getRelationshipAttributes() { return relationshipAttributes; }
public AtlasAttribute getRelationshipAttribute(String attributeName) { return relationshipAttributes.get(attributeName); }
// this method should be called from AtlasRelationshipType.resolveReferencesPhase2() // this method should be called from AtlasRelationshipType.resolveReferencesPhase2()
void addRelationshipAttribute(String attributeName, AtlasAttribute attribute) { void addRelationshipAttribute(String attributeName, AtlasAttribute attribute) {
relationshipAttributes.put(attributeName, attribute); relationshipAttributes.put(attributeName, attribute);
...@@ -220,6 +222,16 @@ public class AtlasEntityType extends AtlasStructType { ...@@ -220,6 +222,16 @@ public class AtlasEntityType extends AtlasStructType {
return relationshipAttributes.containsKey(attributeName); return relationshipAttributes.containsKey(attributeName);
} }
public String getQualifiedAttributeName(String attrName) throws AtlasBaseException {
if (allAttributes.containsKey(attrName)) {
return allAttributes.get(attrName).getQualifiedName();
} else if (relationshipAttributes.containsKey(attrName)) {
return relationshipAttributes.get(attrName).getQualifiedName();
}
throw new AtlasBaseException(AtlasErrorCode.UNKNOWN_ATTRIBUTE, attrName, entityDef.getName());
}
@Override @Override
public AtlasEntity createDefaultValue() { public AtlasEntity createDefaultValue() {
AtlasEntity ret = new AtlasEntity(entityDef.getName()); AtlasEntity ret = new AtlasEntity(entityDef.getName());
......
...@@ -30,6 +30,10 @@ import org.apache.commons.lang.StringUtils; ...@@ -30,6 +30,10 @@ import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import static org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection;
import static org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection.IN;
import static org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection.OUT;
/** /**
* class that implements behaviour of an relationship-type. * class that implements behaviour of an relationship-type.
*/ */
...@@ -97,19 +101,41 @@ public class AtlasRelationshipType extends AtlasStructType { ...@@ -97,19 +101,41 @@ public class AtlasRelationshipType extends AtlasStructType {
// if legacyLabel is not specified at both ends, use relationshipDef name as relationship label. // if legacyLabel is not specified at both ends, use relationshipDef name as relationship label.
// if legacyLabel is specified in any one end, use it as the relationship label for both ends (legacy case). // if legacyLabel is specified in any one end, use it as the relationship label for both ends (legacy case).
// if legacyLabel is specified at both ends use the respective end's legacyLabel as relationship label (legacy case). // if legacyLabel is specified at both ends use the respective end's legacyLabel as relationship label (legacy case).
if (!endDef1.hasLegacyRelation() && !endDef2.hasLegacyRelation()) { if (!endDef1.getIsLegacyAttribute() && !endDef2.getIsLegacyAttribute()) {
relationshipLabel = relationshipDef.getName(); relationshipLabel = relationshipDef.getRelationshipLabel();
} else if (endDef1.getIsLegacyAttribute() && !endDef2.getIsLegacyAttribute()) {
} else if (endDef1.hasLegacyRelation() && !endDef2.hasLegacyRelation()) { relationshipLabel = getLegacyEdgeLabel(end1Type, endDef1.getName());
relationshipLabel = endDef1.getLegacyLabel(); } else if (!endDef1.getIsLegacyAttribute() && endDef2.getIsLegacyAttribute()) {
relationshipLabel = getLegacyEdgeLabel(end2Type, endDef2.getName());
} else if (!endDef1.hasLegacyRelation() && endDef2.hasLegacyRelation()) {
relationshipLabel = endDef2.getLegacyLabel();
} }
addRelationshipAttributeToEndType(endDef1, end1Type, end2Type.getTypeName(), typeRegistry, relationshipLabel); addRelationshipAttributeToEndType(endDef1, end1Type, end2Type.getTypeName(), typeRegistry, relationshipLabel);
addRelationshipAttributeToEndType(endDef2, end2Type, end1Type.getTypeName(), typeRegistry, relationshipLabel); addRelationshipAttributeToEndType(endDef2, end2Type, end1Type.getTypeName(), typeRegistry, relationshipLabel);
// add relationship edge direction information
addRelationshipEdgeDirection();
}
private void addRelationshipEdgeDirection() {
AtlasRelationshipEndDef endDef1 = relationshipDef.getEndDef1();
AtlasRelationshipEndDef endDef2 = relationshipDef.getEndDef2();
AtlasAttribute end1Attribute = end1Type.getRelationshipAttribute(endDef1.getName());
AtlasAttribute end2Attribute = end2Type.getRelationshipAttribute(endDef2.getName());
//default relationship edge direction is end1 (out) -> end2 (in)
AtlasRelationshipEdgeDirection end1Direction = OUT;
AtlasRelationshipEdgeDirection end2Direction = IN;
if (endDef1.getIsLegacyAttribute() && endDef2.getIsLegacyAttribute()) {
end2Direction = OUT;
} else if (!endDef1.getIsLegacyAttribute() && endDef2.getIsLegacyAttribute()) {
end1Direction = IN;
end2Direction = OUT;
}
end1Attribute.setRelationshipEdgeDirection(end1Direction);
end2Attribute.setRelationshipEdgeDirection(end2Direction);
} }
@Override @Override
...@@ -229,7 +255,7 @@ public class AtlasRelationshipType extends AtlasStructType { ...@@ -229,7 +255,7 @@ public class AtlasRelationshipType extends AtlasStructType {
// if relationshipLabel is null, then legacyLabel is mentioned at both ends, // if relationshipLabel is null, then legacyLabel is mentioned at both ends,
// use the respective end's legacyLabel as relationshipLabel // use the respective end's legacyLabel as relationshipLabel
if (relationshipLabel == null) { if (relationshipLabel == null) {
relationshipLabel = endDef.getLegacyLabel(); relationshipLabel = getLegacyEdgeLabel(entityType, attrName);
} }
if (attribute == null) { //attr doesn't exist in type - is a new relationship attribute if (attribute == null) { //attr doesn't exist in type - is a new relationship attribute
...@@ -251,4 +277,15 @@ public class AtlasRelationshipType extends AtlasStructType { ...@@ -251,4 +277,15 @@ public class AtlasRelationshipType extends AtlasStructType {
entityType.addRelationshipAttributeType(attrName, this); entityType.addRelationshipAttributeType(attrName, this);
} }
private String getLegacyEdgeLabel(AtlasEntityType entityType, String attributeName) {
String ret = null;
AtlasAttribute attribute = entityType.getAttribute(attributeName);
if (attribute != null) {
ret = "__" + attribute.getQualifiedName();
}
return ret;
}
} }
\ No newline at end of file
...@@ -610,6 +610,7 @@ public class AtlasStructType extends AtlasType { ...@@ -610,6 +610,7 @@ public class AtlasStructType extends AtlasType {
private final String inverseRefAttributeName; private final String inverseRefAttributeName;
private AtlasAttribute inverseRefAttribute; private AtlasAttribute inverseRefAttribute;
private String relationshipEdgeLabel; private String relationshipEdgeLabel;
private AtlasRelationshipEdgeDirection relationshipEdgeDirection;
public AtlasAttribute(AtlasStructType definedInType, AtlasAttributeDef attrDef, AtlasType attributeType, String relationshipLabel) { public AtlasAttribute(AtlasStructType definedInType, AtlasAttributeDef attrDef, AtlasType attributeType, String relationshipLabel) {
this.definedInType = definedInType; this.definedInType = definedInType;
...@@ -639,6 +640,7 @@ public class AtlasStructType extends AtlasType { ...@@ -639,6 +640,7 @@ public class AtlasStructType extends AtlasType {
this.isOwnedRef = isOwnedRef; this.isOwnedRef = isOwnedRef;
this.inverseRefAttributeName = inverseRefAttribute; this.inverseRefAttributeName = inverseRefAttribute;
this.relationshipEdgeDirection = AtlasRelationshipEdgeDirection.OUT;
} }
public AtlasAttribute(AtlasStructType definedInType, AtlasAttributeDef attrDef, AtlasType attributeType) { public AtlasAttribute(AtlasStructType definedInType, AtlasAttributeDef attrDef, AtlasType attributeType) {
...@@ -677,6 +679,12 @@ public class AtlasStructType extends AtlasType { ...@@ -677,6 +679,12 @@ public class AtlasStructType extends AtlasType {
public void setRelationshipEdgeLabel(String relationshipEdgeLabel) { this.relationshipEdgeLabel = relationshipEdgeLabel; } public void setRelationshipEdgeLabel(String relationshipEdgeLabel) { this.relationshipEdgeLabel = relationshipEdgeLabel; }
public AtlasRelationshipEdgeDirection getRelationshipEdgeDirection() { return relationshipEdgeDirection; }
public void setRelationshipEdgeDirection(AtlasRelationshipEdgeDirection relationshipEdgeDirection) {
this.relationshipEdgeDirection = relationshipEdgeDirection;
}
public static String getEdgeLabel(String property) { public static String getEdgeLabel(String property) {
return "__" + property; return "__" + property;
} }
...@@ -721,5 +729,7 @@ public class AtlasStructType extends AtlasType { ...@@ -721,5 +729,7 @@ public class AtlasStructType extends AtlasType {
new String[] { "$", "_d" }, new String[] { "$", "_d" },
new String[] { "%", "_p" }, new String[] { "%", "_p" },
}; };
public enum AtlasRelationshipEdgeDirection { IN, OUT }
} }
} }
...@@ -35,7 +35,6 @@ import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef; ...@@ -35,7 +35,6 @@ import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef;
import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef.Cardinality; import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef.Cardinality;
import org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef; import org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef;
import org.apache.atlas.model.typedef.AtlasTypesDef; import org.apache.atlas.model.typedef.AtlasTypesDef;
import org.apache.atlas.type.AtlasStructType;
import org.apache.atlas.type.AtlasTypeUtil; import org.apache.atlas.type.AtlasTypeUtil;
import org.apache.commons.lang.RandomStringUtils; import org.apache.commons.lang.RandomStringUtils;
......
...@@ -26,8 +26,10 @@ import org.apache.atlas.AtlasException; ...@@ -26,8 +26,10 @@ import org.apache.atlas.AtlasException;
import org.apache.atlas.RequestContext; import org.apache.atlas.RequestContext;
import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.instance.AtlasEntity.Status; import org.apache.atlas.model.instance.AtlasEntity.Status;
import org.apache.atlas.model.instance.AtlasObjectId;
import org.apache.atlas.model.instance.AtlasRelationship; import org.apache.atlas.model.instance.AtlasRelationship;
import org.apache.atlas.model.typedef.AtlasRelationshipDef; import org.apache.atlas.model.typedef.AtlasRelationshipDef;
import org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection;
import org.apache.atlas.repository.Constants; import org.apache.atlas.repository.Constants;
import org.apache.atlas.repository.RepositoryException; import org.apache.atlas.repository.RepositoryException;
import org.apache.atlas.repository.graphdb.AtlasEdge; import org.apache.atlas.repository.graphdb.AtlasEdge;
...@@ -39,6 +41,7 @@ import org.apache.atlas.repository.graphdb.AtlasVertex; ...@@ -39,6 +41,7 @@ import org.apache.atlas.repository.graphdb.AtlasVertex;
import org.apache.atlas.repository.store.graph.v1.AtlasGraphUtilsV1; import org.apache.atlas.repository.store.graph.v1.AtlasGraphUtilsV1;
import org.apache.atlas.type.AtlasEntityType; import org.apache.atlas.type.AtlasEntityType;
import org.apache.atlas.type.AtlasRelationshipType; import org.apache.atlas.type.AtlasRelationshipType;
import org.apache.atlas.type.AtlasStructType;
import org.apache.atlas.type.AtlasType; import org.apache.atlas.type.AtlasType;
import org.apache.atlas.typesystem.IReferenceableInstance; import org.apache.atlas.typesystem.IReferenceableInstance;
import org.apache.atlas.typesystem.ITypedInstance; import org.apache.atlas.typesystem.ITypedInstance;
...@@ -344,12 +347,46 @@ public final class GraphHelper { ...@@ -344,12 +347,46 @@ public final class GraphHelper {
return null; return null;
} }
public Iterator<AtlasEdge> getIncomingEdgesByLabel(AtlasVertex instanceVertex, String edgeLabel) {
return getAdjacentEdgesByLabel(instanceVertex, AtlasEdgeDirection.IN, edgeLabel);
}
public Iterator<AtlasEdge> getOutGoingEdgesByLabel(AtlasVertex instanceVertex, String edgeLabel) { public Iterator<AtlasEdge> getOutGoingEdgesByLabel(AtlasVertex instanceVertex, String edgeLabel) {
return getAdjacentEdgesByLabel(instanceVertex, AtlasEdgeDirection.OUT, edgeLabel); return getAdjacentEdgesByLabel(instanceVertex, AtlasEdgeDirection.OUT, edgeLabel);
} }
public Iterator<AtlasEdge> getBothEdgesByLabel(AtlasVertex instanceVertex, String edgeLabel) { public AtlasEdge getEdgeForLabel(AtlasVertex vertex, String edgeLabel, AtlasRelationshipEdgeDirection edgeDirection) {
return getAdjacentEdgesByLabel(instanceVertex, AtlasEdgeDirection.BOTH, edgeLabel); AtlasEdge ret;
switch (edgeDirection) {
case IN:
ret = getEdgeForLabel(vertex, edgeLabel, AtlasEdgeDirection.IN);
break;
case OUT:
default:
ret = getEdgeForLabel(vertex, edgeLabel, AtlasEdgeDirection.OUT);
break;
}
return ret;
}
public Iterator<AtlasEdge> getEdgesForLabel(AtlasVertex vertex, String edgeLabel, AtlasRelationshipEdgeDirection edgeDirection) {
Iterator<AtlasEdge> ret;
switch (edgeDirection) {
case IN:
ret = getIncomingEdgesByLabel(vertex, edgeLabel);
break;
case OUT:
default:
ret = getOutGoingEdgesByLabel(vertex, edgeLabel);
break;
}
return ret;
} }
/** /**
...@@ -360,7 +397,11 @@ public final class GraphHelper { ...@@ -360,7 +397,11 @@ public final class GraphHelper {
* @return * @return
*/ */
public AtlasEdge getEdgeForLabel(AtlasVertex vertex, String edgeLabel) { public AtlasEdge getEdgeForLabel(AtlasVertex vertex, String edgeLabel) {
Iterator<AtlasEdge> iterator = getAdjacentEdgesByLabel(vertex, AtlasEdgeDirection.OUT, edgeLabel); return getEdgeForLabel(vertex, edgeLabel, AtlasEdgeDirection.OUT);
}
public AtlasEdge getEdgeForLabel(AtlasVertex vertex, String edgeLabel, AtlasEdgeDirection edgeDirection) {
Iterator<AtlasEdge> iterator = getAdjacentEdgesByLabel(vertex, edgeDirection, edgeLabel);
AtlasEdge latestDeletedEdge = null; AtlasEdge latestDeletedEdge = null;
long latestDeletedEdgeTime = Long.MIN_VALUE; long latestDeletedEdgeTime = Long.MIN_VALUE;
...@@ -1280,4 +1321,43 @@ public final class GraphHelper { ...@@ -1280,4 +1321,43 @@ public final class GraphHelper {
return ret; return ret;
} }
public static boolean isRelationshipEdge(AtlasEdge edge) {
if (edge == null) {
return false;
}
String edgeLabel = edge.getLabel();
return StringUtils.isNotEmpty(edge.getLabel()) ? edgeLabel.startsWith("r:") : false;
}
public static AtlasObjectId getReferenceObjectId(AtlasEdge edge, AtlasRelationshipEdgeDirection relationshipDirection) {
AtlasObjectId ret = null;
if (relationshipDirection == AtlasRelationshipEdgeDirection.OUT) {
ret = new AtlasObjectId(getGuid(edge.getInVertex()), getTypeName(edge.getInVertex()));
} else if (relationshipDirection == AtlasRelationshipEdgeDirection.IN) {
ret = new AtlasObjectId(getGuid(edge.getOutVertex()), getTypeName(edge.getOutVertex()));
}
return ret;
}
public static AtlasObjectId getCurrentObjectId(AtlasEdge edge, AtlasRelationshipEdgeDirection relationshipDirection) {
String typeName = null;
String guid = null;
if (relationshipDirection == AtlasRelationshipEdgeDirection.OUT) {
typeName = GraphHelper.getTypeName(edge.getOutVertex());
guid = GraphHelper.getGuid(edge.getOutVertex());
} else if (relationshipDirection == AtlasRelationshipEdgeDirection.IN) {
typeName = GraphHelper.getTypeName(edge.getInVertex());
guid = GraphHelper.getGuid(edge.getInVertex());
}
return new AtlasObjectId(guid, typeName);
}
} }
\ No newline at end of file
...@@ -286,7 +286,7 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery { ...@@ -286,7 +286,7 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery {
return; return;
} }
AtlasStruct struct; final AtlasStruct struct;
if (val instanceof AtlasStruct) { if (val instanceof AtlasStruct) {
struct = (AtlasStruct) val; struct = (AtlasStruct) val;
...@@ -298,6 +298,10 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery { ...@@ -298,6 +298,10 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery {
throw new AtlasBaseException(AtlasErrorCode.INVALID_STRUCT_VALUE, val.toString()); throw new AtlasBaseException(AtlasErrorCode.INVALID_STRUCT_VALUE, val.toString());
} }
visitStruct(structType, struct);
}
void visitStruct(AtlasStructType structType, AtlasStruct struct) throws AtlasBaseException {
for (AtlasAttribute attribute : structType.getAllAttributes().values()) { for (AtlasAttribute attribute : structType.getAllAttributes().values()) {
AtlasType attrType = attribute.getAttributeType(); AtlasType attrType = attribute.getAttributeType();
Object attrVal = struct.getAttribute(attribute.getName()); Object attrVal = struct.getAttribute(attribute.getName());
...@@ -306,6 +310,16 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery { ...@@ -306,6 +310,16 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery {
} }
} }
void visitEntity(AtlasEntityType entityType, AtlasEntity entity) throws AtlasBaseException {
visitStruct(entityType, entity);
for (AtlasAttribute attribute : entityType.getRelationshipAttributes().values()) {
AtlasType attrType = attribute.getAttributeType();
Object attrVal = entity.getRelationshipAttribute(attribute.getName());
visitAttribute(attrType, attrVal);
}
}
void walkEntityGraph(AtlasEntity entity) throws AtlasBaseException { void walkEntityGraph(AtlasEntity entity) throws AtlasBaseException {
if (entity == null) { if (entity == null) {
...@@ -316,7 +330,7 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery { ...@@ -316,7 +330,7 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery {
recordObjectReference(entity.getGuid()); recordObjectReference(entity.getGuid());
visitStruct(type, entity); visitEntity(type, entity);
} }
......
...@@ -94,8 +94,8 @@ public class AtlasGraphUtilsV1 { ...@@ -94,8 +94,8 @@ public class AtlasGraphUtilsV1 {
public static String getQualifiedAttributePropertyKey(AtlasStructType fromType, String attributeName) throws AtlasBaseException { public static String getQualifiedAttributePropertyKey(AtlasStructType fromType, String attributeName) throws AtlasBaseException {
switch (fromType.getTypeCategory()) { switch (fromType.getTypeCategory()) {
case STRUCT:
case ENTITY: case ENTITY:
case STRUCT:
case CLASSIFICATION: case CLASSIFICATION:
return fromType.getQualifiedAttributeName(attributeName); return fromType.getQualifiedAttributeName(attributeName);
default: default:
......
...@@ -37,6 +37,7 @@ import org.apache.atlas.type.AtlasEntityType; ...@@ -37,6 +37,7 @@ import org.apache.atlas.type.AtlasEntityType;
import org.apache.atlas.type.AtlasMapType; import org.apache.atlas.type.AtlasMapType;
import org.apache.atlas.type.AtlasStructType; import org.apache.atlas.type.AtlasStructType;
import org.apache.atlas.type.AtlasStructType.AtlasAttribute; import org.apache.atlas.type.AtlasStructType.AtlasAttribute;
import org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection;
import org.apache.atlas.type.AtlasType; import org.apache.atlas.type.AtlasType;
import org.apache.atlas.type.AtlasTypeRegistry; import org.apache.atlas.type.AtlasTypeRegistry;
import org.slf4j.Logger; import org.slf4j.Logger;
...@@ -53,6 +54,8 @@ import java.util.Set; ...@@ -53,6 +54,8 @@ import java.util.Set;
import java.util.Stack; import java.util.Stack;
import static org.apache.atlas.repository.graph.GraphHelper.EDGE_LABEL_PREFIX; import static org.apache.atlas.repository.graph.GraphHelper.EDGE_LABEL_PREFIX;
import static org.apache.atlas.repository.graph.GraphHelper.getReferenceObjectId;
import static org.apache.atlas.repository.graph.GraphHelper.isRelationshipEdge;
import static org.apache.atlas.repository.graph.GraphHelper.string; import static org.apache.atlas.repository.graph.GraphHelper.string;
public abstract class DeleteHandlerV1 { public abstract class DeleteHandlerV1 {
...@@ -206,7 +209,6 @@ public abstract class DeleteHandlerV1 { ...@@ -206,7 +209,6 @@ public abstract class DeleteHandlerV1 {
return result; return result;
} }
/** /**
* Force delete is used to remove struct/trait in case of entity updates * Force delete is used to remove struct/trait in case of entity updates
* @param edge * @param edge
...@@ -218,6 +220,13 @@ public abstract class DeleteHandlerV1 { ...@@ -218,6 +220,13 @@ public abstract class DeleteHandlerV1 {
*/ */
public boolean deleteEdgeReference(AtlasEdge edge, TypeCategory typeCategory, boolean isOwned, public boolean deleteEdgeReference(AtlasEdge edge, TypeCategory typeCategory, boolean isOwned,
boolean forceDeleteStructTrait) throws AtlasBaseException { boolean forceDeleteStructTrait) throws AtlasBaseException {
// default edge direction is outward
return deleteEdgeReference(edge, typeCategory, isOwned, forceDeleteStructTrait, AtlasRelationshipEdgeDirection.OUT);
}
public boolean deleteEdgeReference(AtlasEdge edge, TypeCategory typeCategory, boolean isOwned, boolean forceDeleteStructTrait,
AtlasRelationshipEdgeDirection relationshipDirection) throws AtlasBaseException {
LOG.debug("Deleting {}", string(edge)); LOG.debug("Deleting {}", string(edge));
boolean forceDelete = boolean forceDelete =
(typeCategory == TypeCategory.STRUCT || typeCategory == TypeCategory.CLASSIFICATION) && forceDeleteStructTrait; (typeCategory == TypeCategory.STRUCT || typeCategory == TypeCategory.CLASSIFICATION) && forceDeleteStructTrait;
...@@ -236,10 +245,20 @@ public abstract class DeleteHandlerV1 { ...@@ -236,10 +245,20 @@ public abstract class DeleteHandlerV1 {
//If the vertex is of type class, and its not a composite attributes, the reference AtlasVertex' lifecycle is not controlled //If the vertex is of type class, and its not a composite attributes, the reference AtlasVertex' lifecycle is not controlled
//through this delete. Hence just remove the reference edge. Leave the reference AtlasVertex as is //through this delete. Hence just remove the reference edge. Leave the reference AtlasVertex as is
// for relationship edges, inverse vertex's relationship attribute doesn't need to be updated.
// only delete the reference relationship edge
if (isRelationshipEdge(edge)) {
deleteEdge(edge, false);
AtlasObjectId deletedReferenceObjectId = getReferenceObjectId(edge, relationshipDirection);
RequestContextV1.get().recordEntityUpdate(deletedReferenceObjectId);
} else {
//legacy case - not a relationship edge
//If deleting just the edge, reverse attribute should be updated for any references //If deleting just the edge, reverse attribute should be updated for any references
//For example, for the department type system, if the person's manager edge is deleted, subordinates of manager should be updated //For example, for the department type system, if the person's manager edge is deleted, subordinates of manager should be updated
deleteEdge(edge, true, false); deleteEdge(edge, true, false);
} }
}
return !softDelete || forceDelete; return !softDelete || forceDelete;
} }
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
package org.apache.atlas.repository.impexp; package org.apache.atlas.repository.impexp;
import com.google.inject.Inject; import com.google.inject.Inject;
import org.apache.atlas.RequestContextV1;
import org.apache.atlas.TestModules; import org.apache.atlas.TestModules;
import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.impexp.AtlasImportRequest; import org.apache.atlas.model.impexp.AtlasImportRequest;
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
package org.apache.atlas.repository.impexp; package org.apache.atlas.repository.impexp;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import org.apache.atlas.RequestContextV1;
import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.impexp.AtlasExportResult; import org.apache.atlas.model.impexp.AtlasExportResult;
import org.apache.atlas.model.impexp.AtlasImportRequest; import org.apache.atlas.model.impexp.AtlasImportRequest;
...@@ -149,6 +150,8 @@ public class ZipFileResourceTestUtils { ...@@ -149,6 +150,8 @@ public class ZipFileResourceTestUtils {
AtlasExportResult exportResult = zipSource.getExportResult(); AtlasExportResult exportResult = zipSource.getExportResult();
List<String> creationOrder = zipSource.getCreationOrder(); List<String> creationOrder = zipSource.getCreationOrder();
RequestContextV1.clear();
AtlasImportRequest request = getDefaultImportRequest(); AtlasImportRequest request = getDefaultImportRequest();
AtlasImportResult result = runImportWithParameters(importService, request, zipSource); AtlasImportResult result = runImportWithParameters(importService, request, zipSource);
......
/**
* 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.repository.store.graph.v1;
import com.google.common.collect.ImmutableList;
import org.apache.atlas.TestModules;
import org.apache.atlas.model.instance.AtlasEntity;
import org.testng.annotations.Guice;
import static org.apache.atlas.type.AtlasTypeUtil.getAtlasObjectId;
/**
* Inverse reference update test with {@link HardDeleteHandlerV1}
*/
@Guice(modules = TestModules.HardDeleteModule.class)
public class AtlasRelationshipStoreHardDeleteV1Test extends AtlasRelationshipStoreV1Test {
@Override
protected void verifyRelationshipAttributeUpdate_NonComposite_OneToMany(AtlasEntity jane) throws Exception {
// Max should have been removed from the subordinates list, leaving only John.
verifyRelationshipAttributeList(jane, "subordinates", ImmutableList.of(employeeNameIdMap.get("John")));
}
@Override
protected void verifyRelationshipAttributeUpdate_NonComposite_ManyToOne(AtlasEntity a1, AtlasEntity a2,
AtlasEntity a3, AtlasEntity b) {
verifyRelationshipAttributeValue(a1, "oneB", null);
verifyRelationshipAttributeValue(a2, "oneB", null);
verifyRelationshipAttributeList(b, "manyA", ImmutableList.of(getAtlasObjectId(a3)));
}
@Override
protected void verifyRelationshipAttributeUpdate_NonComposite_OneToOne(AtlasEntity a1, AtlasEntity b) {
verifyRelationshipAttributeValue(a1, "b", null);
}
}
/**
* 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.repository.store.graph.v1;
import com.google.common.collect.ImmutableList;
import org.apache.atlas.TestModules;
import org.apache.atlas.model.instance.AtlasEntity;
import org.testng.annotations.Guice;
import static org.apache.atlas.type.AtlasTypeUtil.getAtlasObjectId;
/**
* Inverse reference update test with {@link SoftDeleteHandlerV1}
*/
@Guice(modules = TestModules.SoftDeleteModule.class)
public class AtlasRelationshipStoreSoftDeleteV1Test extends AtlasRelationshipStoreV1Test {
@Override
protected void verifyRelationshipAttributeUpdate_NonComposite_OneToMany(AtlasEntity jane) throws Exception {
// Max is still in the subordinates list, as the edge still exists with state DELETED
verifyRelationshipAttributeList(jane, "subordinates", ImmutableList.of(employeeNameIdMap.get("John"), employeeNameIdMap.get("Max")));
}
@Override
protected void verifyRelationshipAttributeUpdate_NonComposite_ManyToOne(AtlasEntity a1, AtlasEntity a2,
AtlasEntity a3, AtlasEntity b) {
verifyRelationshipAttributeValue(a1, "oneB", b.getGuid());
verifyRelationshipAttributeValue(a2, "oneB", b.getGuid());
verifyRelationshipAttributeList(b, "manyA", ImmutableList.of(getAtlasObjectId(a1), getAtlasObjectId(a2), getAtlasObjectId(a3)));
}
@Override
protected void verifyRelationshipAttributeUpdate_NonComposite_OneToOne(AtlasEntity a1, AtlasEntity b) {
verifyRelationshipAttributeValue(a1, "b", b.getGuid());
}
}
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