private void persistAssociationsOfEntity()

in grails-data-neo4j/grails-datastore-gorm-neo4j/src/main/groovy/org/grails/datastore/gorm/neo4j/engine/Neo4jEntityPersister.java [878:1056]


    private void persistAssociationsOfEntity(GraphPersistentEntity graphEntity, EntityAccess entityAccess, boolean isUpdate) {

        Object obj = entityAccess.getEntity();
        DirtyCheckable dirtyCheckable = null;
        if (obj instanceof DirtyCheckable) {
            dirtyCheckable = (DirtyCheckable)obj;
        }

        Neo4jSession neo4jSession = getSession();
        if(graphEntity.hasDynamicAssociations()) {
            MappingContext mappingContext = graphEntity.getMappingContext();
            DynamicAttributes dynamicAttributes = (DynamicAttributes) obj;
            Map<String, Object> attributes = dynamicAttributes.attributes();
            for (Map.Entry<String, Object> entry : attributes.entrySet()) {
                Object value = entry.getValue();
                if(value == null) {
                    String associationName = entry.getKey();
                    Object originalValue = ((DirtyCheckable) obj).getOriginalValue(associationName);
                    if(originalValue != null && mappingContext.isPersistentEntity(originalValue)) {
                        processDynamicAssociationRemoval(graphEntity, entityAccess, neo4jSession, mappingContext, associationName, originalValue);
                    }
                    else if(originalValue instanceof Iterable) {
                        Iterable i = (Iterable) originalValue;
                        for (Object o : i) {
                            processDynamicAssociationRemoval(graphEntity, entityAccess, neo4jSession, mappingContext, associationName, o);
                        }
                    }
                }
                else if(mappingContext.isPersistentEntity(value)) {
                    if( ((DirtyCheckable)value).hasChanged() ) {
                        neo4jSession.persist(value);
                    }
                }
                else if(value instanceof Iterable) {
                    boolean collectionChanged = false;
                    for(Object o : ((Iterable)value)) {
                        if(mappingContext.isPersistentEntity(o)) {
                            collectionChanged = ((DirtyCheckable)o).hasChanged();
                            if(collectionChanged) break;
                        }
                    }

                    if(collectionChanged) {
                        neo4jSession.persist((Iterable)value);
                    }
                }
            }
        }

        for (PersistentProperty persistentProperty : graphEntity.getAssociations()) {
            String propertyName = persistentProperty.getName();
            if(persistentProperty instanceof Basic) {
                continue;
            }

            if ((!isUpdate) || ((dirtyCheckable!=null) && dirtyCheckable.hasChanged(propertyName))) {

                Object propertyValue = entityAccess.getProperty(propertyName);

                if ((persistentProperty instanceof OneToMany) || (persistentProperty instanceof ManyToMany)) {
                    Association association = (Association) persistentProperty;

                    if (propertyValue!= null) {

                        if(propertyValue instanceof PersistentCollection) {
                            PersistentCollection pc = (PersistentCollection) propertyValue;
                            if(!pc.isInitialized()) continue;
                        }

                        if (association.isBidirectional()) {
                            // Populate other side of bidi
                            for (Object associatedObject: (Iterable)propertyValue) {
                                EntityAccess assocEntityAccess = createEntityAccess(association.getAssociatedEntity(), associatedObject);
                                String referencedPropertyName = association.getReferencedPropertyName();
                                if(association instanceof ManyToMany) {
                                    ((GormEntity)associatedObject).addTo(referencedPropertyName, obj);
                                }
                                else {
                                    assocEntityAccess.setPropertyNoConversion(referencedPropertyName, obj);
                                    ((DirtyCheckable)associatedObject).markDirty(referencedPropertyName);
                                }
                            }
                        }

                        Collection targets = (Collection) propertyValue;
                        persistEntities(association.getAssociatedEntity(), targets);

                        boolean reversed = RelationshipUtils.useReversedMappingFor(association);

                        if (!reversed) {
                            Collection dcc = createDirtyCheckableAwareCollection(entityAccess, association, targets);
                            entityAccess.setProperty(association.getName(), dcc);
                        }
                    }
                } else if (persistentProperty instanceof ToOne) {
                    if (propertyValue != null) {
                        ToOne to = (ToOne) persistentProperty;

                        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(proxyFactory.isInitialized(collection) && !collection.isEmpty()) {
                                    boolean found = false;
                                    for (Object o : collection) {
                                        if(o.equals(obj)) {
                                            found = true; break;
                                        }
                                    }
                                    if (!found) {
                                        collection.add(obj);
                                    }
                                }
                                else {
                                    collection.add(obj);
                                }
                            }
                        }

                        persistEntity(to.getAssociatedEntity(), propertyValue);


                        Serializable thisId = (Serializable) entityAccess.getIdentifier();
                        final EntityAccess associationAccess = neo4jSession.createEntityAccess(to.getAssociatedEntity(), propertyValue);
                        Serializable associationId = (Serializable) associationAccess.getIdentifier();

                        if(graphEntity.isRelationshipEntity() && propertyName.equals(RelationshipPersistentEntity.FROM)) {
                            RelationshipPersistentEntity relEntity = (RelationshipPersistentEntity) graphEntity;
                            // reverse the ids to correctly align from and to
                            thisId = associationId;
                            Object toValue = entityAccess.getProperty(RelationshipPersistentEntity.TO);
                            if(toValue != null) {
                                GraphPersistentEntity toEntity = relEntity.getToEntity();
                                associationId = toEntity.getReflector().getIdentifier(toValue);
                                if(associationId == null) {
                                    associationId = persistEntity(toEntity,toValue);
                                }
                            }

                        }
                        if(thisId != null && associationId != null) {
                            boolean reversed = RelationshipUtils.useReversedMappingFor(to);
                            if (reversed) {
                                Association inverseSide = to.getInverseSide();
                                if(inverseSide != null) {
                                    neo4jSession.addPendingRelationshipInsert(associationId, inverseSide, thisId);
                                }
                            }
                            else {
                                neo4jSession.addPendingRelationshipInsert(thisId, to, associationId);
                            }
                        }


                    }
                    else if(isUpdate) {
                        Object previousValue = dirtyCheckable.getOriginalValue(propertyName);
                        if (previousValue != null) {
                            ToOne to = (ToOne) persistentProperty;
                            Serializable associationId = neo4jSession.getEntityPersister(previousValue).getObjectIdentifier(previousValue);
                            if (associationId != null) {
                                neo4jSession.addPendingRelationshipDelete((Serializable) entityAccess.getIdentifier(), to, associationId);
                            }
                        }
                    }
                } else {
                    throw new IllegalArgumentException("GORM for Neo4j doesn't support properties of the given type " + persistentProperty + "(" + persistentProperty.getClass().getSuperclass() +")" );
                }
            }


        }
    }