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() +")" );
}
}
}
}