final boolean hasReferenceAttribute = obElement.getAttributes().get(
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);
// 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;
// now parse the property elements
while (true) {
xmlReader.nextTag();
if (isAtEndElement(xmlReader, entityName)) {
break;
}
final LocalElement childElement = getElement(xmlReader);
final Property p = entity.getProperty(childElement.getName());
log.debug(">>> Importing 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");
skipElement(xmlReader);
continue;
}
// ignore the id properties as they are already set, or should
// not be set
if (p.isId()) {
skipElement(xmlReader);
continue;
}
if (p.isOneToMany()) {
throw new EntityXMLException("This XML converter can not handle one-to-many properties");
}
final Object currentValue = bob.get(p.getName());
// do the primitive values
if (p.isPrimitive()) {
// NOTE: I noticed a difference between running from Eclipse and from the commandline
// after some searching, there is a jar file wstx-asl-3.0.2.jar used in
// src-db/database/lib
// which provides the woodstox XMLStreamReader. From the commandline the xerces
// XMLStreamReader
// is used. They differ in the handling of the getText method in handling entities. For
// example the following text: <text>Tom&Jerry</text> now assume that the pointer is
// at the content of the text tag, and you do getText, then woodstox will return Tom&Jerry
// while xerces will return Tom, this because the & is an entity which is a separate
// event.
// below we use the getElementText which works correctly in both cases apparently
// element value, note that getElementText means that it is not required anymore
// to go to element end, that is done by the xmlReader
final String elementText = xmlReader.getElementText();
Object newValue = XMLTypeConverter.getInstance().fromXML(p.getPrimitiveType(),
elementText);
// 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 {
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)) {
skipElement(xmlReader);
continue;
}
// determine the referenced entity
Object newValue;
// handle null value
if (childElement.getAttributes().get(XMLConstants.ID_ATTRIBUTE) == null) {
newValue = null;
} else {
// get the info and resolve the reference
final String refId = childElement.getAttributes().get(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;
}
}
checkEndElement(xmlReader, childElement.getName());
}