in core/metamodel/src/main/java/org/apache/causeway/core/metamodel/util/snapshot/XmlSnapshot.java [625:815]
Place objectToElement(final ManagedObject adapter) {
if (log.isDebugEnabled()) {
log.debug("objectToElement({})", log("object", adapter));
}
final ObjectSpecification spec = adapter.objSpec();
if (log.isDebugEnabled()) {
log.debug("objectToElement(NO): create element and causeway:title");
}
final Element element = schema.createElement(getXmlDocument(), spec.getShortIdentifier(),
spec.getFullIdentifier(), spec.getSingularName());
causewayMetaModel.appendCausewayTitle(element, adapter.getTitle());
if (log.isDebugEnabled()) {
log.debug("objectToElement(NO): create XS element for Causeway class");
}
final Element xsElement = schema.createXsElementForNofClass(getXsdDocument(), element, topLevelElementWritten,
FacetUtil.getFacetsByType(spec));
// hack: every element in the XSD schema apart from first needs minimum
// cardinality setting.
topLevelElementWritten = true;
final Place place = new Place(adapter, element);
causewayMetaModel.setAttributesForClass(element, oidAsString(adapter).toString());
final List<ObjectAssociation> fields = spec.streamAssociations(MixedIn.INCLUDED)
.collect(Collectors.toList());
if (log.isDebugEnabled()) {
log.debug("objectToElement(NO): processing fields");
}
eachField: for (int i = 0; i < fields.size(); i++) {
final ObjectAssociation field = fields.get(i);
final String fieldName = field.getId();
if (log.isDebugEnabled()) {
log.debug("objectToElement(NO): {}", log("field", fieldName));
}
// Skip field if we have seen the name already
for (int j = 0; j < i; j++) {
if (Objects.equals(fieldName, fields.get(i).getFriendlyName(adapter))) {
log.debug("objectToElement(NO): {} SKIPPED", log("field", fieldName));
continue eachField;
}
}
Element xmlFieldElement = getXmlDocument().createElementNS(
schema.getUri(), // scoped by namespace of class
/* of containing object*/ schema.getPrefix() + ":" + fieldName);
Element xsdFieldElement = null;
if (field.getElementType().isValue()) {
if (log.isDebugEnabled()) {
log.debug("objectToElement(NO): {} is value", log("field", fieldName));
}
final ObjectSpecification fieldSpec = field.getElementType();
// skip fields of type XmlValue
if (fieldSpec == null) {
continue eachField;
}
if (fieldSpec.getFullIdentifier() != null && fieldSpec.getFullIdentifier().endsWith("XmlValue")) {
continue eachField;
}
final OneToOneAssociation valueAssociation = ((OneToOneAssociation) field);
if(valueAssociation.isExcludedFromSnapshots()) {
continue eachField;
}
final Element xmlValueElement = xmlFieldElement; // more meaningful locally scoped name
ManagedObject value;
try {
value = valueAssociation.get(adapter, InteractionInitiatedBy.PASS_THROUGH);
var valueSpec = value.objSpec();
// XML
causewayMetaModel.setAttributesForValue(xmlValueElement, valueSpec.getShortIdentifier());
// value as JSON
var valueStr = fieldSpec.valueFacetElseFail()
.enstring(Format.JSON, _Casts.uncheckedCast(value.getPojo()));
if (_Strings.isNotEmpty(valueStr)) {
xmlValueElement.appendChild(getXmlDocument().createTextNode(valueStr));
} else {
causewayMetaModel.setIsEmptyAttribute(xmlValueElement, true);
}
} catch (final Exception ex) {
log.warn("objectToElement(NO): {}: getField() threw exception - skipping XML generation",
log("field", fieldName));
}
// XSD
xsdFieldElement = schema.createXsElementForNofValue(xsElement, xmlValueElement,
FacetUtil.getFacetsByType(valueAssociation));
} else if (field instanceof OneToOneAssociation) {
if (log.isDebugEnabled()) {
log.debug("objectToElement(NO): {} is OneToOneAssociation", log("field", fieldName));
}
final OneToOneAssociation oneToOneAssociation = ((OneToOneAssociation) field);
final String fullyQualifiedClassName = spec.getFullIdentifier();
final Element xmlReferenceElement = xmlFieldElement; // more meaningful locally scoped name
ManagedObject referencedObjectAdapter;
try {
referencedObjectAdapter = oneToOneAssociation.get(adapter, InteractionInitiatedBy.PASS_THROUGH);
// XML
causewayMetaModel.setAttributesForReference(xmlReferenceElement, schema.getPrefix(),
fullyQualifiedClassName);
if (referencedObjectAdapter != null) {
causewayMetaModel.appendCausewayTitle(xmlReferenceElement, referencedObjectAdapter.getTitle());
} else {
causewayMetaModel.setIsEmptyAttribute(xmlReferenceElement, true);
}
} catch (final Exception ex) {
log.warn("objectToElement(NO): {}: getAssociation() threw exception - skipping XML generation",
log("field", fieldName));
}
// XSD
xsdFieldElement = schema.createXsElementForNofReference(xsElement, xmlReferenceElement,
oneToOneAssociation.getElementType().getFullIdentifier(),
FacetUtil.getFacetsByType(oneToOneAssociation));
} else if (field instanceof OneToManyAssociation) {
if (log.isDebugEnabled()) {
log.debug("objectToElement(NO): {} is OneToManyAssociation", log("field", fieldName));
}
final OneToManyAssociation oneToManyAssociation = (OneToManyAssociation) field;
final Element xmlCollectionElement = xmlFieldElement; // more meaningful locally scoped name
ManagedObject collection;
try {
collection = oneToManyAssociation.get(adapter, InteractionInitiatedBy.PASS_THROUGH);
final ObjectSpecification referencedTypeNos = oneToManyAssociation.getElementType();
final String fullyQualifiedClassName = referencedTypeNos.getFullIdentifier();
// XML
causewayMetaModel.setCausewayCollection(xmlCollectionElement, schema.getPrefix(), fullyQualifiedClassName,
collection);
} catch (final Exception ex) {
log.warn("objectToElement(NO): {}: get(obj) threw exception - skipping XML generation",
log("field", fieldName));
}
// XSD
xsdFieldElement = schema.createXsElementForNofCollection(xsElement, xmlCollectionElement,
oneToManyAssociation.getElementType().getFullIdentifier(),
FacetUtil.getFacetsByType(oneToManyAssociation));
} else {
if (log.isInfoEnabled()) {
log.info("objectToElement(NO): {} is unknown type; ignored", log("field", fieldName));
}
continue;
}
Place.setXsdElement(xmlFieldElement, xsdFieldElement);
// XML
if (log.isDebugEnabled()) {
log.debug("objectToElement(NO): invoking mergeTree for field");
}
xmlFieldElement = mergeTree(element, xmlFieldElement);
// XSD
if (log.isDebugEnabled()) {
log.debug("objectToElement(NO): adding XS element for field to schema");
}
schema.addFieldXsElement(xsElement, xsdFieldElement);
}
return place;
}