Commit 48477e20 by Madhan Neethiraj

ATLAS-1526: removed foreignKey/mappedFromRef constraints and brought back

legacy flags isComposite/reverseAttributeName using constraints ownedRef/inverseRef(attribute=attr1)
parent 5f508c97
......@@ -215,12 +215,9 @@
"name": "sd",
"typeName": "hive_storagedesc",
"cardinality": "SINGLE",
"constraintDefs": [
"constraints": [
{
"type": "mappedFromRef",
"params": {
"refAttribute": "table"
}
"type": "ownedRef"
}
],
"isIndexable": false,
......@@ -231,7 +228,11 @@
"name": "partitionKeys",
"typeName": "array<hive_column>",
"cardinality": "SINGLE",
"constraintDefs": [],
"constraints": [
{
"type": "ownedRef"
}
],
"isIndexable": false,
"isOptional": true,
"isUnique": false
......@@ -248,7 +249,11 @@
"name": "columns",
"typeName": "array<hive_column>",
"cardinality": "SINGLE",
"constraintDefs": [],
"constraints": [
{
"type": "ownedRef"
}
],
"isIndexable": false,
"isOptional": true,
"isUnique": false
......@@ -306,11 +311,11 @@
"name": "table",
"typeName": "hive_table",
"cardinality": "SINGLE",
"constraintDefs": [
"constraints": [
{
"type": "foreignKey",
"type": "inverseRef",
"params": {
"onDelete": "cascade"
"attribute": "sd"
}
}
],
......@@ -469,11 +474,11 @@
"name": "table",
"typeName": "hive_table",
"cardinality": "SINGLE",
"constraintDefs": [
"constraints": [
{
"type": "foreignKey",
"type": "inverseRef",
"params": {
"onDelete": "cascade"
"attribute": "columns"
}
}
],
......
......@@ -17,7 +17,20 @@
"isIndexable": false,
"isOptional": false,
"isUnique": false
},
{
"name": "column_families",
"typeName": "array<hbase_column_family>",
"cardinality": "SINGLE",
"constraints": [
{
"type": "ownedRef"
}
],
"isIndexable": false,
"isOptional": true,
"isUnique": false
},
]
},
{
......@@ -33,14 +46,27 @@
"isIndexable": false,
"isOptional": false,
"isUnique": false,
"constraintDefs": [
"constraints": [
{
"type": "foreignKey",
"type": "inverseRef",
"params": {
"onDelete": "cascade"
"attribute": "column_families"
}
}
]
},
{
"name": "columns",
"typeName": "array<hbase_column>",
"cardinality": "SINGLE",
"constraints": [
{
"type": "ownedRef"
}
],
"isIndexable": false,
"isOptional": true,
"isUnique": false
}
],
"typeVersion": "1.0"
......@@ -58,11 +84,11 @@
"isIndexable": false,
"isOptional": false,
"isUnique": false,
"constraintDefs": [
"constraints": [
{
"type": "foreignKey",
"type": "inverseRef",
"params": {
"onDelete": "cascade"
"attribute": "columns"
}
}
]
......
......@@ -54,7 +54,7 @@
"name": "nodes",
"typeName": "array<storm_node>",
"cardinality": "LIST",
"constraintDefs": [],
"constraints": [],
"isIndexable": false,
"isOptional": false,
"isUnique": false
......
......@@ -55,6 +55,10 @@ public enum AtlasErrorCode {
TYPE_NAME_INVALID_FORMAT(400, "ATLAS40025E", "{0}: invalid name for {1}. Names must consist of a letter followed by a sequence of letter, number, or '_' characters"),
INVALID_PARAMETERS(400, "ATLAS40025E", "invalid parameters: {0}"),
CLASSIFICATION_ALREADY_ASSOCIATED(400, "ATLAS40026E", "instance {0} already is associated with classification {1}"),
CONSTRAINT_INVERSE_REF_ATTRIBUTE_INVALID_TYPE(400, "ATLAS40027E", "{0}.{1}: invalid {2} constraint. Attribute {3} is not an entity type"),
CONSTRAINT_INVERSE_REF_INVERSE_ATTRIBUTE_NON_EXISTING(400, "ATLAS40028E", "{0}.{1}: invalid {2} constraint. Inverse attribute {3}.{4} does not exist"),
CONSTRAINT_INVERSE_REF_INVERSE_ATTRIBUTE_INVALID_TYPE(400, "ATLAS40029E", "{0}.{1}: invalid {2} constraint. Inverse attribute {3}.{4} is not an entity type"),
CONSTRAINT_OWNED_REF_ATTRIBUTE_INVALID_TYPE(400, "ATLAS40030E", "{0}.{1}: invalid {2} constraint. Attribute {3} is not an entity type"),
// All Not found enums go here
TYPE_NAME_NOT_FOUND(404, "ATLAS4041E", "Given typename {0} was invalid"),
......
......@@ -42,6 +42,8 @@ import org.apache.hadoop.util.StringUtils;
import org.codehaus.jackson.annotate.JsonAutoDetect;
import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.PUBLIC_ONLY;
import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.NONE;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.codehaus.jackson.map.annotate.JsonSerialize;
......@@ -269,7 +271,7 @@ public class AtlasStructDef extends AtlasBaseTypeDef implements Serializable {
private int valuesMaxCount;
private boolean isUnique;
private boolean isIndexable;
private List<AtlasConstraintDef> constraintDefs;
private List<AtlasConstraintDef> constraints;
public AtlasAttributeDef() { this(null, null); }
......@@ -279,7 +281,7 @@ public class AtlasStructDef extends AtlasBaseTypeDef implements Serializable {
public AtlasAttributeDef(String name, String typeName, boolean isOptional, Cardinality cardinality,
int valuesMinCount, int valuesMaxCount, boolean isUnique, boolean isIndexable,
List<AtlasConstraintDef> constraintDefs) {
List<AtlasConstraintDef> constraints) {
setName(name);
setTypeName(typeName);
setIsOptional(isOptional);
......@@ -288,7 +290,7 @@ public class AtlasStructDef extends AtlasBaseTypeDef implements Serializable {
setValuesMaxCount(valuesMaxCount);
setIsUnique(isUnique);
setIsIndexable(isIndexable);
setConstraintDefs(constraintDefs);
setConstraints(constraints);
}
public AtlasAttributeDef(AtlasAttributeDef other) {
......@@ -301,7 +303,7 @@ public class AtlasStructDef extends AtlasBaseTypeDef implements Serializable {
setValuesMaxCount(other.getValuesMaxCount());
setIsUnique(other.getIsUnique());
setIsIndexable(other.getIsIndexable());
setConstraintDefs(other.getConstraintDefs());
setConstraints(other.getConstraints());
}
}
......@@ -367,33 +369,34 @@ public class AtlasStructDef extends AtlasBaseTypeDef implements Serializable {
isIndexable = idexable;
}
public List<AtlasConstraintDef> getConstraintDefs() { return constraintDefs; }
public List<AtlasConstraintDef> getConstraints() { return constraints; }
public void setConstraintDefs(List<AtlasConstraintDef> constraintDefs) {
if (this.constraintDefs != null && this.constraintDefs == constraintDefs) {
public void setConstraints(List<AtlasConstraintDef> constraints) {
if (this.constraints != null && this.constraints == constraints) {
return;
}
if (CollectionUtils.isEmpty(constraintDefs)) {
this.constraintDefs = null;
if (CollectionUtils.isEmpty(constraints)) {
this.constraints = null;
} else {
this.constraintDefs = new ArrayList<>(constraintDefs);
this.constraints = new ArrayList<>(constraints);
}
}
public void addConstraint(AtlasConstraintDef constraintDef) {
List<AtlasConstraintDef> cDefs = constraintDefs;
List<AtlasConstraintDef> cDefs = constraints;
if (cDefs == null) {
cDefs = new ArrayList<>();
this.constraints = cDefs;
} else {
cDefs = new ArrayList<>(cDefs);
}
cDefs.add(constraintDef);
this.constraintDefs = cDefs;
}
public StringBuilder toString(StringBuilder sb) {
if (sb == null) {
sb = new StringBuilder();
......@@ -408,10 +411,10 @@ public class AtlasStructDef extends AtlasBaseTypeDef implements Serializable {
sb.append(", valuesMaxCount=").append(valuesMaxCount);
sb.append(", isUnique=").append(isUnique);
sb.append(", isIndexable=").append(isIndexable);
sb.append(", constraintDefs=[");
if (CollectionUtils.isNotEmpty(constraintDefs)) {
sb.append(", constraints=[");
if (CollectionUtils.isNotEmpty(constraints)) {
int i = 0;
for (AtlasConstraintDef constraintDef : constraintDefs) {
for (AtlasConstraintDef constraintDef : constraints) {
constraintDef.toString(sb);
if (i > 0) {
sb.append(", ");
......@@ -438,12 +441,12 @@ public class AtlasStructDef extends AtlasBaseTypeDef implements Serializable {
Objects.equals(name, that.name) &&
Objects.equals(typeName, that.typeName) &&
cardinality == that.cardinality &&
Objects.equals(constraintDefs, that.constraintDefs);
Objects.equals(constraints, that.constraints);
}
@Override
public int hashCode() {
return Objects.hash(name, typeName, isOptional, cardinality, valuesMinCount, valuesMaxCount, isUnique, isIndexable, constraintDefs);
return Objects.hash(name, typeName, isOptional, cardinality, valuesMinCount, valuesMaxCount, isUnique, isIndexable, constraints);
}
@Override
......@@ -465,11 +468,9 @@ public class AtlasStructDef extends AtlasBaseTypeDef implements Serializable {
public static class AtlasConstraintDef implements Serializable {
private static final long serialVersionUID = 1L;
public static final String CONSTRAINT_TYPE_FOREIGN_KEY = "foreignKey";
public static final String CONSTRAINT_TYPE_MAPPED_FROM_REF = "mappedFromRef";
public static final String CONSTRAINT_PARAM_REF_ATTRIBUTE = "refAttribute";
public static final String CONSTRAINT_PARAM_ON_DELETE = "onDelete";
public static final String CONSTRAINT_PARAM_VAL_CASCADE = "cascade";
public static final String CONSTRAINT_TYPE_OWNED_REF = "ownedRef";
public static final String CONSTRAINT_TYPE_INVERSE_REF = "inverseRef";
public static final String CONSTRAINT_PARAM_ATTRIBUTE = "attribute";
private String type; // foreignKey/mappedFromRef/valueInRange
private Map<String, Object> params; // onDelete=cascade/refAttribute=attr2/min=0,max=23
......@@ -515,6 +516,18 @@ public class AtlasStructDef extends AtlasBaseTypeDef implements Serializable {
this.params = params;
}
@JsonIgnore
public boolean isConstraintType(String name) {
return StringUtils.equalsIgnoreCase(name, this.type);
}
@JsonIgnore
public Object getParam(String name) {
Map<String, Object> params = this.params;
return params != null ? params.get(name) : null;
}
public StringBuilder toString(StringBuilder sb) {
if (sb == null) {
sb = new StringBuilder();
......
......@@ -24,15 +24,12 @@ import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.instance.AtlasObjectId;
import org.apache.atlas.model.typedef.AtlasEntityDef;
import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef;
import org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
......@@ -40,7 +37,6 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef.*;
/**
* class that implements behaviour of an entity-type.
......@@ -53,8 +49,6 @@ public class AtlasEntityType extends AtlasStructType {
private List<AtlasEntityType> superTypes = Collections.emptyList();
private Set<String> allSuperTypes = Collections.emptySet();
private Set<String> allSubTypes = Collections.emptySet();
private Map<String, AtlasAttribute> mappedFromRefAttributes = new HashMap<>();
private List<ForeignKeyReference> foreignKeyReferences = Collections.emptyList();
public AtlasEntityType(AtlasEntityDef entityDef) {
super(entityDef);
......@@ -96,15 +90,12 @@ public class AtlasEntityType extends AtlasStructType {
this.allSuperTypes = Collections.unmodifiableSet(allS);
this.allAttributes = Collections.unmodifiableMap(allA);
this.allSubTypes = new HashSet<>(); // this will be populated in resolveReferencesPhase2()
this.foreignKeyReferences = new ArrayList<>(); // this will be populated in resolveReferencesPhase2()
}
@Override
public void resolveReferencesPhase2(AtlasTypeRegistry typeRegistry) throws AtlasBaseException {
super.resolveReferencesPhase2(typeRegistry);
mappedFromRefAttributes = Collections.unmodifiableMap(resolveMappedFromRefConstraint(allAttributes.values()));
for (String superTypeName : allSuperTypes) {
AtlasEntityType superType = typeRegistry.getEntityTypeByName(superTypeName);
superType.addSubType(this);
......@@ -121,47 +112,6 @@ public class AtlasEntityType extends AtlasStructType {
public Set<String> getAllSubTypes() { return Collections.unmodifiableSet(allSubTypes); }
public Collection<String> getMappedFromRefAttributes() { return mappedFromRefAttributes.keySet(); }
public boolean isMappedFromRefAttribute(String attributeName) {
return mappedFromRefAttributes.containsKey(attributeName);
}
public String getMappedFromRefAttribute(String typeName, String attribName) {
String ret = null;
for (Map.Entry<String, AtlasAttribute> e : mappedFromRefAttributes.entrySet()) {
AtlasAttribute attribute = e.getValue();
if(StringUtils.equals(attribute.getDefinedInType().getTypeName(), typeName) && StringUtils.equals(attribute.getName(), attribName)) {
ret = e.getKey();
break;
}
}
return ret;
}
public List<ForeignKeyReference> getForeignKeyReferences() {
return Collections.unmodifiableList(foreignKeyReferences);
}
public ForeignKeyReference getForeignKeyReference(String fromTypeName, String fromAttributeName) {
ForeignKeyReference ret = null;
for (ForeignKeyReference fkRef : foreignKeyReferences) {
if (StringUtils.equals(fkRef.fromTypeName(), fromTypeName) &&
StringUtils.equals(fkRef.fromAttributeName(), fromAttributeName)) {
ret = fkRef;
break;
}
}
return ret;
}
public boolean isSuperTypeOf(AtlasEntityType entityType) {
return entityType != null && allSubTypes.contains(entityType.getTypeName());
}
......@@ -283,10 +233,6 @@ public class AtlasEntityType extends AtlasStructType {
}
}
void addForeignKeyReference(AtlasAttribute attribute, AtlasConstraintDef refConstraint) {
foreignKeyReferences.add(new ForeignKeyReference(attribute, refConstraint));
}
private void addSubType(AtlasEntityType subType) {
allSubTypes.add(subType.getTypeName());
}
......@@ -334,128 +280,9 @@ public class AtlasEntityType extends AtlasStructType {
}
}
/*
* valid conditions for mapped-from-ref constraint:
* - supported only in entity-type
* - attribute should be an entity-type or an array of entity-type
* - attribute's entity-type should have a foreign-key constraint to this type
*/
private Map<String, AtlasAttribute> resolveMappedFromRefConstraint(Collection<AtlasAttribute> attributes) throws AtlasBaseException {
Map<String, AtlasAttribute> ret = null;
for (AtlasAttribute attribute : attributes) {
AtlasAttributeDef attribDef = attribute.getAttributeDef();
if (CollectionUtils.isEmpty(attribDef.getConstraintDefs())) {
continue;
}
for (AtlasConstraintDef constraintDef : attribDef.getConstraintDefs()) {
if (!StringUtils.equals(constraintDef.getType(), CONSTRAINT_TYPE_MAPPED_FROM_REF)) {
continue;
}
AtlasType attribType = attribute.getAttributeType();
if (attribType instanceof AtlasArrayType) {
attribType = ((AtlasArrayType)attribType).getElementType();
}
if (!(attribType instanceof AtlasEntityType)) {
throw new AtlasBaseException(AtlasErrorCode.CONSTRAINT_NOT_SATISFIED, getTypeName(),
attribDef.getName(), CONSTRAINT_TYPE_MAPPED_FROM_REF,
attribDef.getTypeName());
}
String refAttribName = AtlasTypeUtil.getStringValue(constraintDef.getParams(), CONSTRAINT_PARAM_REF_ATTRIBUTE);
if (StringUtils.isBlank(refAttribName)) {
throw new AtlasBaseException(AtlasErrorCode.CONSTRAINT_MISSING_PARAMS,
getTypeName(), attribDef.getName(),
CONSTRAINT_PARAM_REF_ATTRIBUTE, CONSTRAINT_TYPE_MAPPED_FROM_REF,
String.valueOf(constraintDef.getParams()));
}
AtlasEntityType entityType = (AtlasEntityType) attribType;
AtlasAttribute refAttrib = entityType.getAttribute(refAttribName);
if (refAttrib == null) {
throw new AtlasBaseException(AtlasErrorCode.CONSTRAINT_NOT_EXIST,
getTypeName(), attribDef.getName(), CONSTRAINT_PARAM_REF_ATTRIBUTE,
entityType.getTypeName(), refAttribName);
}
if (!StringUtils.equals(getTypeName(), refAttrib.getTypeName())) {
throw new AtlasBaseException(AtlasErrorCode.CONSTRAINT_NOT_MATCHED,
getTypeName(), attribDef.getName(), CONSTRAINT_PARAM_REF_ATTRIBUTE,
entityType.getTypeName(), refAttribName, getTypeName(),
refAttrib.getTypeName());
}
if (ret == null) {
ret = new HashMap<>();
}
ret.put(attribDef.getName(), refAttrib);
break;
}
}
return ret == null ? Collections.<String, AtlasAttribute>emptyMap() : ret;
}
boolean isAssignableFrom(AtlasObjectId objId) {
boolean ret = objId.isValid() && (StringUtils.equals(objId.getTypeName(), getTypeName()) || isSuperTypeOf(objId.getTypeName()));
return ret;
}
public static class ForeignKeyReference {
private final AtlasAttribute fromAttribute;
private final AtlasConstraintDef refConstraint;
public ForeignKeyReference(AtlasAttribute fromAttribute, AtlasConstraintDef refConstraint) {
this.fromAttribute = fromAttribute;
this.refConstraint = refConstraint;
}
public String fromTypeName() { return fromType().getTypeName(); }
public String fromAttributeName() { return fromAttribute.getName(); }
public String toTypeName() { return fromAttribute.getTypeName(); }
public AtlasStructType fromType() { return fromAttribute.getDefinedInType(); }
public AtlasAttribute fromAttribute() { return fromAttribute; }
public AtlasEntityType toType() {
AtlasType attrType = fromAttribute.getAttributeType();
if (attrType instanceof AtlasArrayType) {
attrType = ((AtlasArrayType)attrType).getElementType();
}
if (attrType instanceof AtlasEntityType) {
return (AtlasEntityType)attrType;
}
return null;
}
public AtlasConstraintDef getConstraint() { return refConstraint; }
public boolean isOnDeleteCascade() {
return StringUtils.equals(getOnDeleteAction(), CONSTRAINT_PARAM_VAL_CASCADE);
}
private String getOnDeleteAction() {
Map<String, Object> params = refConstraint.getParams();
Object action = MapUtils.isNotEmpty(params) ? params.get(AtlasConstraintDef.CONSTRAINT_PARAM_ON_DELETE) : null;
return (action != null) ? action.toString() : null;
}
}
}
......@@ -17,26 +17,26 @@
*/
package org.apache.atlas.type;
import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef.CONSTRAINT_TYPE_OWNED_REF;
import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef.CONSTRAINT_TYPE_INVERSE_REF;
import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef.CONSTRAINT_PARAM_ATTRIBUTE;
import org.apache.atlas.AtlasErrorCode;
import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.instance.AtlasStruct;
import org.apache.atlas.model.typedef.AtlasStructDef;
import org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef;
import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef;
import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef.Cardinality;
import org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef;
import org.apache.atlas.type.AtlasEntityType.ForeignKeyReference;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* class that implements behaviour of a struct-type.
......@@ -46,7 +46,6 @@ public class AtlasStructType extends AtlasType {
private final AtlasStructDef structDef;
private Map<String, AtlasConstraintDef> foreignKeyAttributes = Collections.emptyMap();
protected Map<String, AtlasAttribute> allAttributes = Collections.emptyMap();
public AtlasStructType(AtlasStructDef structDef) {
......@@ -77,37 +76,6 @@ public class AtlasStructType extends AtlasType {
return attribute != null ? attribute.getAttributeDef() : null;
}
public Set<String> getForeignKeyAttributes() { return foreignKeyAttributes.keySet(); }
public boolean isForeignKeyAttribute(String attributeName) {
return foreignKeyAttributes.containsKey(attributeName);
}
public AtlasConstraintDef getForeignKeyConstraint(String attributeName) {
return foreignKeyAttributes.get(attributeName);
}
public String getForeignKeyOnDeleteAction(String attributeName) {
String ret = null;
AtlasConstraintDef fkConstraint = getForeignKeyConstraint(attributeName);
if (fkConstraint != null && MapUtils.isNotEmpty(fkConstraint.getParams())) {
Object onDeleteAction = fkConstraint.getParams().get(AtlasConstraintDef.CONSTRAINT_PARAM_ON_DELETE);
if (onDeleteAction != null) {
ret = onDeleteAction.toString();
}
}
return ret;
}
public boolean isForeignKeyOnDeleteActionCascade(String attributeName) {
return StringUtils.equals(getForeignKeyOnDeleteAction(attributeName),
AtlasConstraintDef.CONSTRAINT_PARAM_VAL_CASCADE);
}
@Override
public void resolveReferences(AtlasTypeRegistry typeRegistry) throws AtlasBaseException {
Map<String, AtlasAttribute> a = new HashMap<>();
......@@ -133,33 +101,69 @@ public class AtlasStructType extends AtlasType {
a.put(attributeDef.getName(), attribute);
}
resolveConstraints(typeRegistry);
this.allAttributes = Collections.unmodifiableMap(a);
}
foreignKeyAttributes = Collections.unmodifiableMap(resolveForeignKeyConstraints(allAttributes.values()));
private void resolveConstraints(AtlasTypeRegistry typeRegistry) throws AtlasBaseException {
for (AtlasAttributeDef attributeDef : getStructDef().getAttributeDefs()) {
if (CollectionUtils.isEmpty(attributeDef.getConstraints())) {
continue;
}
@Override
public void resolveReferencesPhase2(AtlasTypeRegistry typeRegistry) throws AtlasBaseException {
super.resolveReferencesPhase2(typeRegistry);
for (AtlasConstraintDef constraint : attributeDef.getConstraints()) {
if (constraint.isConstraintType(CONSTRAINT_TYPE_OWNED_REF)) {
AtlasEntityType attrType = getReferencedEntityType(typeRegistry.getType(attributeDef.getTypeName()));
for (Map.Entry<String, AtlasConstraintDef> e : foreignKeyAttributes.entrySet()) {
String attributeName = e.getKey();
AtlasAttribute attribute = getAttribute(attributeName);
AtlasConstraintDef constraint = e.getValue();
if (attrType == null) {
throw new AtlasBaseException(AtlasErrorCode.CONSTRAINT_OWNED_REF_ATTRIBUTE_INVALID_TYPE,
getTypeName(), attributeDef.getName(), CONSTRAINT_TYPE_OWNED_REF, attributeDef.getTypeName());
}
} else if (constraint.isConstraintType(CONSTRAINT_TYPE_INVERSE_REF)) {
AtlasEntityType attrType = getReferencedEntityType(typeRegistry.getType(attributeDef.getTypeName()));
AtlasType attrType = attribute.getAttributeType();
if (attrType == null) {
throw new AtlasBaseException(AtlasErrorCode.CONSTRAINT_INVERSE_REF_ATTRIBUTE_INVALID_TYPE,
getTypeName(), attributeDef.getName(), CONSTRAINT_TYPE_INVERSE_REF,
attributeDef.getTypeName());
}
String inverseRefAttrName = AtlasTypeUtil.getStringValue(constraint.getParams(), CONSTRAINT_PARAM_ATTRIBUTE);
if (attrType instanceof AtlasArrayType) {
attrType = ((AtlasArrayType)attrType).getElementType();
if (StringUtils.isBlank(inverseRefAttrName)) {
throw new AtlasBaseException(AtlasErrorCode.CONSTRAINT_MISSING_PARAMS,
getTypeName(), attributeDef.getName(),
CONSTRAINT_PARAM_ATTRIBUTE, CONSTRAINT_TYPE_INVERSE_REF,
String.valueOf(constraint.getParams()));
}
if (attrType instanceof AtlasEntityType) {
((AtlasEntityType)attrType).addForeignKeyReference(attribute, constraint);
AtlasAttributeDef inverseRefAttrDef = attrType.getStructDef().getAttribute(inverseRefAttrName);
if (inverseRefAttrDef == null) {
throw new AtlasBaseException(AtlasErrorCode.CONSTRAINT_INVERSE_REF_INVERSE_ATTRIBUTE_NON_EXISTING,
getTypeName(), attributeDef.getName(),
CONSTRAINT_TYPE_INVERSE_REF, attrType.getTypeName(), inverseRefAttrName);
}
AtlasEntityType inverseRefAttrType = getReferencedEntityType(typeRegistry.getType(inverseRefAttrDef.getTypeName()));
if (inverseRefAttrType == null) {
throw new AtlasBaseException(AtlasErrorCode.CONSTRAINT_INVERSE_REF_INVERSE_ATTRIBUTE_INVALID_TYPE,
getTypeName(), attributeDef.getName(),
CONSTRAINT_TYPE_INVERSE_REF, attrType.getTypeName(), inverseRefAttrName);
}
}
}
}
}
@Override
public void resolveReferencesPhase2(AtlasTypeRegistry typeRegistry) throws AtlasBaseException {
super.resolveReferencesPhase2(typeRegistry);
}
@Override
public AtlasStruct createDefaultValue() {
AtlasStruct ret = new AtlasStruct(structDef.getName());
......@@ -383,57 +387,6 @@ public class AtlasStructType extends AtlasType {
return null;
}
/*
* valid conditions for foreign-key constraint:
* - supported only in entity-type
* - attribute should be an entity-type or an array of entity-type
*/
private Map<String, AtlasConstraintDef> resolveForeignKeyConstraints(Collection<AtlasAttribute> attributes)
throws AtlasBaseException {
Map<String, AtlasConstraintDef> ret = null;
for (AtlasAttribute attribute : attributes) {
AtlasAttributeDef attribDef = attribute.getAttributeDef();
if (CollectionUtils.isEmpty(attribDef.getConstraintDefs())) {
continue;
}
for (AtlasConstraintDef constraintDef : attribDef.getConstraintDefs()) {
if (!StringUtils.equals(constraintDef.getType(), AtlasConstraintDef.CONSTRAINT_TYPE_FOREIGN_KEY)) {
continue;
}
if (!(this instanceof AtlasEntityType)) {
throw new AtlasBaseException(AtlasErrorCode.UNSUPPORTED_CONSTRAINT,
AtlasConstraintDef.CONSTRAINT_TYPE_FOREIGN_KEY, getTypeName(), attribute.getName());
}
AtlasType attrType = attribute.getAttributeType();
if (attrType instanceof AtlasArrayType) {
attrType = ((AtlasArrayType) attrType).getElementType();
}
if (!(attrType instanceof AtlasEntityType)) {
throw new AtlasBaseException(AtlasErrorCode.CONSTRAINT_NOT_SATISFIED,
getTypeName(), attribute.getName(), AtlasConstraintDef.CONSTRAINT_TYPE_FOREIGN_KEY,
attrType.getTypeName());
}
if (ret == null) {
ret = new HashMap<>();
}
ret.put(attribute.getName(), constraintDef);
break;
}
}
return ret == null ? Collections.<String, AtlasConstraintDef>emptyMap() : ret;
}
public String getQualifiedAttributeName(String attrName) throws AtlasBaseException {
if ( allAttributes.containsKey(attrName)) {
return allAttributes.get(attrName).getQualifiedName();
......@@ -442,18 +395,49 @@ public class AtlasStructType extends AtlasType {
throw new AtlasBaseException(AtlasErrorCode.UNKNOWN_ATTRIBUTE, attrName, structDef.getName());
}
public static class AtlasAttribute {
private AtlasEntityType getReferencedEntityType(AtlasType type) {
if (type instanceof AtlasArrayType) {
type = ((AtlasArrayType)type).getElementType();
}
return type instanceof AtlasEntityType ? (AtlasEntityType)type : null;
}
public static class AtlasAttribute {
private final AtlasStructType definedInType;
private final AtlasType attributeType;
private final AtlasAttributeDef attributeDef;
private final String qualifiedName;
private final boolean isOwnedRef;
private final String inverseRefAttribute;
public AtlasAttribute(AtlasStructType definedInType, AtlasAttributeDef attrDef, AtlasType attributeType) {
this.definedInType = definedInType;
this.attributeDef = attrDef;
this.attributeType = attributeType;
this.qualifiedName = getQualifiedAttributeName(definedInType.getStructDef(), attributeDef.getName());
boolean isOwnedRef = false;
String inverseRefAttribute = null;
if (CollectionUtils.isNotEmpty(attributeDef.getConstraints())) {
for (AtlasConstraintDef constraint : attributeDef.getConstraints()) {
if (constraint.isConstraintType(CONSTRAINT_TYPE_OWNED_REF)) {
isOwnedRef = true;
}
if (constraint.isConstraintType(CONSTRAINT_TYPE_INVERSE_REF)) {
Object val = constraint.getParam(CONSTRAINT_PARAM_ATTRIBUTE);
if (val != null) {
inverseRefAttribute = val.toString();
}
}
}
}
this.isOwnedRef = isOwnedRef;
this.inverseRefAttribute = inverseRefAttribute;
}
public AtlasStructType getDefinedInType() { return definedInType; }
......@@ -478,74 +462,9 @@ public class AtlasStructType extends AtlasType {
return qualifiedName;
}
public boolean isForeignKeyWithOnDeleteCascade() {
return definedInType.isForeignKeyOnDeleteActionCascade(getName());
}
/*
* true - if attribute-type has foreign-key(onDelete=cascade) reference to this type
* false - in all cases
*
* "legacyIsComposite" can not be computed and cached in the constructor - as definedInType is not fully
* populated at the time AtlasAttribute object is constructed.
*/
public boolean legacyIsComposite() {
boolean ret = false;
if (definedInType instanceof AtlasEntityType) {
AtlasEntityType entityType = (AtlasEntityType) definedInType;
AtlasType attrType = attributeType;
if (attrType instanceof AtlasArrayType) {
attrType = ((AtlasArrayType)attrType).getElementType();
}
if (attrType instanceof AtlasEntityType) {
for (ForeignKeyReference fkRef : entityType.getForeignKeyReferences()) {
if (fkRef.isOnDeleteCascade() && StringUtils.equals(fkRef.fromTypeName(), attrType.getTypeName())) {
ret = true;
break;
}
}
}
}
if (LOG.isDebugEnabled()) {
LOG.debug("*** {}.{}: isComposite={} ***", definedInType.getTypeName(), getName(), ret);
}
return ret;
}
/*
* return the name of the attribute in attribute-type that has mappedFromRef constraint on this attribute
*
* "legacyReverseAttribute" can not be computed and cached in the constructor - as definedInType is not fully
* populated at the time AtlasAttribute object is constructed.
*/
public String legacyReverseAttribute() {
String ret = null;
if (definedInType instanceof AtlasEntityType) {
AtlasType attrType = attributeType;
if (attrType instanceof AtlasArrayType) {
attrType = ((AtlasArrayType)attrType).getElementType();
}
if (attrType instanceof AtlasEntityType) {
AtlasEntityType attribEntityType = (AtlasEntityType) attrType;
public boolean isOwnedRef() { return isOwnedRef; }
ret = attribEntityType.getMappedFromRefAttribute(definedInType.getTypeName(), getName());
}
}
if (LOG.isDebugEnabled()) {
LOG.debug("*** {}.{}: reverseAttribute={} ***", definedInType.getTypeName(), getName(), ret);
}
return ret;
}
public String getInverseRefAttribute() { return inverseRefAttribute; }
public static String getQualifiedAttributeName(AtlasStructDef structDef, String attrName) {
final String typeName = structDef.getName();
......
......@@ -87,12 +87,6 @@ public final class TestUtilsV2 {
AtlasAttributeDef.Cardinality.SINGLE, 0, 1, false, false,
new ArrayList<AtlasConstraintDef>()));
deptTypeDef.getAttribute("employees").addConstraint(
new AtlasConstraintDef(
AtlasConstraintDef.CONSTRAINT_TYPE_MAPPED_FROM_REF, new HashMap<String, Object>() {{
put(AtlasConstraintDef.CONSTRAINT_PARAM_REF_ATTRIBUTE, "department");
}}));
AtlasEntityDef personTypeDef = AtlasTypeUtil.createClassTypeDef("Person", "Person"+_description, ImmutableSet.<String>of(),
AtlasTypeUtil.createUniqueRequiredAttrDef("name", "string"),
AtlasTypeUtil.createOptionalAttrDef("address", "Address"),
......@@ -126,8 +120,8 @@ public final class TestUtilsV2 {
employeeTypeDef.getAttribute("department").addConstraint(
new AtlasConstraintDef(
AtlasConstraintDef.CONSTRAINT_TYPE_FOREIGN_KEY, new HashMap<String, Object>() {{
put(AtlasConstraintDef.CONSTRAINT_PARAM_ON_DELETE, AtlasConstraintDef.CONSTRAINT_PARAM_VAL_CASCADE);
AtlasConstraintDef.CONSTRAINT_TYPE_INVERSE_REF, new HashMap<String, Object>() {{
put(AtlasConstraintDef.CONSTRAINT_PARAM_ATTRIBUTE, "employees");
}}));
AtlasEntityDef managerTypeDef = AtlasTypeUtil.createClassTypeDef("Manager", "Manager"+_description, ImmutableSet.of("Employee"),
......@@ -480,8 +474,8 @@ public final class TestUtilsV2 {
false, false,
new ArrayList<AtlasStructDef.AtlasConstraintDef>() {{
add(new AtlasStructDef.AtlasConstraintDef(
AtlasStructDef.AtlasConstraintDef.CONSTRAINT_TYPE_FOREIGN_KEY, new HashMap<String, Object>() {{
put(AtlasStructDef.AtlasConstraintDef.CONSTRAINT_PARAM_ON_DELETE, AtlasStructDef.AtlasConstraintDef.CONSTRAINT_PARAM_VAL_CASCADE);
AtlasConstraintDef.CONSTRAINT_TYPE_INVERSE_REF, new HashMap<String, Object>() {{
put(AtlasConstraintDef.CONSTRAINT_PARAM_ATTRIBUTE, "columns");
}}));
}})
);
......@@ -583,11 +577,7 @@ public final class TestUtilsV2 {
AtlasAttributeDef.Cardinality.SINGLE, 0, 1,
false, false,
new ArrayList<AtlasStructDef.AtlasConstraintDef>() {{
add(new AtlasStructDef.AtlasConstraintDef(
AtlasStructDef.AtlasConstraintDef.CONSTRAINT_TYPE_MAPPED_FROM_REF,
new HashMap<String, Object>() {{
put(AtlasStructDef.AtlasConstraintDef.CONSTRAINT_PARAM_REF_ATTRIBUTE, "table");
}}));
add(new AtlasStructDef.AtlasConstraintDef(AtlasConstraintDef.CONSTRAINT_TYPE_OWNED_REF));
}}),
// array of structs
new AtlasAttributeDef("partitions", String.format("array<%s>", "partition_struct_type"),
......
......@@ -23,6 +23,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import org.apache.atlas.AtlasErrorCode;
import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.ModelTestUtil;
import org.apache.atlas.model.instance.AtlasEntity;
......@@ -31,7 +32,6 @@ import org.apache.atlas.model.typedef.AtlasEntityDef;
import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef;
import org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef;
import org.apache.atlas.type.AtlasTypeRegistry.AtlasTransientTypeRegistry;
import org.apache.atlas.type.AtlasEntityType.ForeignKeyReference;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
......@@ -42,6 +42,7 @@ public class TestAtlasEntityType {
private static final String TYPE_COLUMN = "my_column";
private static final String ATTR_TABLE = "table";
private static final String ATTR_COLUMNS = "columns";
private static final String ATTR_NAME = "name";
private final AtlasEntityType entityType;
private final List<Object> validValues = new ArrayList<>();
......@@ -129,7 +130,7 @@ public class TestAtlasEntityType {
}
@Test
public void testForeignKeyConstraintValid() {
public void testValidConstraints() {
AtlasTypeRegistry typeRegistry = new AtlasTypeRegistry();
AtlasTransientTypeRegistry ttr = null;
boolean commit = false;
......@@ -147,42 +148,81 @@ public class TestAtlasEntityType {
AtlasEntityType typeTable = ttr.getEntityTypeByName(TYPE_TABLE);
AtlasEntityType typeColumn = ttr.getEntityTypeByName(TYPE_COLUMN);
assertEquals(typeTable.getForeignKeyReferences().size(), 1);
assertTrue(typeTable.getAttribute(ATTR_COLUMNS).isOwnedRef());
assertNull(typeTable.getAttribute(ATTR_COLUMNS).getInverseRefAttribute());
assertFalse(typeColumn.getAttribute(ATTR_TABLE).isOwnedRef());
assertEquals(typeColumn.getAttribute(ATTR_TABLE).getInverseRefAttribute(), ATTR_COLUMNS);
ForeignKeyReference fkRef = typeTable.getForeignKeyReferences().get(0);
assertEquals(fkRef.fromTypeName(), TYPE_COLUMN);
assertEquals(fkRef.fromAttributeName(), ATTR_TABLE);
assertEquals(fkRef.toTypeName(), TYPE_TABLE);
assertTrue(fkRef.isOnDeleteCascade());
commit = true;
} catch (AtlasBaseException excp) {
failureMsg = excp.getMessage();
} finally {
typeRegistry.releaseTypeRegistryForUpdate(ttr, commit);
}
assertNull(failureMsg, "failed to create types " + TYPE_TABLE + " and " + TYPE_COLUMN);
}
assertEquals(typeTable.getForeignKeyAttributes().size(), 0);
assertEquals(typeTable.getMappedFromRefAttributes().size(), 1);
assertTrue(typeTable.getMappedFromRefAttributes().contains(ATTR_COLUMNS));
@Test
public void testConstraintInvalidOwnedRef_InvalidAttributeType() {
AtlasTypeRegistry typeRegistry = new AtlasTypeRegistry();
AtlasTransientTypeRegistry ttr = null;
boolean commit = false;
List<AtlasEntityDef> entityDefs = new ArrayList<>();
AtlasErrorCode errorCode = null;
entityDefs.add(createTableEntityDefWithOwnedRefOnInvalidType());
try {
ttr = typeRegistry.lockTypeRegistryForUpdate();
assertEquals(typeColumn.getForeignKeyReferences().size(), 0);
assertEquals(typeColumn.getForeignKeyAttributes().size(), 1);
assertTrue(typeColumn.getForeignKeyAttributes().contains(ATTR_TABLE));
assertEquals(typeColumn.getMappedFromRefAttributes().size(), 0);
ttr.addTypes(entityDefs);
commit = true;
} catch (AtlasBaseException excp) {
failureMsg = excp.getMessage();
errorCode = excp.getAtlasErrorCode();
} finally {
typeRegistry.releaseTypeRegistryForUpdate(ttr, commit);
}
assertNull(failureMsg, "failed to create types " + TYPE_TABLE + " and " + TYPE_COLUMN);
assertEquals(errorCode, AtlasErrorCode.CONSTRAINT_OWNED_REF_ATTRIBUTE_INVALID_TYPE,
"expected invalid constraint failure - missing refAttribute");
}
@Test
public void testForeignKeyConstraintInValidMappedFromRef() {
public void testConstraintInValidInverseRef_MissingParams() {
AtlasTypeRegistry typeRegistry = new AtlasTypeRegistry();
AtlasTransientTypeRegistry ttr = null;
boolean commit = false;
List<AtlasEntityDef> entityDefs = new ArrayList<>();
String failureMsg = null;
AtlasErrorCode errorCode = null;
entityDefs.add(createTableEntityDef());
entityDefs.add(createColumnEntityDefWithMissingInverseAttribute());
try {
ttr = typeRegistry.lockTypeRegistryForUpdate();
ttr.addTypes(entityDefs);
commit = true;
} catch (AtlasBaseException excp) {
errorCode = excp.getAtlasErrorCode();
} finally {
typeRegistry.releaseTypeRegistryForUpdate(ttr, commit);
}
assertEquals(errorCode, AtlasErrorCode.CONSTRAINT_MISSING_PARAMS,
"expected invalid constraint failure - missing refAttribute");
}
@Test
public void testConstraintInValidInverseRef_InvalidAttributeTypeForInverseAttribute() {
AtlasTypeRegistry typeRegistry = new AtlasTypeRegistry();
AtlasTransientTypeRegistry ttr = null;
boolean commit = false;
List<AtlasEntityDef> entityDefs = new ArrayList<>();
AtlasErrorCode errorCode = null;
entityDefs.add(createTableEntityDef());
entityDefs.add(createColumnEntityDefWithInvaidAttributeTypeForInverseAttribute());
try {
ttr = typeRegistry.lockTypeRegistryForUpdate();
......@@ -191,23 +231,24 @@ public class TestAtlasEntityType {
commit = true;
} catch (AtlasBaseException excp) {
failureMsg = excp.getMessage();
errorCode = excp.getAtlasErrorCode();
} finally {
typeRegistry.releaseTypeRegistryForUpdate(ttr, commit);
}
assertNotNull(failureMsg, "expected invalid constraint failure - unknown attribute in mappedFromRef");
assertEquals(errorCode, AtlasErrorCode.CONSTRAINT_INVERSE_REF_ATTRIBUTE_INVALID_TYPE,
"expected invalid constraint failure - missing refAttribute");
}
@Test
public void testForeignKeyConstraintInValidMappedFromRef2() {
public void testConstraintInValidInverseRef_InvalidAttributeType() {
AtlasTypeRegistry typeRegistry = new AtlasTypeRegistry();
AtlasTransientTypeRegistry ttr = null;
boolean commit = false;
List<AtlasEntityDef> entityDefs = new ArrayList<>();
String failureMsg = null;
AtlasErrorCode errorCode = null;
entityDefs.add(createTableEntityDefWithMissingRefAttribute());
entityDefs.add(createColumnEntityDef());
entityDefs.add(createTableEntityDef());
entityDefs.add(createColumnEntityDefWithInvalidInverseAttributeType());
try {
ttr = typeRegistry.lockTypeRegistryForUpdate();
......@@ -216,22 +257,24 @@ public class TestAtlasEntityType {
commit = true;
} catch (AtlasBaseException excp) {
failureMsg = excp.getMessage();
errorCode = excp.getAtlasErrorCode();
} finally {
typeRegistry.releaseTypeRegistryForUpdate(ttr, commit);
}
assertNotNull(failureMsg, "expected invalid constraint failure - missing refAttribute in mappedFromRef");
assertEquals(errorCode, AtlasErrorCode.CONSTRAINT_INVERSE_REF_INVERSE_ATTRIBUTE_INVALID_TYPE,
"expected invalid constraint failure - invalid refAttribute type");
}
@Test
public void testForeignKeyConstraintInValidForeignKey() {
public void testConstraintInValidInverseRef_NonExistingAttribute() {
AtlasTypeRegistry typeRegistry = new AtlasTypeRegistry();
AtlasTransientTypeRegistry ttr = null;
boolean commit = false;
List<AtlasEntityDef> entityDefs = new ArrayList<>();
String failureMsg = null;
AtlasErrorCode errorCode = null;
entityDefs.add(createColumnEntityDef());
entityDefs.add(createTableEntityDef());
entityDefs.add(createColumnEntityDefWithNonExistingInverseAttribute());
try {
ttr = typeRegistry.lockTypeRegistryForUpdate();
......@@ -240,11 +283,12 @@ public class TestAtlasEntityType {
commit = true;
} catch (AtlasBaseException excp) {
failureMsg = excp.getMessage();
errorCode = excp.getAtlasErrorCode();
} finally {
typeRegistry.releaseTypeRegistryForUpdate(ttr, commit);
}
assertNotNull(failureMsg, "expected invalid constraint failure - unknown attribute in foreignKey");
assertEquals(errorCode, AtlasErrorCode.CONSTRAINT_INVERSE_REF_INVERSE_ATTRIBUTE_NON_EXISTING,
"expected invalid constraint failure - non-existing refAttribute");
}
private static AtlasEntityType getEntityType(AtlasEntityDef entityDef) {
......@@ -257,37 +301,86 @@ public class TestAtlasEntityType {
private AtlasEntityDef createTableEntityDef() {
AtlasEntityDef table = new AtlasEntityDef(TYPE_TABLE);
AtlasAttributeDef attrName = new AtlasAttributeDef(ATTR_NAME, AtlasBaseTypeDef.ATLAS_TYPE_STRING);
AtlasAttributeDef attrColumns = new AtlasAttributeDef(ATTR_COLUMNS,
AtlasBaseTypeDef.getArrayTypeName(TYPE_COLUMN));
Map<String, Object> params = new HashMap<>();
params.put(AtlasConstraintDef.CONSTRAINT_PARAM_REF_ATTRIBUTE, ATTR_TABLE);
attrColumns.addConstraint(new AtlasConstraintDef(AtlasConstraintDef.CONSTRAINT_TYPE_OWNED_REF));
attrColumns.addConstraint(new AtlasConstraintDef(AtlasConstraintDef.CONSTRAINT_TYPE_MAPPED_FROM_REF, params));
table.addAttribute(attrName);
table.addAttribute(attrColumns);
return table;
}
private AtlasEntityDef createTableEntityDefWithMissingRefAttribute() {
private AtlasEntityDef createTableEntityDefWithOwnedRefOnInvalidType() {
AtlasEntityDef table = new AtlasEntityDef(TYPE_TABLE);
AtlasAttributeDef attrColumns = new AtlasAttributeDef(ATTR_COLUMNS,
AtlasBaseTypeDef.getArrayTypeName(TYPE_COLUMN));
AtlasAttributeDef attrName = new AtlasAttributeDef(ATTR_NAME, AtlasBaseTypeDef.ATLAS_TYPE_STRING);
attrColumns.addConstraint(new AtlasConstraintDef(AtlasConstraintDef.CONSTRAINT_TYPE_MAPPED_FROM_REF, null));
table.addAttribute(attrColumns);
attrName.addConstraint(new AtlasConstraintDef(AtlasConstraintDef.CONSTRAINT_TYPE_OWNED_REF));
table.addAttribute(attrName);
return table;
}
private AtlasEntityDef createColumnEntityDefWithMissingInverseAttribute() {
AtlasEntityDef column = new AtlasEntityDef(TYPE_COLUMN);
AtlasAttributeDef attrTable = new AtlasAttributeDef(ATTR_TABLE, TYPE_TABLE);
attrTable.addConstraint(new AtlasConstraintDef(AtlasConstraintDef.CONSTRAINT_TYPE_INVERSE_REF));
column.addAttribute(attrTable);
return column;
}
private AtlasEntityDef createColumnEntityDefWithInvaidAttributeTypeForInverseAttribute() {
AtlasEntityDef column = new AtlasEntityDef(TYPE_COLUMN);
AtlasAttributeDef attrTable = new AtlasAttributeDef(ATTR_NAME, AtlasBaseTypeDef.ATLAS_TYPE_STRING);
Map<String, Object> params = new HashMap<>();
params.put(AtlasConstraintDef.CONSTRAINT_PARAM_ATTRIBUTE, ATTR_NAME);
attrTable.addConstraint(new AtlasConstraintDef(AtlasConstraintDef.CONSTRAINT_TYPE_INVERSE_REF, params));
column.addAttribute(attrTable);
return column;
}
private AtlasEntityDef createColumnEntityDefWithNonExistingInverseAttribute() {
AtlasEntityDef column = new AtlasEntityDef(TYPE_COLUMN);
AtlasAttributeDef attrTable = new AtlasAttributeDef(ATTR_TABLE, TYPE_TABLE);
Map<String, Object> params = new HashMap<>();
params.put(AtlasConstraintDef.CONSTRAINT_PARAM_ATTRIBUTE, "non-existing:" + ATTR_COLUMNS);
attrTable.addConstraint(new AtlasConstraintDef(AtlasConstraintDef.CONSTRAINT_TYPE_INVERSE_REF, params));
column.addAttribute(attrTable);
return column;
}
private AtlasEntityDef createColumnEntityDefWithInvalidInverseAttributeType() {
AtlasEntityDef column = new AtlasEntityDef(TYPE_COLUMN);
AtlasAttributeDef attrTable = new AtlasAttributeDef(ATTR_TABLE, TYPE_TABLE);
Map<String, Object> params = new HashMap<>();
params.put(AtlasConstraintDef.CONSTRAINT_PARAM_ATTRIBUTE, ATTR_NAME);
attrTable.addConstraint(new AtlasConstraintDef(AtlasConstraintDef.CONSTRAINT_TYPE_INVERSE_REF, params));
column.addAttribute(attrTable);
return column;
}
private AtlasEntityDef createColumnEntityDef() {
AtlasEntityDef column = new AtlasEntityDef(TYPE_COLUMN);
AtlasAttributeDef attrTable = new AtlasAttributeDef(ATTR_TABLE, TYPE_TABLE);
Map<String, Object> params = new HashMap<>();
params.put(AtlasConstraintDef.CONSTRAINT_PARAM_ON_DELETE, AtlasConstraintDef.CONSTRAINT_PARAM_VAL_CASCADE);
params.put(AtlasConstraintDef.CONSTRAINT_PARAM_ATTRIBUTE, ATTR_COLUMNS);
attrTable.addConstraint(new AtlasConstraintDef(AtlasConstraintDef.CONSTRAINT_TYPE_FOREIGN_KEY, params));
attrTable.addConstraint(new AtlasConstraintDef(AtlasConstraintDef.CONSTRAINT_TYPE_INVERSE_REF, params));
column.addAttribute(attrTable);
return column;
......
......@@ -52,11 +52,6 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef.CONSTRAINT_PARAM_ON_DELETE;
import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef.CONSTRAINT_PARAM_VAL_CASCADE;
import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef.CONSTRAINT_TYPE_FOREIGN_KEY;
import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef.CONSTRAINT_TYPE_MAPPED_FROM_REF;
/**
* StructDef store in v1 format.
*/
......@@ -503,18 +498,14 @@ public class AtlasStructDefStoreV1 extends AtlasAbstractDefStoreV1 implements At
@VisibleForTesting
public static String toJsonFromAttribute(AtlasAttribute attribute) {
AtlasAttributeDef attributeDef = attribute.getAttributeDef();
boolean isComposite = attribute.legacyIsComposite();
String reverseAttribName = attribute.legacyReverseAttribute();
Map<String, Object> attribInfo = new HashMap<>();
attribInfo.put("name", attributeDef.getName());
attribInfo.put("dataType", attributeDef.getTypeName());
attribInfo.put("isUnique", attributeDef.getIsUnique());
attribInfo.put("isIndexable", attributeDef.getIsIndexable());
attribInfo.put("isComposite", isComposite);
attribInfo.put("reverseAttributeName", reverseAttribName);
attribInfo.put("isForeignKeyWithOnDeleteCascade", attribute.isForeignKeyWithOnDeleteCascade());
attribInfo.put("isComposite", attribute.isOwnedRef());
attribInfo.put("reverseAttributeName", attribute.getInverseRefAttribute());
final int lower;
final int upper;
......@@ -554,111 +545,16 @@ public class AtlasStructDefStoreV1 extends AtlasAbstractDefStoreV1 implements At
ret.setIsUnique((Boolean) attribInfo.get("isUnique"));
ret.setIsIndexable((Boolean) attribInfo.get("isIndexable"));
String attrTypeName = ret.getTypeName();
if (AtlasTypeUtil.isArrayType(attrTypeName)) {
Set<String> typeNames = AtlasTypeUtil.getReferencedTypeNames(attrTypeName);
if (typeNames.size() > 0) {
attrTypeName = typeNames.iterator().next();
}
}
if (!AtlasTypeUtil.isBuiltInType(attrTypeName)) {
AtlasVertex attributeType = typeDefStore.findTypeVertexByName(attrTypeName);
/* determine constraints to add to this attribute
- add mappedFromRef if attribute-type has an attribute that refers to this attribute via reverseAttributeName
example: hive_table.sd referenced from hive_storagedesc.table with reverseAttributeName=sd
- add foreignKey(onDelete=cascade) if attribute-type has an attribute that refers to this struct with isComposite=true
example: hive_storagedesc referenced from hive_table.sd with isComposite=true
example: hive_column referenced from hive_table.columns with isComposite=true
*/
if (attributeType != null && typeDefStore.isTypeVertex(attributeType, TypeCategory.CLASS)) {
boolean attributeTypeHasIsCompositeRef = false;
String attributeTypeRevAttribRefFrom = null;
List<String> attrNames = attributeType.getProperty(AtlasGraphUtilsV1.getTypeDefPropertyKey(attrTypeName), List.class);
if (CollectionUtils.isNotEmpty(attrNames)) {
for (String attrName : attrNames) {
String attribJson = attributeType.getProperty(
AtlasGraphUtilsV1.getTypeDefPropertyKey(attrTypeName, attrName), String.class);
if (StringUtils.isBlank(attribJson)) {
continue;
}
Map refAttrInfo = AtlasType.fromJson(attribJson, Map.class);
if (refAttrInfo == null) {
continue;
}
String refAttribType = (String) refAttrInfo.get("dataType");
if (AtlasTypeUtil.isArrayType(refAttribType)) {
Set<String> typeNames = AtlasTypeUtil.getReferencedTypeNames(refAttribType);
if (typeNames.size() > 0) {
refAttribType = typeNames.iterator().next();
}
}
if (!StringUtils.equals(refAttribType, structDef.getName())) {
continue;
if ((Boolean)attribInfo.get("isComposite")) {
ret.addConstraint(new AtlasConstraintDef(AtlasConstraintDef.CONSTRAINT_TYPE_OWNED_REF));
}
if (StringUtils.isBlank(attributeTypeRevAttribRefFrom)) {
String refAttribRevAttribName = (String) refAttrInfo.get("reverseAttributeName");
if (StringUtils.equals(refAttribRevAttribName, ret.getName())) {
attributeTypeRevAttribRefFrom = (String) refAttrInfo.get("name");
}
}
if (!attributeTypeHasIsCompositeRef) {
Object val = refAttrInfo.get("isComposite");
if (val instanceof Boolean) {
attributeTypeHasIsCompositeRef = (Boolean) val;
} if (val != null) {
attributeTypeHasIsCompositeRef = Boolean.parseBoolean(val.toString());
}
}
if (StringUtils.isNotBlank(attributeTypeRevAttribRefFrom) && attributeTypeHasIsCompositeRef) {
break;
}
}
}
boolean isForeignKeyWithOnDeleteCascade = attributeTypeHasIsCompositeRef;
if (!isForeignKeyWithOnDeleteCascade) {
Object val = attribInfo.get("isForeignKeyWithOnDeleteCascade");
if (val instanceof Boolean) {
isForeignKeyWithOnDeleteCascade = (Boolean) val;
} else if (val != null) {
isForeignKeyWithOnDeleteCascade = Boolean.parseBoolean(val.toString());
}
}
if (StringUtils.isNotBlank(attributeTypeRevAttribRefFrom)) {
Map<String, Object> params = new HashMap<>();
params.put(AtlasConstraintDef.CONSTRAINT_PARAM_REF_ATTRIBUTE, attributeTypeRevAttribRefFrom);
ret.addConstraint(new AtlasConstraintDef(CONSTRAINT_TYPE_MAPPED_FROM_REF, params));
}
if (isForeignKeyWithOnDeleteCascade) { // ex: hive_column.table
Map<String, Object> params = new HashMap<>();
params.put(CONSTRAINT_PARAM_ON_DELETE, CONSTRAINT_PARAM_VAL_CASCADE);
ret.addConstraint(new AtlasConstraintDef(CONSTRAINT_TYPE_FOREIGN_KEY, params));
}
}
final String reverseAttributeName = (String) attribInfo.get("reverseAttributeName");
if (StringUtils.isNotBlank(reverseAttributeName)) {
ret.addConstraint(new AtlasConstraintDef(AtlasConstraintDef.CONSTRAINT_TYPE_INVERSE_REF,
new HashMap<String, Object>() {{
put(AtlasConstraintDef.CONSTRAINT_PARAM_ATTRIBUTE, reverseAttributeName);
}}));
}
Map multiplicity = AtlasType.fromJson((String) attribInfo.get("multiplicity"), Map.class);
......
......@@ -139,7 +139,7 @@ public abstract class DeleteHandlerV1 {
}
for (AtlasStructType.AtlasAttribute attributeInfo : entityType.getAllAttributes().values()) {
if (!entityType.isMappedFromRefAttribute(attributeInfo.getName())) {
if (! attributeInfo.isOwnedRef()) {
continue;
}
String edgeLabel = AtlasGraphUtilsV1.getAttributeEdgeLabel(entityType, attributeInfo.getName());
......@@ -284,7 +284,7 @@ public abstract class DeleteHandlerV1 {
for (AtlasStructType.AtlasAttribute attributeInfo : getAttributes(structType)) {
LOG.debug("Deleting attribute {} for {}", attributeInfo.getName(), string(instanceVertex));
boolean isComposite = isEntityType && ((AtlasEntityType)structType).isMappedFromRefAttribute(attributeInfo.getName());
boolean isComposite = isEntityType && attributeInfo.isOwnedRef();
AtlasType attrType = typeRegistry.getType(attributeInfo.getTypeName());
......
......@@ -88,7 +88,9 @@ public class StructVertexMapper implements InstanceGraphMapper<AtlasEdge> {
}
public static boolean shouldManageChildReferences(AtlasStructType type, String attributeName) {
return (type instanceof AtlasEntityType) && ((AtlasEntityType)type).isMappedFromRefAttribute(attributeName);
AtlasStructType.AtlasAttribute attribute = type.getAttribute(attributeName);
return attribute != null ? attribute.isOwnedRef() : false;
}
/**
......
......@@ -63,11 +63,9 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef.CONSTRAINT_PARAM_ON_DELETE;
import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef.CONSTRAINT_PARAM_REF_ATTRIBUTE;
import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef.CONSTRAINT_PARAM_VAL_CASCADE;
import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef.CONSTRAINT_TYPE_FOREIGN_KEY;
import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef.CONSTRAINT_TYPE_MAPPED_FROM_REF;
import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef.CONSTRAINT_TYPE_INVERSE_REF;
import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef.CONSTRAINT_TYPE_OWNED_REF;
import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef.CONSTRAINT_PARAM_ATTRIBUTE;
/**
* A driver that sets up sample types and entities using v2 types and entity model for testing purposes.
......@@ -217,8 +215,8 @@ public class QuickStartV2 {
AtlasTypeUtil.createOptionalAttrDef("createTime", "long"));
AtlasEntityDef sdType = AtlasTypeUtil.createClassTypeDef(STORAGE_DESC_TYPE, STORAGE_DESC_TYPE, "1.0", null,
AtlasTypeUtil.createOptionalAttrDefWithConstraint("table", TABLE_TYPE, CONSTRAINT_TYPE_FOREIGN_KEY,
new HashMap<String, Object>() {{ put(CONSTRAINT_PARAM_ON_DELETE, CONSTRAINT_PARAM_VAL_CASCADE); }}),
AtlasTypeUtil.createOptionalAttrDefWithConstraint("table", TABLE_TYPE, CONSTRAINT_TYPE_INVERSE_REF,
new HashMap<String, Object>() {{ put(CONSTRAINT_PARAM_ATTRIBUTE, "sd"); }}),
AtlasTypeUtil.createOptionalAttrDef("location", "string"),
AtlasTypeUtil.createOptionalAttrDef("inputFormat", "string"),
AtlasTypeUtil.createOptionalAttrDef("outputFormat", "string"),
......@@ -228,15 +226,14 @@ public class QuickStartV2 {
AtlasTypeUtil.createOptionalAttrDef("name", "string"),
AtlasTypeUtil.createOptionalAttrDef("dataType", "string"),
AtlasTypeUtil.createOptionalAttrDef("comment", "string"),
AtlasTypeUtil.createOptionalAttrDefWithConstraint("table", TABLE_TYPE, CONSTRAINT_TYPE_FOREIGN_KEY,
new HashMap<String, Object>() {{ put(CONSTRAINT_PARAM_ON_DELETE, CONSTRAINT_PARAM_VAL_CASCADE); }}));
AtlasTypeUtil.createOptionalAttrDefWithConstraint("table", TABLE_TYPE, CONSTRAINT_TYPE_INVERSE_REF,
new HashMap<String, Object>() {{ put(CONSTRAINT_PARAM_ATTRIBUTE, "table"); }}));
colType.setOptions(new HashMap<String, String>() {{ put("schemaAttributes", "[\"name\", \"description\", \"owner\", \"type\", \"comment\", \"position\"]"); }});
AtlasEntityDef tblType = AtlasTypeUtil.createClassTypeDef(TABLE_TYPE, TABLE_TYPE, "1.0", ImmutableSet.of("DataSet"),
AtlasTypeUtil.createRequiredAttrDef("db", DATABASE_TYPE),
AtlasTypeUtil.createRequiredAttrDefWithConstraint("sd", STORAGE_DESC_TYPE, CONSTRAINT_TYPE_MAPPED_FROM_REF,
new HashMap<String, Object>() {{ put(CONSTRAINT_PARAM_REF_ATTRIBUTE, "table"); }}),
AtlasTypeUtil.createRequiredAttrDefWithConstraint("sd", STORAGE_DESC_TYPE, CONSTRAINT_TYPE_OWNED_REF, null),
AtlasTypeUtil.createOptionalAttrDef("owner", "string"),
AtlasTypeUtil.createOptionalAttrDef("createTime", "long"),
AtlasTypeUtil.createOptionalAttrDef("lastAccessTime", "long"),
......@@ -246,7 +243,7 @@ public class QuickStartV2 {
AtlasTypeUtil.createOptionalAttrDef("tableType", "string"),
AtlasTypeUtil.createOptionalAttrDef("temporary", "boolean"),
AtlasTypeUtil.createRequiredListAttrDefWithConstraint("columns", AtlasBaseTypeDef.getArrayTypeName(COLUMN_TYPE),
CONSTRAINT_TYPE_MAPPED_FROM_REF, new HashMap<String, Object>() {{ put(CONSTRAINT_PARAM_REF_ATTRIBUTE, "table"); }}));
CONSTRAINT_TYPE_OWNED_REF, null));
tblType.setOptions(new HashMap<String, String>() {{ put("schemaElementsAttribute", "columns"); }});
......
......@@ -19,21 +19,18 @@
package org.apache.atlas.util;
import static org.apache.atlas.AtlasErrorCode.INVALID_TYPE_DEFINITION;
import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef.CONSTRAINT_PARAM_ON_DELETE;
import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef.CONSTRAINT_PARAM_VAL_CASCADE;
import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef.CONSTRAINT_TYPE_FOREIGN_KEY;
import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef.CONSTRAINT_TYPE_MAPPED_FROM_REF;
import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef.CONSTRAINT_TYPE_OWNED_REF;
import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef.CONSTRAINT_TYPE_INVERSE_REF;
import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef.CONSTRAINT_PARAM_ATTRIBUTE;
import static org.apache.atlas.type.AtlasTypeUtil.isArrayType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.TypeCategory;
import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.typedef.AtlasClassificationDef;
import org.apache.atlas.model.typedef.AtlasEntityDef;
import org.apache.atlas.model.typedef.AtlasEnumDef;
......@@ -45,7 +42,6 @@ import org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef;
import org.apache.atlas.model.typedef.AtlasTypeDefHeader;
import org.apache.atlas.model.typedef.AtlasTypesDef;
import org.apache.atlas.repository.store.graph.v1.AtlasStructDefStoreV1;
import org.apache.atlas.type.AtlasArrayType;
import org.apache.atlas.type.AtlasClassificationType;
import org.apache.atlas.type.AtlasEntityType;
import org.apache.atlas.type.AtlasEnumType;
......@@ -73,6 +69,13 @@ import org.slf4j.LoggerFactory;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import static org.apache.atlas.AtlasErrorCode.INVALID_TYPE_DEFINITION;
import static org.apache.atlas.type.AtlasTypeUtil.isArrayType;
public final class RestUtils {
......@@ -307,85 +310,6 @@ public final class RestUtils {
AttributeDefinition[] attrDefinitions = classType.attributeDefinitions;
for (AttributeDefinition oldAttr : attrDefinitions) {
AtlasAttributeDef newAttr = toAtlasAttributeDef(oldAttr);
// isComposite and reverseAttributeName applicable only for entities/classes.
if (oldAttr.isComposite) {
String attrType = oldAttr.dataTypeName;
attrType = isArrayType(attrType) ? getArrayTypeName(attrType) : attrType;
if (!AtlasTypeUtil.isBuiltInType(attrType)) {
String refAttrName = null;
// 1. Check if attribute datatype is present in payload definition, if present get the typeDefinition,
// check all its attributes and find attribute that matches with classTypeDefName and reverseAttributeName
HierarchicalTypeDefinition<ClassType> refType = findClassType(classTypeDefinitions, attrType);
if (refType != null) {
for (AttributeDefinition refAttr : refType.attributeDefinitions) {
String refAttrDataTypeName = refAttr.dataTypeName;
String refAttrRevAttrName = refAttr.reverseAttributeName;
if (StringUtils.equals(refAttrDataTypeName, classTypeDefName) &&
StringUtils.equals(refAttrRevAttrName, oldAttr.name)) {
refAttrName = refAttr.name;
break;
}
}
}
// 2. Check if attribute present in typeRegistry. If present fetch all attributes associated with the type and
// check revAttrName equals base type attr name AND classTypeDefName equals attribute name
else {
if (registry.isRegisteredType(attrType)) {
AtlasType atlasType = registry.getType(attrType);
if (isEntity(atlasType)) {
AtlasEntityType entityType = (AtlasEntityType) atlasType;
List<AtlasAttributeDef> atlasAttrDefs = entityType.getEntityDef().getAttributeDefs();
for (AtlasAttributeDef attrDef : atlasAttrDefs) {
boolean isForeignKey = entityType.isForeignKeyAttribute(attrDef.getName());
if (isForeignKey) {
AtlasType attribType = entityType.getAttributeType(attrDef.getName());
if (attribType != null) {
if (attribType.getTypeCategory() == TypeCategory.ARRAY) {
attribType = ((AtlasArrayType) attribType).getElementType();
}
if (attribType.getTypeCategory() == TypeCategory.ENTITY) {
String revAttrName = ((AtlasEntityType) attribType).
getMappedFromRefAttribute(entityType.getTypeName(), attrDef.getName());
if (StringUtils.equals(classTypeDefName, attrDef.getTypeName()) &&
StringUtils.equals(oldAttr.name, revAttrName)) {
refAttrName = attrDef.getName();
}
}
}
}
}
}
}
}
if (StringUtils.isNotBlank(refAttrName)) { // ex: hive_table.columns, hive_column.table
Map<String, Object> params = new HashMap<>();
params.put(AtlasConstraintDef.CONSTRAINT_PARAM_REF_ATTRIBUTE, refAttrName);
newAttr.addConstraint(new AtlasConstraintDef(CONSTRAINT_TYPE_MAPPED_FROM_REF, params));
} else { // ex: hive_table.partitionKeys, with no reverseAttribute-reference
newAttr.addConstraint(new AtlasConstraintDef(CONSTRAINT_TYPE_FOREIGN_KEY));
}
}
} else if (StringUtils.isNotEmpty(oldAttr.reverseAttributeName)) {
Map<String, Object> params = new HashMap<>();
params.put(CONSTRAINT_PARAM_ON_DELETE, CONSTRAINT_PARAM_VAL_CASCADE);
newAttr.addConstraint(new AtlasConstraintDef(CONSTRAINT_TYPE_FOREIGN_KEY, params));
}
attrDefs.add(newAttr);
}
......@@ -432,13 +356,23 @@ public final class RestUtils {
return ret.toArray(new EnumValue[ret.size()]);
}
private static AtlasAttributeDef toAtlasAttributeDef(AttributeDefinition attrDefinition) {
private static AtlasAttributeDef toAtlasAttributeDef(final AttributeDefinition attrDefinition) {
AtlasAttributeDef ret = new AtlasAttributeDef();
ret.setName(attrDefinition.name);
ret.setTypeName(attrDefinition.dataTypeName);
ret.setIsIndexable(attrDefinition.isIndexable);
ret.setIsUnique(attrDefinition.isUnique);
if (attrDefinition.isComposite) {
ret.addConstraint(new AtlasConstraintDef(CONSTRAINT_TYPE_OWNED_REF));
}
if (StringUtils.isNotBlank(attrDefinition.reverseAttributeName)) {
ret.addConstraint(new AtlasConstraintDef(CONSTRAINT_TYPE_INVERSE_REF,
new HashMap<String, Object>() {{
put(CONSTRAINT_PARAM_ATTRIBUTE, attrDefinition.reverseAttributeName);
}}));
}
// Multiplicity attribute mapping
Multiplicity multiplicity = attrDefinition.multiplicity;
......
......@@ -136,7 +136,7 @@ public class AtlasStructFormatConverter extends AtlasAbstractFormatConverter {
Object v1Value = null;
AtlasFormatConverter attrConverter = null;
if (attrType.getTypeCategory() == TypeCategory.ENTITY && !attr.legacyIsComposite()) {
if (attrType.getTypeCategory() == TypeCategory.ENTITY && !attr.isOwnedRef()) {
attrConverter = new AtlasObjectIdConverter(converterRegistry, typeRegistry);
v1Value = attrConverter.fromV2ToV1(v2Value, attrType, context);
} else {
......
......@@ -18,9 +18,9 @@
package org.apache.atlas.web.resources;
import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef.CONSTRAINT_PARAM_ON_DELETE;
import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef.CONSTRAINT_PARAM_VAL_CASCADE;
import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef.CONSTRAINT_TYPE_FOREIGN_KEY;
import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef.CONSTRAINT_TYPE_OWNED_REF;
import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef.CONSTRAINT_TYPE_INVERSE_REF;
import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef.CONSTRAINT_PARAM_ATTRIBUTE;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
......@@ -408,11 +408,10 @@ public abstract class BaseResourceIT {
protected void createTypeDefinitionsV2() throws Exception {
AtlasConstraintDef isCompositeSourceConstraint = new AtlasConstraintDef(CONSTRAINT_TYPE_FOREIGN_KEY,
Collections.<String, Object>singletonMap(CONSTRAINT_PARAM_ON_DELETE, CONSTRAINT_PARAM_VAL_CASCADE));
AtlasConstraintDef isCompositeSourceConstraint = new AtlasConstraintDef(CONSTRAINT_TYPE_OWNED_REF);
AtlasConstraintDef isCompositeTargetConstraint = new AtlasConstraintDef(CONSTRAINT_TYPE_FOREIGN_KEY,
Collections.<String, Object>emptyMap());
AtlasConstraintDef isCompositeTargetConstraint = new AtlasConstraintDef(CONSTRAINT_TYPE_INVERSE_REF,
Collections.<String, Object>singletonMap(CONSTRAINT_PARAM_ATTRIBUTE, "randomTable"));
AtlasEntityDef dbClsTypeDef = AtlasTypeUtil.createClassTypeDef(
DATABASE_TYPE_V2,
......
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