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
}
}