private void putAssociationOperation( Association association, AssociationKey associationKey, AssociationOperation action, AssociatedEntityKeyMetadata associatedEntityKeyMetadata) { Relationship relationship = associationQueries .get(associationKey.getMetadata()) .findRelationship(dataBase, associationKey, action.getKey()); if (relationship != null) { for (String relationshipProperty : associationKey.getMetadata().getRowKeyIndexColumnNames()) { relationship.setProperty(relationshipProperty, action.getValue().get(relationshipProperty)); } for (String column : associationKey .getMetadata() .getColumnsWithoutKeyColumns(action.getValue().getColumnNames())) { if (!isRowKeyColumn(associationKey.getMetadata(), column)) { relationship.getEndNode().setProperty(column, action.getValue().get(column)); } } GraphLogger.log("Updated relationship: %1$s", relationship); } else { relationship = createRelationship(associationKey, action.getValue(), associatedEntityKeyMetadata); GraphLogger.log("Created relationship: %1$s", relationship); } }
@Override public void removeAssociation(AssociationKey key, AssociationContext associationContext) { // If this is the inverse side of a bi-directional association, we don't manage the relationship // from this side if (key.getMetadata().isInverse()) { return; } associationQueries.get(key.getMetadata()).removeAssociation(dataBase, key); }
private Relationship createRelationshipWithTargetNode( AssociationKey associationKey, Tuple associationRow, Node targetNode) { EntityKey entityKey = associationKey.getEntityKey(); Node ownerNode = entityQueries .get(entityKey.getMetadata()) .findEntity(dataBase, entityKey.getColumnValues()); Relationship relationship = ownerNode.createRelationshipTo( targetNode, withName(associationKey.getMetadata().getCollectionRole())); applyProperties(associationKey, associationRow, relationship); return relationship; }
/** * Returns the entity key on the other side of association row represented by the given row key. * * <p><b>Note:</b> May only be invoked if the row key actually contains all the columns making up * that entity key. Specifically, it may <b>not</b> be invoked if the association has index * columns (maps, ordered collections), as the entity key columns will not be part of the row key * in this case. */ private EntityKey getEntityKey(AssociationKey associationKey, RowKey rowKey) { String[] associationKeyColumns = associationKey.getMetadata().getAssociatedEntityKeyMetadata().getAssociationKeyColumns(); Object[] columnValues = new Object[associationKeyColumns.length]; int i = 0; for (String associationKeyColumn : associationKeyColumns) { columnValues[i] = rowKey.getColumnValue(associationKeyColumn); i++; } EntityKeyMetadata entityKeyMetadata = associationKey.getMetadata().getAssociatedEntityKeyMetadata().getEntityKeyMetadata(); return new EntityKey(entityKeyMetadata, columnValues); }
@Override public void insertOrUpdateAssociation( AssociationKey key, Association association, AssociationContext associationContext) { Map<SerializableRowKey, Map<String, Object>> associationRows = ((SerializableMapAssociationSnapshot) association.getSnapshot()).getUnderlyingMap(); for (AssociationOperation action : association.getOperations()) { switch (action.getType()) { case CLEAR: associationRows.clear(); case PUT: associationRows.put( new SerializableRowKey(action.getKey()), MapHelpers.associationRowToMap(action.getValue())); break; case REMOVE: associationRows.remove(new SerializableRowKey(action.getKey())); break; } } final Cache<AK> associationCache = getCacheManager().getAssociationCache(key.getMetadata()); associationCache.put( new Element(getKeyProvider().getAssociationCacheKey(key), associationRows)); }
@Override public void removeAssociation(AssociationKey key, AssociationContext associationContext) { Cache<AK, Map<RowKey, Map<String, Object>>> cache = getCacheManager().getAssociationCache(key.getMetadata()); AK cacheKey = getKeyProvider().getAssociationCacheKey(key); AtomicMapLookup.removeAtomicMap(cache, cacheKey); }
/** * When dealing with some scenarios like, for example, a bidirectional association, OGM calls this * method twice: * * <p>the first time with the information related to the owner of the association and the {@link * RowKey}, the second time using the same {@link RowKey} but with the {@link AssociationKey} * referring to the other side of the association. * * @param associatedEntityKeyMetadata */ private Relationship createRelationship( AssociationKey associationKey, Tuple associationRow, AssociatedEntityKeyMetadata associatedEntityKeyMetadata) { switch (associationKey.getMetadata().getAssociationKind()) { case EMBEDDED_COLLECTION: return createRelationshipWithEmbeddedNode( associationKey, associationRow, associatedEntityKeyMetadata); case ASSOCIATION: return findOrCreateRelationshipWithEntityNode( associationKey, associationRow, associatedEntityKeyMetadata); default: throw new AssertionFailure( "Unrecognized associationKind: " + associationKey.getMetadata().getAssociationKind()); } }
@Override public Association createAssociation(AssociationKey key, AssociationContext associationContext) { final Cache<AK> associationCache = getCacheManager().getAssociationCache(key.getMetadata()); Map<SerializableRowKey, Map<String, Object>> association = new HashMap<SerializableRowKey, Map<String, Object>>(); associationCache.put(new Element(getKeyProvider().getAssociationCacheKey(key), association)); return new Association(new SerializableMapAssociationSnapshot(association)); }
/** * The only properties added to a relationship are the columns representing the index of the * association. */ private void applyProperties( AssociationKey associationKey, Tuple associationRow, Relationship relationship) { String[] indexColumns = associationKey.getMetadata().getRowKeyIndexColumnNames(); for (int i = 0; i < indexColumns.length; i++) { String propertyName = indexColumns[i]; Object propertyValue = associationRow.get(propertyName); relationship.setProperty(propertyName, propertyValue); } }
private void removeAssociationOperation( Association association, AssociationKey associationKey, AssociationOperation action, AssociatedEntityKeyMetadata associatedEntityKeyMetadata) { associationQueries .get(associationKey.getMetadata()) .removeAssociationRow(dataBase, associationKey, action.getKey()); }
@Override public Association getAssociation(AssociationKey key, AssociationContext associationContext) { Cache<AK, Map<RowKey, Map<String, Object>>> cache = getCacheManager().getAssociationCache(key.getMetadata()); AK cacheKey = getKeyProvider().getAssociationCacheKey(key); Map<RowKey, Map<String, Object>> atomicMap = AtomicMapLookup.getFineGrainedAtomicMap(cache, cacheKey, false); return atomicMap == null ? null : new Association(new MapAssociationSnapshot(atomicMap)); }
private RowKey convert(AssociationKey associationKey, Neo4jTupleAssociationSnapshot snapshot) { String[] columnNames = associationKey.getMetadata().getRowKeyColumnNames(); Object[] values = new Object[columnNames.length]; for (int i = 0; i < columnNames.length; i++) { values[i] = snapshot.get(columnNames[i]); } return new RowKey(columnNames, values); }
/** * Remove an association row * * @param executionEngine the {@link ExecutionEngine} used to run the query * @param associationKey represents the association * @param rowKey represents a row in an association */ public void removeAssociationRow( ExecutionEngine executionEngine, AssociationKey associationKey, RowKey rowKey) { Object[] relationshipValues; if (associationKey.getMetadata().getRowKeyIndexColumnNames().length > 0) { int length = associationKey.getMetadata().getRowKeyIndexColumnNames().length; relationshipValues = new Object[length]; String[] indexColumnNames = associationKey.getMetadata().getRowKeyIndexColumnNames(); for (int i = 0; i < indexColumnNames.length; i++) { for (int j = 0; j < rowKey.getColumnNames().length; j++) { if (indexColumnNames[i].equals(rowKey.getColumnNames()[j])) { relationshipValues[i] = rowKey.getColumnValues()[j]; } } } } else { relationshipValues = getEntityKey(associationKey, rowKey).getColumnValues(); } Object[] queryValues = ArrayHelper.concat(associationKey.getEntityKey().getColumnValues(), relationshipValues); executionEngine.execute(removeAssociationRowQuery, params(queryValues)); }
@Override public Association createAssociation(AssociationKey key, AssociationContext associationContext) { // TODO we don't verify that it does not yet exist assuming that this ahs been done before by // the calling code // should we improve? Cache<AK, Map<RowKey, Map<String, Object>>> cache = getCacheManager().getAssociationCache(key.getMetadata()); AK cacheKey = getKeyProvider().getAssociationCacheKey(key); Map<RowKey, Map<String, Object>> atomicMap = AtomicMapLookup.getFineGrainedAtomicMap(cache, cacheKey, true); return new Association(new MapAssociationSnapshot(atomicMap)); }
private Relationship createRelationshipWithEmbeddedNode( AssociationKey associationKey, Tuple associationRow, AssociatedEntityKeyMetadata associatedEntityKeyMetadata) { EntityKey embeddedKey = getEntityKey(associationRow, associatedEntityKeyMetadata); Relationship relationship = associationQueries .get(associationKey.getMetadata()) .createRelationshipForEmbeddedAssociation(dataBase, associationKey, embeddedKey); applyProperties(associationKey, associationRow, relationship); return relationship; }
@Override public Association getAssociation(AssociationKey key, AssociationContext associationContext) { final Cache<AK> associationCache = getCacheManager().getAssociationCache(key.getMetadata()); final Element element = associationCache.get(getKeyProvider().getAssociationCacheKey(key)); if (element == null) { return null; } else { @SuppressWarnings("unchecked") Map<SerializableRowKey, Map<String, Object>> associationRows = (Map<SerializableRowKey, Map<String, Object>>) element.getObjectValue(); return new Association(new SerializableMapAssociationSnapshot(associationRows)); } }
@Override public void insertOrUpdateAssociation( AssociationKey key, Association association, AssociationContext associationContext) { // If this is the inverse side of a bi-directional association, we don't create a relationship // for this; this // will happen when updating the main side if (key.getMetadata().isInverse()) { return; } for (AssociationOperation action : association.getOperations()) { applyAssociationOperation(association, key, action, associationContext); } }
@Override public Association getAssociation( AssociationKey associationKey, AssociationContext associationContext) { EntityKey entityKey = associationKey.getEntityKey(); Node entityNode = entityQueries .get(entityKey.getMetadata()) .findEntity(dataBase, entityKey.getColumnValues()); GraphLogger.log("Found owner node: %1$s", entityNode); if (entityNode == null) { return null; } Map<RowKey, Tuple> tuples = createAssociationMap(associationKey, associationContext, entityKey); return new Association(new EmbeddedNeo4jAssociationSnapshot(tuples)); }
/** * Removes the relationship(s) representing the given association. If the association refers to an * embedded entity (collection), the referenced entities are removed as well. * * @param executionEngine the {@link ExecutionEngine} used to run the query * @param associationKey represents the association */ public void removeAssociation(ExecutionEngine executionEngine, AssociationKey associationKey) { executionEngine.execute( removeAssociationQuery, params(associationKey.getEntityKey().getColumnValues())); }
@Override public void removeAssociation(AssociationKey key, AssociationContext associationContext) { getCacheManager() .getAssociationCache(key.getMetadata()) .remove(getKeyProvider().getAssociationCacheKey(key)); }