protected void processAssociations()

in grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/engine/MongoCodecEntityPersister.groovy [262:373]


    protected void processAssociations(MongoCodecSession mongoCodecSession, PersistentEntity entity, EntityAccess entityAccess, obj, ProxyFactory proxyFactory, boolean isUpdate) {
        // now we must ensure that all cascades are handled and inserts / updates scheduled
        for (association in entity.associations) {
            def associatedEntity = association.associatedEntity
            if (association instanceof ToOne) {
                if (association instanceof Embedded) {
                    def propertyName = association.name
                    def value = entityAccess.getProperty(propertyName)
                    if (!proxyFactory.isInitialized(value)) {
                        continue
                    }
                    if (value != null) {
                        processAssociations(mongoCodecSession,
                                associatedEntity,
                                createEntityAccess(associatedEntity, value),
                                value,
                                proxyFactory,
                                isUpdate)
                    }
                } else {
                    def propertyName = association.name
                    def value = entityAccess.getProperty(propertyName)
                    if (value != null) {
                        if (association.isBidirectional() && !isUpdate) {
                            def inverseAccess = createEntityAccess(associatedEntity, value)
                            def inverseSide = association.inverseSide

                            def inverseName = inverseSide.name
                            if (inverseSide instanceof ToOne) {
                                inverseAccess.setPropertyNoConversion(
                                        inverseName,
                                        obj
                                )
                            } else if (inverseSide instanceof OneToMany) {
                                if (isUpdate) continue

                                def inverseCollection = inverseAccess.getProperty(inverseName)

                                if (inverseCollection == null) {
                                    inverseCollection = MappingUtils.createConcreteCollection(inverseSide.type)
                                    inverseAccess.setPropertyNoConversion(
                                            inverseName,
                                            inverseCollection
                                    )
                                }
                                if (inverseCollection instanceof Collection) {
                                    def coll = (Collection) inverseCollection
                                    if (!coll.contains(obj)) {
                                        coll << obj
                                    }
                                }

                            }
                        }
                        if (proxyFactory.isInitialized(value)) {
                            def dirtyCheckable = (DirtyCheckable) value
                            if (dirtyCheckable.hasChanged()) {
                                if (association.isOwningSide() || association.doesCascade(CascadeType.PERSIST)) {
                                    mongoCodecSession.persist(value)
                                }
                            }
                        }
                    }

                }
            } else if ((association instanceof OneToMany) || (association instanceof ManyToMany)) {
                def propertyName = association.name
                def value = entityAccess.getProperty(propertyName)
                boolean shouldPersist = false
                if (value != null && association.doesCascade(CascadeType.PERSIST)) {
                    if (!isUpdate) {
                        shouldPersist = true
                    } else {
                        if (value instanceof DirtyCheckableCollection) {
                            def dirtyCheckingCollection = DirtyCheckingSupport.wrap((Collection) value, (DirtyCheckable) obj, propertyName)
                            if (((DirtyCheckingCollection) dirtyCheckingCollection).hasChanged()) {
                                shouldPersist = true
                            }
                        } else {
                            shouldPersist = true
                        }
                    }

                    if (shouldPersist) {

                        def associatedEntities = (Iterable) value
                        if (association.isBidirectional()) {
                            def inverseSide = association.inverseSide
                            def inverseName = inverseSide.name
                            if (inverseSide instanceof ToOne) {

                                for (ae in associatedEntities) {
                                    createEntityAccess(associatedEntity, ae)
                                            .setPropertyNoConversion(inverseName, obj)
                                }
                            }
                        }

                        def identifiers = mongoCodecSession.persist(associatedEntities)
                        mongoCodecSession.setAttribute(
                                obj,
                                "${association}.ids",
                                identifiers
                        )

                        def dirtyCheckingCollection = DirtyCheckingSupport.wrap((Collection) value, (DirtyCheckable) obj, propertyName)
                        entityAccess.setPropertyNoConversion(propertyName, dirtyCheckingCollection)
                    }
                }
            }
        }
    }