protected processProperty()

in grails-web-databinding/src/main/groovy/grails/web/databinding/GrailsWebDataBinder.groovy [252:364]


    protected processProperty(obj, MetaProperty metaProperty, val, DataBindingSource source, DataBindingListener listener, errors) {
        boolean needsBinding = true

        if (source.dataSourceAware) {
            def propName = metaProperty.name
            def propertyType = getDomainClassType(obj, metaProperty.name)
            if (propertyType && isDomainClass(propertyType)) {
                def idValue = getIdentifierValueFrom(val)
                if (idValue != 'null' && idValue != null && idValue != '') {
                    def persistedInstance = getPersistentInstance(propertyType, idValue)
                    if (persistedInstance != null) {
                        needsBinding = false
                        bindProperty obj, source, metaProperty, persistedInstance, listener, errors
                        if (persistedInstance != null) {
                            if (val instanceof Map) {
                                bind persistedInstance, new SimpleMapDataBindingSource(val), listener
                            } else if (val instanceof DataBindingSource) {
                                bind persistedInstance, val, listener
                            }
                        }
                    }
                } else {
                    boolean shouldBindNull = false
                    if(val instanceof DataBindingSource) {
                        // bind null if this binding source does contain an identifier
                        shouldBindNull = ((DataBindingSource)val).hasIdentifier()
                    } else if(val instanceof Map) {
                        // bind null if this Map does contain an id
                        shouldBindNull = ((Map)val).containsKey('id')
                    } else if(idValue instanceof CharSequence) {
                        // bind null if idValue is a CharSequence because it would have
                        // to be 'null' or '' in order for control to be in this else block
                        shouldBindNull = true
                    }
                    if(shouldBindNull) {
                        needsBinding = false
                        bindProperty obj, source, metaProperty, null, listener, errors
                    }
                }
            } else if(Collection.isAssignableFrom(metaProperty.type)) {
                def referencedType = getReferencedTypeForCollection(propName, obj)
                if(referencedType) {
                    def listValue
                    if(val instanceof List) {
                        listValue = (List)val
                    } else if(val instanceof GPathResultMap && ((GPathResultMap)val).size() == 1) {
                        def mapValue = (GPathResultMap)val
                        def valueInMap = mapValue[mapValue.keySet()[0]]
                        if(valueInMap instanceof List) {
                            listValue = (List)valueInMap
                        } else {
                            listValue = [valueInMap]
                        }
                    }
                    if(listValue != null) {
                        needsBinding = false
                        def coll = initializeCollection obj, metaProperty.name, metaProperty.type
                        if(coll instanceof Collection) {
                            coll.clear()
                        }
                        def itemsWhichNeedBinding = []
                        listValue.each { item ->
                            def persistentInstance
                            if(isDomainClass(referencedType)) {
                                if(item instanceof Map || item instanceof DataBindingSource) {
                                    def idValue = getIdentifierValueFrom(item)
                                    if(idValue != null) {
                                        persistentInstance = getPersistentInstance(referencedType, idValue)
                                        if(persistentInstance != null) {
                                            DataBindingSource newBindingSource
                                            if(item instanceof DataBindingSource) {
                                                newBindingSource = (DataBindingSource)item
                                            } else {
                                                newBindingSource = new SimpleMapDataBindingSource((Map)item)
                                            }
                                            bind persistentInstance, newBindingSource, listener
                                            itemsWhichNeedBinding << persistentInstance
                                        }
                                    }
                                }
                            }
                            if(persistentInstance == null) {
                                itemsWhichNeedBinding << item
                            }
                        }
                        if(itemsWhichNeedBinding) {
                            for(item in itemsWhichNeedBinding) {
                                addElementToCollection obj, metaProperty.name, metaProperty.type, item, false
                            }
                        }
                    }
                }
            } else if (grailsApplication != null) { // Fixes bidirectional oneToOne binding issue #9308
                PersistentEntity domainClass = getPersistentEntity(obj.getClass())

                if (domainClass != null) {
                    def property = domainClass.getPropertyByName(metaProperty.name)
                    if (property != null && property instanceof Association) {
                        Association association = (Association)property
                        if (association.isBidirectional()) {
                            def otherSide = association.inverseSide
                            if (otherSide instanceof OneToOne) {
                                val[otherSide.name] = obj
                            }
                        }
                    }
                }
            }
        }
        if (needsBinding) {
            super.processProperty obj, metaProperty, val, source, listener, errors
        }
    }