}
private Object unmarshallProperty(GrailsDomainClass domainClass, String propertyName, Object propertyValue, DefaultUnmarshallingContext unmarshallingContext) {
// TODO : adapt behavior if the mapping option "component" or "reference" are set
// below is considering the "component" behavior
SearchableClassPropertyMapping scpm = elasticSearchContextHolder.getMappingContext(domainClass).getPropertyMapping(propertyName);
Object parseResult = null;
if (null == scpm) {
// TODO: unhandled property exists in index
}
if (null != scpm && propertyValue instanceof Map) {
@SuppressWarnings({"unchecked"})
Map<String, Object> data = (Map<String, Object>) propertyValue;
// Handle cycle reference
if (data.containsKey("ref")) {
unmarshallingContext.addCycleRef(propertyValue);
return null;
}
// Searchable reference.
if (scpm.getReference() != null) {
Class<?> refClass = scpm.getBestGuessReferenceType();
GrailsDomainClass refDomainClass = null;
for(GrailsClass dClazz : grailsApplication.getArtefacts(DomainClassArtefactHandler.TYPE)) {
if (dClazz.getClazz().equals(refClass)) {
refDomainClass = (GrailsDomainClass) dClazz;
break;
}
}
if (refDomainClass == null) {
throw new IllegalStateException("Found reference to non-domain class: " + refClass);
}
return unmarshallReference(refDomainClass, data, unmarshallingContext);
}
if (data.containsKey("class") && (Boolean)grailsApplication.getFlatConfig().get("elasticSearch.unmarshallComponents")) {
// Embedded instance.
if (!scpm.isComponent()) {
// maybe ignore?
throw new IllegalStateException("Property " + domainClass.getName() + "." + propertyName +
" is not mapped as [component], but broken search hit found.");
}
GrailsDomainClass nestedDomainClass = (GrailsDomainClass)
grailsApplication.getArtefact(DomainClassArtefactHandler.TYPE, (String) data.get("class"));
if (domainClass != null) {
// Unmarshall 'component' instance.
if (!scpm.isComponent()) {
throw new IllegalStateException("Object " + data.get("class") +
" found in index, but [" + propertyName + "] is not mapped as component.");
}
parseResult = unmarshallDomain(nestedDomainClass, data.get("id"), data, unmarshallingContext);
}
}
} else if (propertyValue instanceof Collection) {
List<Object> results = new ArrayList<Object>();
int index = 0;
for(Object innerValue : (Collection) propertyValue) {
unmarshallingContext.getUnmarshallingStack().push(String.valueOf(index));
Object parseItem = unmarshallProperty(domainClass, propertyName, innerValue, unmarshallingContext);
if (parseItem != null) {
results.add(parseItem);
}
index++;
unmarshallingContext.getUnmarshallingStack().pop();
}
parseResult = results;
} else {
// consider any custom property editors here.
if (scpm.getConverter() != null) {
if (scpm.getConverter() instanceof Class) {
try {
PropertyEditor propertyEditor = (PropertyEditor) ((Class) scpm.getConverter()).newInstance();
propertyEditor.setAsText((String) propertyValue);
parseResult = propertyEditor.getValue();
} catch (Exception e) {
throw new IllegalArgumentException("Unable to unmarshall " + propertyName +
" using " + scpm.getConverter(), e);
}
}
} else if (scpm.getReference() != null) {
// This is a reference and it MUST be null because it's not a Map.
if (propertyValue != null) {
throw new IllegalStateException("Found searchable reference which is not a Map: " + domainClass + "." + propertyName +
" = " + propertyValue);