final boolean hasReferenceAttribute = obElement
.attributeValue(XMLConstants.REFERENCE_ATTRIBUTE) != null;
// resolve the entity, using the id, note that
// resolve will create a new object if none is found
BaseOBObject bob = resolve(entityName, id, false);
// should never be null at this point
Check.isNotNull(bob, "The business object " + entityName + " (" + id
+ ") can not be resolved");
// warn/error is logged below if the entity is updated
// update is prevented below
final boolean writable = OBContext.getOBContext().isInAdministratorMode()
|| SecurityChecker.getInstance().isWritable(bob);
// referenced and not new, so already there, don't update
if (hasReferenceAttribute && !bob.isNewOBObject()) {
return bob;
}
if (!writable && bob.isNewOBObject()) {
error("Object " + entityName + "(" + id + ") is new but not writable");
return bob;
}
// do some checks to determine if this one should be updated
// a referenced instance should not be updated if it is not new
// note that embedded children are updated but non-embedded children
// are not updated!
final boolean preventRealUpdate = !writable
|| (hasReferenceAttribute && !bob.isNewOBObject());
final Entity entity = ModelProvider.getInstance().getEntity(obElement.getName());
boolean updated = false;
// the onetomany properties are done in a second pass
final List<Element> oneToManyElements = new ArrayList<Element>();
// now parse the property elements
for (final Element childElement : (List<Element>) obElement.elements()) {
final Property p = entity.getProperty(childElement.getName());
log.debug(">>> Exporting property " + p.getName());
// TODO: make this option controlled
final boolean isNotImportableProperty = p.isTransient(bob)
|| (p.isAuditInfo() && !isOptionImportAuditInfo()) || p.isInactive();
if (isNotImportableProperty) {
log.debug("Property " + p + " is inactive, transient or auditinfo, " + "ignoring it");
continue;
}
// ignore the id properties as they are already set, or should
// not be set
if (p.isId()) {
continue;
}
final Object currentValue = bob.get(p.getName());
// do the primitive values
if (p.isPrimitive()) {
Object newValue = XMLTypeConverter.getInstance().fromXML(p.getPrimitiveType(),
childElement.getText());
// correct the value
newValue = replaceValue(bob, p, newValue);
log.debug("Primitive property with value " + newValue);
// only update if changed
if ((currentValue == null && newValue != null)
|| (currentValue != null && newValue == null)
|| (currentValue != null && newValue != null && !currentValue.equals(newValue))) {
log.debug("Value changed setting it");
if (!preventRealUpdate) {
bob.set(p.getName(), newValue);
updated = true;
}
}
} else if (p.isOneToMany()) {
// resolve the content of the list
final List<BaseOBObject> newValues = new ArrayList<BaseOBObject>();
for (final Object o : childElement.elements()) {
final Element listElement = (Element) o;
newValues.add(processEntityElement(listElement.getName(), listElement, true));
}
// get the currentvalue and compare
final List<BaseOBObject> currentValues = (List<BaseOBObject>) currentValue;
if (!newValues.equals(currentValues)) {
if (!preventRealUpdate) {
// TODO: is this efficient? Or will it even work
// with hibernate first removing all?
currentValues.clear();
currentValues.addAll(newValues);
updated = true;
}
}
} else {
Check.isTrue(!p.isOneToMany(), "One to many property not allowed here");
// never update the org or client through xml!
final boolean clientUpdate = bob instanceof ClientEnabled
&& p.getName().equals(Organization.PROPERTY_CLIENT);
final boolean orgUpdate = bob instanceof OrganizationEnabled
&& p.getName().equals(Client.PROPERTY_ORGANIZATION);
if (!isOptionClientImport() && currentValue != null && (clientUpdate || orgUpdate)) {
continue;
}
// determine the referenced entity
Object newValue;
// handle null value
if (childElement.attribute(XMLConstants.ID_ATTRIBUTE) == null) {
newValue = null;
} else {
// get the info and resolve the reference
final String refId = childElement.attributeValue(XMLConstants.ID_ATTRIBUTE);
final String refEntityName = p.getTargetEntity().getName();
newValue = resolve(refEntityName, refId, true);
}
newValue = replaceValue(bob, p, newValue);
final boolean hasChanged = (currentValue == null && newValue != null)
|| (currentValue != null && newValue != null && !currentValue.equals(newValue));
if (hasChanged) {
log.debug("Setting value " + newValue);
if (!preventRealUpdate) {
bob.set(p.getName(), newValue);
updated = true;
}
}
}