Commit 242b5585 by Sarath Subramanian Committed by Madhan Neethiraj

ATLAS-1856: AtlasRelationship instance implementation Java/REST

parent c2d52759
......@@ -19,5 +19,5 @@
package org.apache.atlas.authorize;
public enum AtlasResourceTypes {
UNKNOWN, ENTITY, TYPE, OPERATION, TAXONOMY, TERM
UNKNOWN, ENTITY, TYPE, OPERATION, TAXONOMY, TERM, RELATION
}
......@@ -139,6 +139,8 @@ public class AtlasAuthorizationUtils {
if (contextPath.contains("/terms")) {
resourceTypes.add(AtlasResourceTypes.TERM);
}
} else if (api.startsWith("relation")) {
resourceTypes.add(AtlasResourceTypes.RELATION);
} else {
LOG.error("Unable to find Atlas Resource corresponding to : {}\nSetting {}"
, api, AtlasResourceTypes.UNKNOWN.name());
......
......@@ -231,6 +231,8 @@ public class PolicyParser {
resourceType = AtlasResourceTypes.TAXONOMY;
} else if (type.equalsIgnoreCase("TERM")) {
resourceType = AtlasResourceTypes.TERM;
} else if (type.equalsIgnoreCase("RELATION")) {
resourceType = AtlasResourceTypes.RELATION;
} else {
Log.warn(type + " is invalid resource please check PolicyStore file");
continue;
......
......@@ -60,6 +60,12 @@ public interface AtlasGraphQuery<V, E> {
*/
Iterable<AtlasVertex<V, E>> vertices();
/**
* Executes the query and returns the matching edges.
* @return
*/
Iterable<AtlasEdge<V, E>> edges();
/**
* Adds a predicate that the returned vertices must have the specified
......
......@@ -19,6 +19,7 @@ package org.apache.atlas.repository.graphdb.titan.query;
import java.util.Collection;
import org.apache.atlas.repository.graphdb.AtlasEdge;
import org.apache.atlas.repository.graphdb.AtlasGraphQuery.ComparisionOperator;
import org.apache.atlas.repository.graphdb.AtlasVertex;
......@@ -39,6 +40,11 @@ public interface NativeTitanGraphQuery<V, E> {
*/
Iterable<AtlasVertex<V, E>> vertices();
/**
* Executes the graph query.
* @return
*/
Iterable<AtlasEdge<V, E>> edges();
/**
* Adds an in condition to the query.
......
......@@ -22,6 +22,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.atlas.repository.graphdb.AtlasEdge;
import org.apache.atlas.repository.graphdb.AtlasGraph;
import org.apache.atlas.repository.graphdb.AtlasGraphQuery;
import org.apache.atlas.repository.graphdb.AtlasVertex;
......@@ -121,8 +122,10 @@ public abstract class TitanGraphQuery<V, E> implements AtlasGraphQuery<V, E> {
@Override
public Iterable<AtlasVertex<V, E>> vertices() {
LOG.debug("Executing: ");
LOG.debug(queryCondition.toString());
if (LOG.isDebugEnabled()) {
LOG.debug("Executing: " + queryCondition.toString());
}
//compute the overall result by unioning the results from all of the
//AndConditions together.
Set<AtlasVertex<V, E>> result = new HashSet<>();
......@@ -136,6 +139,24 @@ public abstract class TitanGraphQuery<V, E> implements AtlasGraphQuery<V, E> {
}
@Override
public Iterable<AtlasEdge<V, E>> edges() {
if (LOG.isDebugEnabled()) {
LOG.debug("Executing: " + queryCondition.toString());
}
//compute the overall result by unioning the results from all of the
//AndConditions together.
Set<AtlasEdge<V, E>> result = new HashSet<>();
for(AndCondition andExpr : queryCondition.getAndTerms()) {
NativeTitanGraphQuery<V, E> andQuery = andExpr.create(getQueryFactory());
for(AtlasEdge<V, E> edge : andQuery.edges()) {
result.add(edge);
}
}
return result;
}
@Override
public AtlasGraphQuery<V, E> has(String propertyKey, ComparisionOperator operator,
Object value) {
queryCondition.andWith(new HasPredicate(propertyKey, operator, value));
......
......@@ -19,6 +19,7 @@ package org.apache.atlas.repository.graphdb.titan0.query;
import java.util.Collection;
import org.apache.atlas.repository.graphdb.AtlasEdge;
import org.apache.atlas.repository.graphdb.AtlasGraphQuery.ComparisionOperator;
import org.apache.atlas.repository.graphdb.AtlasVertex;
import org.apache.atlas.repository.graphdb.titan.query.NativeTitanGraphQuery;
......@@ -54,6 +55,11 @@ public class NativeTitan0GraphQuery implements NativeTitanGraphQuery<Titan0Verte
return graph.wrapVertices(it);
}
@Override
public Iterable<AtlasEdge<Titan0Vertex, Titan0Edge>> edges() {
Iterable it = query.edges();
return graph.wrapEdges(it);
}
@Override
public void in(String propertyName, Collection<?> values) {
......
......@@ -384,11 +384,6 @@ public class Titan1Graph implements AtlasGraph<Titan1Vertex, Titan1Edge> {
return expr;
}
public Iterable<AtlasEdge<Titan1Vertex, Titan1Edge>> wrapEdges(Iterator<Edge> it) {
Iterable<Edge> iterable = new IteratorToIterableAdapter<Edge>(it);
return wrapEdges(iterable);
}
public Iterable<AtlasVertex<Titan1Vertex, Titan1Edge>> wrapVertices(Iterator<? extends Vertex> it) {
Iterable<? extends Vertex> iterable = new IteratorToIterableAdapter<>(it);
return wrapVertices(iterable);
......@@ -406,15 +401,21 @@ public class Titan1Graph implements AtlasGraph<Titan1Vertex, Titan1Edge> {
}
public Iterable<AtlasEdge<Titan1Vertex, Titan1Edge>> wrapEdges(Iterable<Edge> it) {
Iterable<Edge> result = (Iterable<Edge>) it;
return Iterables.transform(result, new Function<Edge, AtlasEdge<Titan1Vertex, Titan1Edge>>() {
public Iterable<AtlasEdge<Titan1Vertex, Titan1Edge>> wrapEdges(Iterator<? extends Edge> it) {
Iterable<? extends Edge> iterable = new IteratorToIterableAdapter<>(it);
return wrapEdges(iterable);
}
public Iterable<AtlasEdge<Titan1Vertex, Titan1Edge>> wrapEdges(Iterable<? extends Edge> it) {
return Iterables.transform(it, new Function<Edge, AtlasEdge<Titan1Vertex, Titan1Edge>>() {
@Override
public AtlasEdge<Titan1Vertex, Titan1Edge> apply(Edge input) {
return GraphDbObjectFactory.createEdge(Titan1Graph.this, input);
}
});
}
@Override
......
......@@ -19,6 +19,8 @@ package org.apache.atlas.repository.graphdb.titan1.query;
import java.util.Collection;
import com.thinkaurelius.titan.core.TitanEdge;
import org.apache.atlas.repository.graphdb.AtlasEdge;
import org.apache.atlas.repository.graphdb.AtlasGraphQuery.ComparisionOperator;
import org.apache.atlas.repository.graphdb.AtlasVertex;
import org.apache.atlas.repository.graphdb.titan.query.NativeTitanGraphQuery;
......@@ -53,6 +55,12 @@ public class NativeTitan1GraphQuery implements NativeTitanGraphQuery<Titan1Verte
}
@Override
public Iterable<AtlasEdge<Titan1Vertex, Titan1Edge>> edges() {
Iterable<TitanEdge> it = query.edges();
return graph.wrapEdges(it);
}
@Override
public void in(String propertyName, Collection<? extends Object> values) {
query.has(propertyName, Contain.IN, values);
......
......@@ -79,6 +79,8 @@ public enum AtlasErrorCode {
RELATIONSHIPDEF_AGGREGATION_NO_CONTAINER(400, "ATLAS-400-00-032", "AGGREGATION relationshipDef {0} creation attempted without an end specifying isContainer"),
RELATIONSHIPDEF_COMPOSITION_SET_CONTAINER(400, "ATLAS-400-00-033", "COMPOSITION relationshipDef {0} cannot have a SET cardinality and be a container"),
RELATIONSHIPDEF_LIST_ON_END(400, "ATLAS-400-00-034", "relationshipDef {0} cannot have a LIST cardinality on an end"),
RELATIONSHIPDEF_INVALID_END_TYPE(400, "ATLAS-400-00-035", "relationshipDef {0} has invalid end type {1}"),
INVALID_RELATIONSHIP_END_TYPE(400, "ATLAS-400-00-036", "invalid end type for relationship {0}: expected {1}, found {2}"),
// All Not found enums go here
TYPE_NAME_NOT_FOUND(404, "ATLAS-404-00-001", "Given typename {0} was invalid"),
TYPE_GUID_NOT_FOUND(404, "ATLAS-404-00-002", "Given type guid {0} was invalid"),
......@@ -90,11 +92,13 @@ public enum AtlasErrorCode {
INSTANCE_BY_UNIQUE_ATTRIBUTE_NOT_FOUND(404, "ATLAS-404-00-009", "Instance {0} with unique attribute {1} does not exist"),
REFERENCED_ENTITY_NOT_FOUND(404, "ATLAS-404-00-00A", "Referenced entity {0} is not found"),
INSTANCE_NOT_FOUND(404, "ATLAS-404-00-00B", "Given instance is invalid/not found: {0}"),
RELATIONSHIP_GUID_NOT_FOUND(404, "ATLAS-404-00-00C", "Given relationship guid {0} is invalid/not found"),
// All data conflict errors go here
TYPE_ALREADY_EXISTS(409, "ATLAS-409-00-001", "Given type {0} already exists"),
TYPE_HAS_REFERENCES(409, "ATLAS-409-00-002", "Given type {0} has references"),
INSTANCE_ALREADY_EXISTS(409, "ATLAS-409-00-003", "failed to update entity: {0}"),
RELATIONSHIP_ALREADY_EXISTS(409, "ATLAS-409-00-004", "relationship {0} already exists between entities {1} and {2}"),
// All internal errors go here
INTERNAL_ERROR(500, "ATLAS-500-00-001", "Internal server error {0}"),
......
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.atlas.model.instance;
import org.apache.atlas.model.typedef.AtlasRelationshipDef;
import org.codehaus.jackson.annotate.JsonAutoDetect;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;
import java.util.Date;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicLong;
import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.NONE;
import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.PUBLIC_ONLY;
/**
* Atlas relationship instance.
*/
@JsonAutoDetect(getterVisibility=PUBLIC_ONLY, setterVisibility=PUBLIC_ONLY, fieldVisibility=NONE)
@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown=true)
@XmlRootElement
@XmlAccessorType(XmlAccessType.PROPERTY)
public class AtlasRelationship extends AtlasStruct implements Serializable {
private static final long serialVersionUID = 1L;
private String guid = null;
private AtlasObjectId end1 = null;
private AtlasObjectId end2 = null;
private Status status = Status.ACTIVE;
private String createdBy = null;
private String updatedBy = null;
private Date createTime = null;
private Date updateTime = null;
private Long version = 0L;
public enum Status { ACTIVE, DELETED }
@JsonIgnore
private static AtomicLong s_nextId = new AtomicLong(System.nanoTime());
public AtlasRelationship() {
super();
init();
}
public AtlasRelationship(String typeName) {
this(typeName, null);
}
public AtlasRelationship(String typeName, Map<String, Object> attributes) {
super(typeName, attributes);
init();
}
public AtlasRelationship(String typeName, AtlasObjectId end1, AtlasObjectId end2) {
super(typeName);
init(nextInternalId(), end1, end2, null, null, null, null, null, 0L);
}
public AtlasRelationship(String typeName, String attrName, Object attrValue) {
super(typeName, attrName, attrValue);
init();
}
public AtlasRelationship(AtlasRelationshipDef relationshipDef) {
this(relationshipDef != null ? relationshipDef.getName() : null);
}
public AtlasRelationship(AtlasRelationship other) {
super(other);
if (other != null) {
init(other.guid, other.end1, other.end2, other.status, other.createdBy, other.updatedBy,
other.createTime, other.updateTime, other.version);
}
}
public String getGuid() {
return guid;
}
public void setGuid(String guid) {
this.guid = guid;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
public String getCreatedBy() {
return createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
public String getUpdatedBy() {
return updatedBy;
}
public void setUpdatedBy(String updatedBy) {
this.updatedBy = updatedBy;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
public Long getVersion() {
return version;
}
public void setVersion(Long version) {
this.version = version;
}
public AtlasObjectId getEnd1() { return end1; }
public void setEnd1(AtlasObjectId end1) { this.end1 = end1; }
public AtlasObjectId getEnd2() { return end2; }
public void setEnd2(AtlasObjectId end2) { this.end2 = end2; }
private static String nextInternalId() {
return "-" + Long.toString(s_nextId.getAndIncrement());
}
public String getRelationshipLabel() { return "r:" + super.getTypeName(); }
private void init() {
init(nextInternalId(), null, null, null, null, null, null, null, 0L);
}
private void init(String guid, AtlasObjectId end1, AtlasObjectId end2,
Status status, String createdBy, String updatedBy,
Date createTime, Date updateTime, Long version) {
setGuid(guid);
setEnd1(end1);
setEnd2(end2);
setStatus(status);
setCreatedBy(createdBy);
setUpdatedBy(updatedBy);
setCreateTime(createTime);
setUpdateTime(updateTime);
setVersion(version);
}
@Override
public StringBuilder toString(StringBuilder sb) {
if (sb == null) {
sb = new StringBuilder();
}
sb.append("AtlasRelationship{");
super.toString(sb);
sb.append("guid='").append(guid).append('\'');
sb.append(", end1=").append(end1);
sb.append(", end2=").append(end2);
sb.append(", status=").append(status);
sb.append(", createdBy='").append(createdBy).append('\'');
sb.append(", updatedBy='").append(updatedBy).append('\'');
dumpDateField(", createTime=", createTime, sb);
dumpDateField(", updateTime=", updateTime, sb);
sb.append(", version=").append(version);
sb.append('}');
return sb;
}
@Override
public boolean equals(Object o) {
if (this == o) { return true; }
if (o == null || getClass() != o.getClass()) { return false; }
if (!super.equals(o)) { return false; }
AtlasRelationship that = (AtlasRelationship) o;
return Objects.equals(guid, that.guid) &&
Objects.equals(end1, that.end1) &&
Objects.equals(end2, that.end2) &&
status == that.status &&
Objects.equals(createdBy, that.createdBy) &&
Objects.equals(updatedBy, that.updatedBy) &&
Objects.equals(createTime, that.createTime) &&
Objects.equals(updateTime, that.updateTime) &&
Objects.equals(version, that.version);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), guid, end1, end2, status, createdBy, updatedBy, createTime, updateTime, version);
}
@Override
public String toString() {
return toString(new StringBuilder()).toString();
}
}
\ No newline at end of file
......@@ -18,6 +18,7 @@
package org.apache.atlas.model.typedef;
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.JsonIgnoreProperties;
import org.codehaus.jackson.map.annotate.JsonSerialize;
......@@ -59,6 +60,10 @@ public class AtlasRelationshipEndDef implements Serializable {
* This is the cardinality of the end
*/
private Cardinality cardinality;
/**
* legacy edge label name of the endpoint
*/
private String legacyLabel;
/**
* Base constructor
......@@ -92,10 +97,29 @@ public class AtlasRelationshipEndDef implements Serializable {
* - whether the end is a container or not
*/
public AtlasRelationshipEndDef(String typeName, String name, Cardinality cardinality, boolean isContainer) {
this(typeName, name, cardinality, isContainer, null);
}
public AtlasRelationshipEndDef(String typeName, String name, Cardinality cardinality, boolean isContainer, String legacyLabel) {
setType(typeName);
setName(name);
setCardinality(cardinality);
setIsContainer(isContainer);
setLegacyLabel(legacyLabel);
}
/**
* Construct using an existing AtlasRelationshipEndDef
* @param other
*/
public AtlasRelationshipEndDef(AtlasRelationshipEndDef other) {
if (other != null) {
setType(other.getType());
setName(other.getName());
setIsContainer(other.getIsContainer());
setCardinality(other.getCardinality());
setLegacyLabel(other.getLegacyLabel());
}
}
public void setType(String type) {
......@@ -142,18 +166,15 @@ public class AtlasRelationshipEndDef implements Serializable {
return this.cardinality;
}
/**
* Construct using an existing AtlasRelationshipEndDef
* @param other
*/
public AtlasRelationshipEndDef(AtlasRelationshipEndDef other) {
if (other != null) {
setType(other.getType());
setName(other.getName());
setIsContainer(other.getIsContainer());
setCardinality(other.getCardinality());
}
}
public boolean isContainer() { return isContainer; }
public void setContainer(boolean container) { isContainer = container; }
public String getLegacyLabel() { return legacyLabel; }
public void setLegacyLabel(String legacyLabel) { this.legacyLabel = legacyLabel; }
public boolean hasLegacyRelation() { return StringUtils.isNotEmpty(getLegacyLabel()) ? true : false; }
public StringBuilder toString(StringBuilder sb) {
if (sb == null) {
......@@ -165,6 +186,7 @@ public class AtlasRelationshipEndDef implements Serializable {
sb.append(", name==>'").append(name).append('\'');
sb.append(", isContainer==>'").append(isContainer).append('\'');
sb.append(", cardinality==>'").append(cardinality).append('\'');
sb.append(", legacyLabel==>'").append(legacyLabel).append('\'');
sb.append('}');
return sb;
......@@ -177,13 +199,17 @@ public class AtlasRelationshipEndDef implements Serializable {
if (o == null || getClass() != o.getClass())
return false;
AtlasRelationshipEndDef that = (AtlasRelationshipEndDef) o;
return Objects.equals(type, that.type) && Objects.equals(name, that.name)
&& (isContainer == that.isContainer) && (cardinality == that.cardinality);
return Objects.equals(type, that.type) &&
Objects.equals(name, that.name) &&
isContainer == that.isContainer &&
cardinality == that.cardinality &&
Objects.equals(legacyLabel, that.legacyLabel);
}
@Override
public int hashCode() {
return Objects.hash(type, getName(), isContainer, cardinality);
return Objects.hash(type, getName(), isContainer, cardinality, legacyLabel);
}
@Override
......
......@@ -128,6 +128,10 @@ public class AtlasEntityType extends AtlasStructType {
return StringUtils.isNotEmpty(entityTypeName) && allSubTypes.contains(entityTypeName);
}
public boolean isTypeOrSuperTypeOf(String entityTypeName) {
return StringUtils.isNotEmpty(entityTypeName) && typeAndAllSubTypes.contains(entityTypeName);
}
public boolean isSubTypeOf(AtlasEntityType entityType) {
return entityType != null && allSuperTypes.contains(entityType.getTypeName());
}
......
......@@ -35,6 +35,8 @@ public class AtlasRelationshipType extends AtlasStructType {
private static final Logger LOG = LoggerFactory.getLogger(AtlasRelationshipType.class);
private final AtlasRelationshipDef relationshipDef;
private AtlasEntityType end1Type;
private AtlasEntityType end2Type;
public AtlasRelationshipType(AtlasRelationshipDef relationshipDef) {
super(relationshipDef);
......@@ -55,6 +57,24 @@ public class AtlasRelationshipType extends AtlasStructType {
public void resolveReferences(AtlasTypeRegistry typeRegistry) throws AtlasBaseException {
super.resolveReferences(typeRegistry);
String end1TypeName = relationshipDef != null && relationshipDef.getEndDef1() != null ? relationshipDef.getEndDef1().getType() : null;
String end2TypeName = relationshipDef != null && relationshipDef.getEndDef2() != null ? relationshipDef.getEndDef2().getType() : null;
AtlasType type1 = typeRegistry.getType(end1TypeName);
AtlasType type2 = typeRegistry.getType(end2TypeName);
if (type1 instanceof AtlasEntityType) {
end1Type = (AtlasEntityType)type1;
} else {
throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIPDEF_INVALID_END_TYPE, getTypeName(), end1TypeName);
}
if (type2 instanceof AtlasEntityType) {
end2Type = (AtlasEntityType)type2;
} else {
throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIPDEF_INVALID_END_TYPE, getTypeName(), end2TypeName);
}
validateAtlasRelationshipDef(this.relationshipDef);
}
......@@ -81,6 +101,11 @@ public class AtlasRelationshipType extends AtlasStructType {
return ret;
}
public AtlasEntityType getEnd1Type() { return end1Type; }
public AtlasEntityType getEnd2Type() { return end2Type; }
/**
* Validate the fields in the the RelationshipType are consistent with respect to themselves.
* @param type
......
......@@ -186,6 +186,7 @@ public class AtlasTypeRegistry {
return registryData.classificationDefs.getTypeByName(name);
}
public Collection<AtlasRelationshipDef> getAllRelationshipDefs() { return registryData.relationshipDefs.getAll(); }
public Collection<AtlasEntityDef> getAllEntityDefs() { return registryData.entityDefs.getAll(); }
public AtlasEntityDef getEntityDefByGuid(String guid) {
......@@ -211,6 +212,7 @@ public class AtlasTypeRegistry {
return registryData.relationshipDefs.getTypeDefByName(name);
}
public AtlasRelationshipType getRelationshipTypeByName(String name) { return registryData.relationshipDefs.getTypeByName(name); }
public AtlasTransientTypeRegistry lockTypeRegistryForUpdate() throws AtlasBaseException {
return lockTypeRegistryForUpdate(DEFAULT_LOCK_MAX_WAIT_TIME_IN_SECONDS);
}
......@@ -347,6 +349,7 @@ public class AtlasTypeRegistry {
addTypesWithNoRefResolve(parent.getAllStructDefs());
addTypesWithNoRefResolve(parent.getAllClassificationDefs());
addTypesWithNoRefResolve(parent.getAllEntityDefs());
addTypesWithNoRefResolve(parent.getAllRelationshipDefs());
addedTypes.clear();
updatedTypes.clear();
......
......@@ -24,7 +24,9 @@ import com.google.common.collect.HashBiMap;
import org.apache.atlas.ApplicationProperties;
import org.apache.atlas.AtlasException;
import org.apache.atlas.RequestContext;
import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.instance.AtlasEntity.Status;
import org.apache.atlas.model.instance.AtlasRelationship;
import org.apache.atlas.repository.Constants;
import org.apache.atlas.repository.RepositoryException;
import org.apache.atlas.repository.graphdb.AtlasEdge;
......@@ -259,31 +261,42 @@ public final class GraphHelper {
* Searches for a AtlasVertex with prop1=key1 && prop2=key2
* @param args
* @return AtlasVertex with the given property keys
* @throws EntityNotFoundException
* @throws AtlasBaseException
*/
public AtlasVertex findVertex(Object... args) throws EntityNotFoundException {
return (AtlasVertex) findElement(true, args);
}
/**
* Args of the format prop1, key1, prop2, key2...
* Searches for a AtlasEdge with prop1=key1 && prop2=key2
* @param args
* @return AtlasEdge with the given property keys
* @throws AtlasBaseException
*/
public AtlasEdge findEdge(Object... args) throws EntityNotFoundException {
return (AtlasEdge) findElement(false, args);
}
private AtlasElement findElement(boolean isVertexSearch, Object... args) throws EntityNotFoundException {
AtlasGraphQuery query = graph.query();
for (int i = 0 ; i < args.length; i+=2) {
query = query.has((String) args[i], args[i+1]);
for (int i = 0; i < args.length; i += 2) {
query = query.has((String) args[i], args[i + 1]);
}
Iterator<AtlasVertex> results = query.vertices().iterator();
// returning one since entityType, qualifiedName should be unique
AtlasVertex vertex = results.hasNext() ? results.next() : null;
Iterator<AtlasElement> results = isVertexSearch ? query.vertices().iterator() : query.edges().iterator();
AtlasElement element = (results != null && results.hasNext()) ? results.next() : null;
if (vertex == null) {
String conditionStr = getConditionString(args);
if (LOG.isDebugEnabled()) {
LOG.debug("Could not find a vertex with {}", conditionStr);
}
throw new EntityNotFoundException("Could not find an entity in the repository with " + conditionStr);
} else {
if (LOG.isDebugEnabled()) {
LOG.debug("Found a vertex {} with {}", string(vertex), getConditionString(args));
}
if (element == null) {
throw new EntityNotFoundException("Could not find " + (isVertexSearch ? "vertex" : "edge") + " with condition: " + getConditionString(args));
}
if (LOG.isDebugEnabled()) {
LOG.debug("Found {} with condition {}", string(element), getConditionString(args));
}
return vertex;
return element;
}
//In some cases of parallel APIs, the edge is added, but get edge by label doesn't return the edge. ATLAS-1104
......@@ -534,6 +547,9 @@ public final class GraphHelper {
return findVertex(Constants.GUID_PROPERTY_KEY, guid);
}
public AtlasEdge getEdgeForGUID(String guid) throws EntityNotFoundException {
return findEdge(Constants.GUID_PROPERTY_KEY, guid);
}
/**
* Finds the Vertices that correspond to the given property values. Property
......@@ -646,12 +662,12 @@ public final class GraphHelper {
return getIdFromVertex(getTypeName(vertex), vertex);
}
public static String getGuid(AtlasVertex vertex) {
return vertex.<String>getProperty(Constants.GUID_PROPERTY_KEY, String.class);
public static String getGuid(AtlasElement element) {
return element.<String>getProperty(Constants.GUID_PROPERTY_KEY, String.class);
}
public static String getTypeName(AtlasVertex instanceVertex) {
return instanceVertex.getProperty(Constants.ENTITY_TYPE_PROPERTY_KEY, String.class);
public static String getTypeName(AtlasElement element) {
return element.getProperty(Constants.ENTITY_TYPE_PROPERTY_KEY, String.class);
}
public static Id.EntityState getState(AtlasElement element) {
......@@ -663,8 +679,6 @@ public final class GraphHelper {
return element.getProperty(Constants.VERSION_PROPERTY_KEY, Integer.class);
}
public static String getStateAsString(AtlasElement element) {
return element.getProperty(Constants.STATE_PROPERTY_KEY, String.class);
}
......@@ -673,6 +687,10 @@ public final class GraphHelper {
return (getState(element) == Id.EntityState.DELETED) ? Status.DELETED : Status.ACTIVE;
}
public static AtlasRelationship.Status getEdgeStatus(AtlasElement element) {
return (getState(element) == Id.EntityState.DELETED) ? AtlasRelationship.Status.DELETED : AtlasRelationship.Status.ACTIVE;
}
//Added conditions in fetching system attributes to handle test failures in GremlinTest where these properties are not set
public static String getCreatedByAsString(AtlasElement element){
return element.getProperty(Constants.CREATED_BY_KEY, String.class);
......
/**
* 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;
import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.instance.AtlasRelationship;
/**
* Persistence/Retrieval API for AtlasRelationship
*/
public interface AtlasRelationshipStore {
/**
* Create a new relationship instance.
* @param relationship relationship instance definition
* @return AtlasRelationship d
*/
AtlasRelationship create(AtlasRelationship relationship) throws AtlasBaseException;
/**
* Update an existing relationship instance.
* @param relationship relationship instance definition
* @return AtlasRelationship d
*/
AtlasRelationship update(AtlasRelationship relationship) throws AtlasBaseException;
/**
* Retrieve a relationship instance using guid.
* @param guid relationship instance guid
* @return AtlasRelationship
*/
AtlasRelationship getById(String guid) throws AtlasBaseException;
/**
* Delete a relationship instance using guid.
* @param guid relationship instance guid
*/
void deleteById(String guid) throws AtlasBaseException;
}
......@@ -35,6 +35,7 @@ import org.apache.atlas.type.AtlasStructType;
import org.apache.atlas.type.AtlasStructType.AtlasAttribute;
import org.apache.atlas.type.AtlasType;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -234,6 +235,18 @@ public class AtlasGraphUtilsV1 {
return vertex;
}
public static String getTypeNameFromGuid(String guid) {
String ret = null;
if (StringUtils.isNotEmpty(guid)) {
AtlasVertex vertex = AtlasGraphUtilsV1.findByGuid(guid);
ret = (vertex != null) ? AtlasGraphUtilsV1.getTypeName(vertex) : null;
}
return ret;
}
public static boolean typeHasInstanceVertex(String typeName) throws AtlasBaseException {
AtlasGraphQuery query = AtlasGraphProvider.getGraphInstance()
.query()
......
......@@ -34,6 +34,7 @@ import org.apache.atlas.repository.Constants;
import org.apache.atlas.repository.graph.GraphHelper;
import org.apache.atlas.repository.graphdb.AtlasEdge;
import org.apache.atlas.repository.graphdb.AtlasEdgeDirection;
import org.apache.atlas.repository.graphdb.AtlasElement;
import org.apache.atlas.repository.graphdb.AtlasVertex;
import org.apache.atlas.type.*;
import org.apache.atlas.type.AtlasStructType.AtlasAttribute;
......@@ -460,7 +461,7 @@ public final class EntityGraphRetriever {
return ret;
}
private Object mapVertexToPrimitive(AtlasVertex entityVertex, final String vertexPropertyName, AtlasAttributeDef attrDef) {
public Object mapVertexToPrimitive(AtlasElement entityVertex, final String vertexPropertyName, AtlasAttributeDef attrDef) {
Object ret = null;
if (GraphHelper.getSingleValuedProperty(entityVertex, vertexPropertyName, Object.class) == null) {
......
......@@ -273,6 +273,10 @@ public class GraphBackedTypeStore implements ITypeStore {
traits.add(new HierarchicalTypeDefinition(TraitType.class, typeName, typeDescription, superTypes, attributes));
break;
case RELATIONSHIP:
// v1 typesystem is not notified on new relation type
break;
default:
throw new IllegalArgumentException("Unhandled type category " + typeCategory);
}
......
......@@ -47,9 +47,11 @@ import org.apache.atlas.repository.graphdb.AtlasGraph;
import org.apache.atlas.repository.impexp.ExportService;
import org.apache.atlas.repository.store.graph.AtlasEntityDefStore;
import org.apache.atlas.repository.store.graph.AtlasEntityStore;
import org.apache.atlas.repository.store.graph.AtlasRelationshipStore;
import org.apache.atlas.repository.store.graph.v1.AtlasEntityChangeNotifier;
import org.apache.atlas.repository.store.graph.v1.AtlasEntityDefStoreV1;
import org.apache.atlas.repository.store.graph.v1.AtlasEntityStoreV1;
import org.apache.atlas.repository.store.graph.v1.AtlasRelationshipStoreV1;
import org.apache.atlas.repository.store.graph.v1.AtlasTypeDefGraphStoreV1;
import org.apache.atlas.repository.store.graph.v1.DeleteHandlerV1;
import org.apache.atlas.repository.store.graph.v1.EntityGraphMapper;
......@@ -152,6 +154,7 @@ public class TestModules {
typeDefChangeListenerMultibinder.addBinding().to(GraphBackedSearchIndexer.class).asEagerSingleton();
bind(AtlasEntityStore.class).to(AtlasEntityStoreV1.class);
bind(AtlasRelationshipStore.class).to(AtlasRelationshipStoreV1.class);
// bind the MetadataService interface to an implementation
bind(MetadataService.class).to(DefaultMetadataService.class).asEagerSingleton();
......
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.atlas.web.rest;
import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.instance.AtlasRelationship;
import org.apache.atlas.repository.store.graph.AtlasRelationshipStore;
import org.apache.atlas.utils.AtlasPerfTracer;
import org.apache.atlas.web.util.Servlets;
import org.slf4j.Logger;
import org.springframework.stereotype.Service;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
/**
* REST interface for entity relationships.
*/
@Path("v2/relation")
@Singleton
@Service
public class RelationshipREST {
private static final Logger PERF_LOG = AtlasPerfTracer.getPerfLogger("rest.RelationshipREST");
private final AtlasRelationshipStore relationshipStore;
@Inject
public RelationshipREST(AtlasRelationshipStore relationshipStore) {
this.relationshipStore = relationshipStore;
}
/**
* Create a new relationship between entities.
*/
@POST
@Consumes(Servlets.JSON_MEDIA_TYPE)
@Produces(Servlets.JSON_MEDIA_TYPE)
public AtlasRelationship create(AtlasRelationship relationship) throws AtlasBaseException {
AtlasPerfTracer perf = null;
try {
if (AtlasPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "RelationshipREST.create(" + relationship + ")");
}
return relationshipStore.create(relationship);
} finally {
AtlasPerfTracer.log(perf);
}
}
/**
* Update an existing relationship between entities.
*/
@PUT
@Consumes(Servlets.JSON_MEDIA_TYPE)
@Produces(Servlets.JSON_MEDIA_TYPE)
public AtlasRelationship update(AtlasRelationship relationship) throws AtlasBaseException {
AtlasPerfTracer perf = null;
try {
if (AtlasPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "RelationshipREST.update(" + relationship + ")");
}
return relationshipStore.update(relationship);
} finally {
AtlasPerfTracer.log(perf);
}
}
/**
* Get relationship information between entities using guid.
*/
@GET
@Path("/guid/{guid}")
@Consumes(Servlets.JSON_MEDIA_TYPE)
@Produces(Servlets.JSON_MEDIA_TYPE)
public AtlasRelationship getById(@PathParam("guid") String guid) throws AtlasBaseException {
AtlasPerfTracer perf = null;
try {
if (AtlasPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "RelationshipREST.getById(" + guid + ")");
}
return relationshipStore.getById(guid);
} finally {
AtlasPerfTracer.log(perf);
}
}
/**
* Delete a relationship between entities using guid.
*/
@DELETE
@Path("/guid/{guid}")
@Consumes(Servlets.JSON_MEDIA_TYPE)
@Produces(Servlets.JSON_MEDIA_TYPE)
public void deleteById(@PathParam("guid") String guid) throws AtlasBaseException {
AtlasPerfTracer perf = null;
try {
if (AtlasPerfTracer.isPerfTraceEnabled(PERF_LOG)) {
perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "RelationshipREST.deleteById(" + guid + ")");
}
relationshipStore.deleteById(guid);
} finally {
AtlasPerfTracer.log(perf);
}
}
}
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