private Object unmarshall(PersistentEntity persistentEntity, Long id, Map<String, Object> data) { log.debug("unmarshalling entity {}, props {}, {}", id, data); EntityAccess entityAccess = new EntityAccess(persistentEntity, persistentEntity.newInstance()); entityAccess.setConversionService(persistentEntity.getMappingContext().getConversionService()); entityAccess.setIdentifier(id); data.remove("__id__"); for (PersistentProperty property : entityAccess.getPersistentEntity().getPersistentProperties()) { String propertyName = property.getName(); if (property instanceof Simple) { // implicitly sets version property as well entityAccess.setProperty(propertyName, data.remove(propertyName)); // } else if (property instanceof OneToOne) { // log.error("property " + property.getName() + " is of type " + // property.getClass().getSuperclass()); } else if (property instanceof ToOne) { ToOne to = (ToOne) property; CypherResult cypherResult = getSession() .getNativeInterface() .execute( CypherBuilder.findRelationshipEndpointIdsFor(to), Collections.singletonMap("id", id)); Map<String, Object> row = IteratorUtil.singleOrNull(cypherResult); if (row != null) { Long endpointId = (Long) row.get("id"); entityAccess.setProperty( propertyName, getMappingContext() .getProxyFactory() .createProxy(session, to.getAssociatedEntity().getJavaClass(), endpointId)); } } else if ((property instanceof OneToMany) || (property instanceof ManyToMany)) { LazyEnititySet lazyEnititySet = new LazyEnititySet( entityAccess, (Association) property, getMappingContext().getProxyFactory(), getSession()); entityAccess.setProperty(propertyName, lazyEnititySet); } else { throw new IllegalArgumentException( "property $property.name is of type ${property.class.superclass}"); } } if (!data.isEmpty()) { GroovyObject go = (GroovyObject) (entityAccess.getEntity()); go.setProperty(Neo4jGormEnhancer.UNDECLARED_PROPERTIES, data); } firePostLoadEvent(entityAccess.getPersistentEntity(), entityAccess); return entityAccess.getEntity(); }
@Override protected void deleteEntity(PersistentEntity pe, Object obj) { EntityAccess entityAccess = createEntityAccess(pe, obj); if (cancelDelete(pe, entityAccess)) { return; } for (Association association : pe.getAssociations()) { if (association.isOwningSide() && association.doesCascade(CascadeType.REMOVE)) { log.debug("cascading delete for property " + association.getName()); GraphPersistentEntity otherPersistentEntity = (GraphPersistentEntity) association.getAssociatedEntity(); Object otherSideValue = entityAccess.getProperty(association.getName()); if (association instanceof ToOne) { deleteEntity(otherPersistentEntity, otherSideValue); } else { deleteEntities(otherPersistentEntity, (Iterable) otherSideValue); } } } getCypherEngine() .execute( String.format( "MATCH (n:%s) WHERE n.__id__={id} OPTIONAL MATCH (n)-[r]-() DELETE r,n", ((GraphPersistentEntity) pe).getLabel()), Collections.singletonMap("id", entityAccess.getIdentifier())); firePostDeleteEvent(pe, entityAccess); }
@Override protected void setManyToMany( PersistentEntity persistentEntity, Object obj, DBObject nativeEntry, ManyToMany manyToMany, Collection associatedObjects, Map<Association, List<Serializable>> toManyKeys) { List ids = new ArrayList(); if (associatedObjects != null) { for (Object o : associatedObjects) { if (o == null) { ids.add(null); } else { PersistentEntity childPersistentEntity = getMappingContext().getPersistentEntity(o.getClass().getName()); EntityAccess entityAccess = createEntityAccess(childPersistentEntity, o); ids.add(entityAccess.getIdentifier()); } } } nativeEntry.put(manyToMany.getName() + "_$$manyToManyIds", ids); }
protected Object getCurrentVersion(final EntityAccess ea) { Object currentVersion = ea.getProperty("version"); if (Number.class.isAssignableFrom(ea.getPropertyType("version"))) { currentVersion = currentVersion != null ? ((Number) currentVersion).longValue() : currentVersion; } return currentVersion; }
RelationshipPendingInsert( EntityAccess source, String relType, EntityAccess target, CypherEngine cypherEngine) { super(source.getPersistentEntity(), -1l, source.getEntity(), source); this.relType = relType; this.target = target; this.cypherEngine = cypherEngine; // validateNonExistingRelationship("constructor"); }
@Override protected void deleteEntities( PersistentEntity pe, @SuppressWarnings("rawtypes") Iterable objects) { List<EntityAccess> entityAccesses = new ArrayList<EntityAccess>(); List<Object> ids = new ArrayList<Object>(); Map<PersistentEntity, Collection<Object>> cascades = new HashMap<PersistentEntity, Collection<Object>>(); for (Object obj : objects) { EntityAccess entityAccess = createEntityAccess(pe, obj); if (cancelDelete(pe, entityAccess)) { return; } entityAccesses.add(entityAccess); ids.add(entityAccess.getIdentifier()); // populate cascades for (Association association : pe.getAssociations()) { Object property = entityAccess.getProperty(association.getName()); if (association.isOwningSide() && association.doesCascade(CascadeType.REMOVE) && (property != null)) { PersistentEntity associatedEntity = association.getAssociatedEntity(); Collection<Object> cascadesForPersistentEntity = cascades.get(associatedEntity); if (cascadesForPersistentEntity == null) { cascadesForPersistentEntity = new ArrayList<Object>(); cascades.put(associatedEntity, cascadesForPersistentEntity); } if (association instanceof ToOne) { cascadesForPersistentEntity.add(property); } else { cascadesForPersistentEntity.addAll((Collection<?>) property); } } } } for (Map.Entry<PersistentEntity, Collection<Object>> entry : cascades.entrySet()) { deleteEntities(entry.getKey(), entry.getValue()); } getCypherEngine() .execute( String.format( "MATCH (n:%s) WHERE n.__id__ in {ids} OPTIONAL MATCH (n)-[r]-() DELETE r,n", ((GraphPersistentEntity) pe).getLabel()), Collections.singletonMap("ids", ids)); for (EntityAccess entityAccess : entityAccesses) { firePostDeleteEvent(pe, entityAccess); } }
public RelationshipPendingInsert( EntityAccess parent, Association association, Collection<Serializable> pendingInserts, GraphDatabaseService graphDatabaseService, boolean isUpdate) { super(parent.getPersistentEntity(), -1L, parent.getEntity(), parent); this.graphDatabaseService = graphDatabaseService; this.targetIdentifiers = pendingInserts; this.association = association; this.isUpdate = isUpdate; }
@Override protected void loadEmbeddedCollection( EmbeddedCollection embeddedCollection, EntityAccess ea, Object embeddedInstances, String propertyKey) { Collection<Object> instances; if (List.class.isAssignableFrom(embeddedCollection.getType())) { instances = new ArrayList<Object>(); } else { instances = new HashSet<Object>(); } if (embeddedInstances instanceof List) { List list = (List) embeddedInstances; for (Object dbo : list) { if (dbo instanceof BasicDBObject) { BasicDBObject nativeEntry = (BasicDBObject) dbo; Object instance = createObjectFromEmbeddedNativeEntry( embeddedCollection.getAssociatedEntity(), nativeEntry); instances.add(instance); } } } ea.setProperty(embeddedCollection.getName(), instances); }
@Override public void run() { // validateNonExistingRelationship("execution"); List params = new ArrayList(); params.add(getEntityAccess().getIdentifier()); params.add(target.getIdentifier()); String labelsFrom = ((GraphPersistentEntity) getEntity()).getLabelsAsString(); String labelsTo = ((GraphPersistentEntity) target.getPersistentEntity()).getLabelsAsString(); String cypher = String.format( "MATCH (from%s {__id__:{1}}), (to%s {__id__:{2}}) MERGE (from)-[:%s]->(to)", labelsFrom, labelsTo, relType); cypherEngine.execute(cypher, params); }
@Override public boolean isDirty(Object instance, Object entry) { if (super.isDirty(instance, entry)) { return true; } DBObject dbo = (DBObject) entry; PersistentEntity entity = getPersistentEntity(); EntityAccess entityAccess = createEntityAccess(entity, instance, dbo); DBObject cached = (DBObject) ((SessionImplementor<?>) getSession()) .getCachedEntry(entity, (Serializable) entityAccess.getIdentifier(), true); return !dbo.equals(cached); }
@Override protected Serializable persistEntity(PersistentEntity pe, Object obj) { if ((obj == null) || (getSession().containsPersistingInstance(obj))) { return null; } EntityAccess entityAccess = createEntityAccess(pe, obj); if (getMappingContext().getProxyFactory().isProxy(obj)) { return (Serializable) entityAccess.getIdentifier(); } getSession().addPersistingInstance(obj); // cancel operation if vetoed boolean isUpdate = entityAccess.getIdentifier() != null; if (isUpdate) { if (cancelUpdate(pe, entityAccess)) { return null; } getSession() .addPendingUpdate( new NodePendingUpdate(entityAccess, getCypherEngine(), getMappingContext())); persistAssociationsOfEntity(pe, entityAccess, true); firePostUpdateEvent(pe, entityAccess); } else { if (cancelInsert(pe, entityAccess)) { return null; } getSession() .addPendingInsert( new NodePendingInsert( getSession().getDatastore().nextIdForType(pe), entityAccess, getCypherEngine(), getMappingContext())); persistAssociationsOfEntity(pe, entityAccess, false); firePostInsertEvent(pe, entityAccess); } return (Serializable) entityAccess.getIdentifier(); }
private void persistAssociationsOfEntity( PersistentEntity pe, EntityAccess entityAccess, boolean isUpdate) { Object obj = entityAccess.getEntity(); DirtyCheckable dirtyCheckable = null; if (obj instanceof DirtyCheckable) { dirtyCheckable = (DirtyCheckable) obj; } for (PersistentProperty pp : pe.getAssociations()) { if ((!isUpdate) || ((dirtyCheckable != null) && dirtyCheckable.hasChanged(pp.getName()))) { Object propertyValue = entityAccess.getProperty(pp.getName()); if ((pp instanceof OneToMany) || (pp instanceof ManyToMany)) { Association association = (Association) pp; if (propertyValue != null) { if (association.isBidirectional()) { // Populate other side of bidi for (Object associatedObject : (Iterable) propertyValue) { EntityAccess assocEntityAccess = createEntityAccess(association.getAssociatedEntity(), associatedObject); assocEntityAccess.setProperty(association.getReferencedPropertyName(), obj); } } Iterable targets = (Iterable) propertyValue; persistEntities(association.getAssociatedEntity(), targets); boolean reversed = RelationshipUtils.useReversedMappingFor(association); if (!reversed) { if (!(propertyValue instanceof LazyEnititySet)) { LazyEnititySet les = new LazyEnititySet( entityAccess, association, getMappingContext().getProxyFactory(), getSession()); les.addAll(targets); entityAccess.setProperty(association.getName(), les); } } } } else if (pp instanceof ToOne) { if (propertyValue != null) { ToOne to = (ToOne) pp; if (to.isBidirectional()) { // Populate other side of bidi EntityAccess assocEntityAccess = createEntityAccess(to.getAssociatedEntity(), propertyValue); if (to instanceof OneToOne) { assocEntityAccess.setProperty(to.getReferencedPropertyName(), obj); } else { Collection collection = (Collection) assocEntityAccess.getProperty(to.getReferencedPropertyName()); if (collection == null) { collection = new ArrayList(); assocEntityAccess.setProperty(to.getReferencedPropertyName(), collection); } if (!collection.contains(obj)) { collection.add(obj); } } } persistEntity(to.getAssociatedEntity(), propertyValue); boolean reversed = RelationshipUtils.useReversedMappingFor(to); String relType = RelationshipUtils.relationshipTypeUsedFor(to); if (!reversed) { getSession() .addPendingInsert( new RelationshipPendingInsert( entityAccess, relType, new EntityAccess(to.getAssociatedEntity(), propertyValue), getCypherEngine())); } } } else { throw new IllegalArgumentException( "wtf don't know how to handle " + pp + "(" + pp.getClass() + ")"); } } } }