private void dumpGraph() { AtlasGraph<?, ?> graph = TestUtils.getGraph(); for (AtlasVertex<?, ?> v : graph.getVertices()) { System.out.println("****v = " + GraphHelper.vertexString(v)); for (AtlasEdge<?, ?> e : v.getEdges(AtlasEdgeDirection.OUT)) { System.out.println("****e = " + GraphHelper.edgeString(e)); } } }
public static void updateVertexPreUpdate( AtlasStructDef structDef, AtlasStructType structType, AtlasVertex vertex, AtlasTypeDefGraphStoreV1 typeDefStore) throws AtlasBaseException { List<String> attrNames = new ArrayList<>(); if (CollectionUtils.isNotEmpty(structDef.getAttributeDefs())) { for (AtlasAttributeDef attributeDef : structDef.getAttributeDefs()) { attrNames.add(attributeDef.getName()); } } List<String> currAttrNames = vertex.getProperty(AtlasGraphUtilsV1.getPropertyKey(structDef), List.class); // delete attributes that are not present in updated structDef if (CollectionUtils.isNotEmpty(currAttrNames)) { for (String currAttrName : currAttrNames) { if (!attrNames.contains(currAttrName)) { throw new AtlasBaseException( AtlasErrorCode.ATTRIBUTE_DELETION_NOT_SUPPORTED, structDef.getName(), currAttrName); } } } typeDefStore.updateTypeVertex(structDef, vertex); // add/update attributes that are present in updated structDef if (CollectionUtils.isNotEmpty(structDef.getAttributeDefs())) { for (AtlasAttributeDef attributeDef : structDef.getAttributeDefs()) { if (CollectionUtils.isEmpty(currAttrNames) || !currAttrNames.contains(attributeDef.getName())) { // new attribute - only allow if optional if (!attributeDef.isOptional()) { throw new AtlasBaseException( AtlasErrorCode.CANNOT_ADD_MANDATORY_ATTRIBUTE, structDef.getName(), attributeDef.getName()); } } String propertyKey = AtlasGraphUtilsV1.getPropertyKey(structDef, attributeDef.getName()); AtlasGraphUtilsV1.setProperty( vertex, propertyKey, toJsonFromAttributeDef(attributeDef, structType)); } } AtlasGraphUtilsV1.setProperty(vertex, AtlasGraphUtilsV1.getPropertyKey(structDef), attrNames); }
@Override public AtlasStructDef getByName(String name) throws AtlasBaseException { if (LOG.isDebugEnabled()) { LOG.debug("==> AtlasStructDefStoreV1.getByName({})", name); } AtlasVertex vertex = typeDefStore.findTypeVertexByNameAndCategory(name, TypeCategory.STRUCT); if (vertex == null) { throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_NOT_FOUND, name); } vertex.getProperty(Constants.TYPE_CATEGORY_PROPERTY_KEY, String.class); AtlasStructDef ret = toStructDef(vertex); if (LOG.isDebugEnabled()) { LOG.debug("<== AtlasStructDefStoreV1.getByName({}): {}", name, ret); } return ret; }
public static AtlasStructDef toStructDef( AtlasVertex vertex, AtlasStructDef structDef, AtlasTypeDefGraphStoreV1 typeDefStore) throws AtlasBaseException { AtlasStructDef ret = (structDef != null) ? structDef : new AtlasStructDef(); typeDefStore.vertexToTypeDef(vertex, ret); List<AtlasAttributeDef> attributeDefs = new ArrayList<>(); List<String> attrNames = vertex.getProperty(AtlasGraphUtilsV1.getPropertyKey(ret), List.class); if (CollectionUtils.isNotEmpty(attrNames)) { for (String attrName : attrNames) { String propertyKey = AtlasGraphUtilsV1.getPropertyKey(ret, attrName); String attribJson = vertex.getProperty(propertyKey, String.class); attributeDefs.add( toAttributeDefFromJson( structDef, AtlasType.fromJson(attribJson, Map.class), typeDefStore)); } } ret.setAttributeDefs(attributeDefs); return ret; }
protected void deleteVertex(AtlasVertex instanceVertex, boolean force) throws AtlasException { // Update external references(incoming edges) to this vertex LOG.debug( "Setting the external references to {} to null(removing edges)", string(instanceVertex)); Iterator<AtlasEdge> edges = instanceVertex.getEdges(AtlasEdgeDirection.IN).iterator(); while (edges.hasNext()) { AtlasEdge edge = edges.next(); Id.EntityState edgeState = GraphHelper.getState(edge); if (edgeState == Id.EntityState.ACTIVE) { // Delete only the active edge references AttributeInfo attribute = getAttributeForEdge(edge.getLabel()); // TODO use delete edge instead?? deleteEdgeBetweenVertices(edge.getOutVertex(), edge.getInVertex(), attribute.name); } } _deleteVertex(instanceVertex, force); }
private static void addReferencesForAttribute( AtlasVertex vertex, AtlasAttributeDef attributeDef, AtlasTypeDefGraphStoreV1 typeDefStore) throws AtlasBaseException { Set<String> referencedTypeNames = AtlasTypeUtil.getReferencedTypeNames(attributeDef.getTypeName()); String typeName = vertex.getProperty(Constants.TYPENAME_PROPERTY_KEY, String.class); for (String referencedTypeName : referencedTypeNames) { if (!AtlasTypeUtil.isBuiltInType(referencedTypeName)) { AtlasVertex referencedTypeVertex = typeDefStore.findTypeVertexByName(referencedTypeName); if (referencedTypeVertex == null) { throw new AtlasBaseException( AtlasErrorCode.UNKNOWN_TYPE, referencedTypeName, typeName, attributeDef.getName()); } String label = AtlasGraphUtilsV1.getEdgeLabel(typeName, attributeDef.getName()); typeDefStore.getOrCreateEdge(vertex, referencedTypeVertex, label); } } }
/** * Deletes the edge between outvertex and inVertex. The edge is for attribute attributeName of * outVertex * * @param outVertex * @param inVertex * @param attributeName * @throws AtlasException */ protected void deleteEdgeBetweenVertices( AtlasVertex outVertex, AtlasVertex inVertex, String attributeName) throws AtlasException { LOG.debug( "Removing edge from {} to {} with attribute name {}", string(outVertex), string(inVertex), attributeName); String typeName = GraphHelper.getTypeName(outVertex); String outId = GraphHelper.getIdFromVertex(outVertex); Id.EntityState state = GraphHelper.getState(outVertex); if ((outId != null && RequestContext.get().isDeletedEntity(outId)) || state == Id.EntityState.DELETED) { // If the reference vertex is marked for deletion, skip updating the reference return; } IDataType type = typeSystem.getDataType(IDataType.class, typeName); AttributeInfo attributeInfo = getFieldMapping(type).fields.get(attributeName); String propertyName = GraphHelper.getQualifiedFieldName(type, attributeName); String edgeLabel = EDGE_LABEL_PREFIX + propertyName; AtlasEdge edge = null; switch (attributeInfo.dataType().getTypeCategory()) { case CLASS: // If its class attribute, its the only edge between two vertices if (attributeInfo.multiplicity.nullAllowed()) { edge = graphHelper.getEdgeForLabel(outVertex, edgeLabel); if (shouldUpdateReverseAttribute) { GraphHelper.setProperty(outVertex, propertyName, null); } } else { // Cannot unset a required attribute. throw new NullRequiredAttributeException( "Cannot unset required attribute " + GraphHelper.getQualifiedFieldName(type, attributeName) + " on " + GraphHelper.getVertexDetails(outVertex) + " edge = " + edgeLabel); } break; case ARRAY: // If its array attribute, find the right edge between the two vertices and update array // property List<String> elements = GraphHelper.getListProperty(outVertex, propertyName); if (elements != null) { elements = new ArrayList<>( elements); // Make a copy, else list.remove reflects on titan.getProperty() for (String elementEdgeId : elements) { AtlasEdge elementEdge = graphHelper.getEdgeByEdgeId(outVertex, edgeLabel, elementEdgeId); if (elementEdge == null) { continue; } AtlasVertex elementVertex = elementEdge.getInVertex(); if (elementVertex.equals(inVertex)) { edge = elementEdge; // TODO element.size includes deleted items as well. should exclude if (!attributeInfo.multiplicity.nullAllowed() && elements.size() <= attributeInfo.multiplicity.lower) { // Deleting this edge would violate the attribute's lower bound. throw new NullRequiredAttributeException( "Cannot remove array element from required attribute " + GraphHelper.getQualifiedFieldName(type, attributeName) + " on " + GraphHelper.getVertexDetails(outVertex) + " " + GraphHelper.getEdgeDetails(elementEdge)); } if (shouldUpdateReverseAttribute) { // if composite attribute, remove the reference as well. else, just remove the edge // for example, when table is deleted, process still references the table // but when column is deleted, table will not reference the deleted column LOG.debug( "Removing edge {} from the array attribute {}", string(elementEdge), attributeName); elements.remove(elementEdge.getId().toString()); GraphHelper.setProperty(outVertex, propertyName, elements); break; } } } } break; case MAP: // If its map attribute, find the right edge between two vertices and update map property List<String> keys = GraphHelper.getListProperty(outVertex, propertyName); if (keys != null) { keys = new ArrayList<>( keys); // Make a copy, else list.remove reflects on titan.getProperty() for (String key : keys) { String keyPropertyName = GraphHelper.getQualifiedNameForMapKey(propertyName, key); String mapEdgeId = GraphHelper.getSingleValuedProperty(outVertex, keyPropertyName, String.class); AtlasEdge mapEdge = graphHelper.getEdgeByEdgeId(outVertex, keyPropertyName, mapEdgeId); if (mapEdge != null) { AtlasVertex mapVertex = mapEdge.getInVertex(); if (mapVertex.getId().toString().equals(inVertex.getId().toString())) { // TODO keys.size includes deleted items as well. should exclude if (attributeInfo.multiplicity.nullAllowed() || keys.size() > attributeInfo.multiplicity.lower) { edge = mapEdge; } else { // Deleting this entry would violate the attribute's lower bound. throw new NullRequiredAttributeException( "Cannot remove map entry " + keyPropertyName + " from required attribute " + GraphHelper.getQualifiedFieldName(type, attributeName) + " on " + GraphHelper.getVertexDetails(outVertex) + " " + GraphHelper.getEdgeDetails(mapEdge)); } if (shouldUpdateReverseAttribute) { // remove this key LOG.debug( "Removing edge {}, key {} from the map attribute {}", string(mapEdge), key, attributeName); keys.remove(key); GraphHelper.setProperty(outVertex, propertyName, keys); GraphHelper.setProperty(outVertex, keyPropertyName, null); } break; } } } } break; case STRUCT: case TRAIT: break; default: throw new IllegalStateException( "There can't be an edge from " + GraphHelper.getVertexDetails(outVertex) + " to " + GraphHelper.getVertexDetails(inVertex) + " with attribute name " + attributeName + " which is not class/array/map attribute"); } if (edge != null) { deleteEdge(edge, false); RequestContext requestContext = RequestContext.get(); GraphHelper.setProperty( outVertex, Constants.MODIFICATION_TIMESTAMP_PROPERTY_KEY, requestContext.getRequestTime()); requestContext.recordEntityUpdate(outId); } }
private static AtlasAttributeDef toAttributeDefFromJson( AtlasStructDef structDef, Map attribInfo, AtlasTypeDefGraphStoreV1 typeDefStore) throws AtlasBaseException { AtlasAttributeDef ret = new AtlasAttributeDef(); ret.setName((String) attribInfo.get("name")); ret.setTypeName((String) attribInfo.get("dataType")); ret.setUnique((Boolean) attribInfo.get("isUnique")); ret.setIndexable((Boolean) attribInfo.get("isIndexable")); String attrTypeName = ret.getTypeName(); if (AtlasTypeUtil.isArrayType(attrTypeName)) { Set<String> typeNames = AtlasTypeUtil.getReferencedTypeNames(ret.getTypeName()); if (typeNames.size() > 0) { attrTypeName = typeNames.iterator().next(); } } if (!AtlasTypeUtil.isBuiltInType(attrTypeName)) { AtlasVertex attributeType = typeDefStore.findTypeVertexByName(attrTypeName); // check for isComposite/reverseAttributeName for entity types if (attributeType != null && typeDefStore.isTypeVertex(attributeType, TypeCategory.CLASS)) { String reverseAttribName = (String) attribInfo.get("reverseAttributeName"); Boolean isComposite = (Boolean) attribInfo.get("isComposite"); if (StringUtils.isNotBlank(reverseAttribName) || isComposite) { if (AtlasTypeUtil.isMapType(attrTypeName)) { throw new AtlasBaseException( AtlasErrorCode.CONSTRAINT_NOT_SUPPORTED_ON_MAP_TYPE, structDef.getName(), ret.getName(), attrTypeName); } String refAttributeName = null; List<String> attrNames = attributeType.getProperty(AtlasGraphUtilsV1.getPropertyKey(attrTypeName), List.class); if (CollectionUtils.isNotEmpty(attrNames)) { for (String attrName : attrNames) { String attribJson = attributeType.getProperty( AtlasGraphUtilsV1.getPropertyKey(attrTypeName, attrName), String.class); Map refAttrInfo = AtlasType.fromJson(attribJson, Map.class); String refAttribType = (String) refAttrInfo.get("dataType"); String refAttribRevAttribName = (String) refAttrInfo.get("reverseAttributeName"); if (StringUtils.equals(refAttribType, structDef.getName()) && StringUtils.equals(refAttribRevAttribName, ret.getName())) { refAttributeName = (String) refAttrInfo.get("name"); break; } } } if (isComposite) { if (StringUtils.isNotBlank( refAttributeName)) { // ex: hive_table.columns, hive_column.table Map<String, Object> params = new HashMap<>(); params.put(AtlasConstraintDef.CONSTRAINT_PARAM_REF_ATTRIBUTE, refAttributeName); ret.addConstraint(new AtlasConstraintDef(CONSTRAINT_TYPE_MAPPED_FROM_REF, params)); } else { // ex: hive_table.partitionKeys, with no reverseAttribute-reference ret.addConstraint(new AtlasConstraintDef(CONSTRAINT_TYPE_FOREIGN_KEY)); } } if (StringUtils.isNotBlank(reverseAttribName)) { // 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)); } } } } Map multiplicity = AtlasType.fromJson((String) attribInfo.get("multiplicity"), Map.class); Number minCount = (Number) multiplicity.get("lower"); Number maxCount = (Number) multiplicity.get("upper"); Boolean isUnique = (Boolean) multiplicity.get("isUnique"); if (minCount == null || minCount.intValue() == 0) { ret.setOptional(true); ret.setValuesMinCount(0); } else { ret.setOptional(false); ret.setValuesMinCount(minCount.intValue()); } if (maxCount == null || maxCount.intValue() < 2) { ret.setCardinality(AtlasAttributeDef.Cardinality.SINGLE); ret.setValuesMaxCount(1); } else { if (isUnique == null || isUnique == Boolean.FALSE) { ret.setCardinality(AtlasAttributeDef.Cardinality.LIST); } else { ret.setCardinality(AtlasAttributeDef.Cardinality.SET); } ret.setValuesMaxCount(maxCount.intValue()); } return ret; }