in core/metamodel/src/main/java/org/apache/causeway/core/metamodel/util/snapshot/XmlSnapshot.java [416:548]
private boolean includeField(final Place place, final Vector<String> fieldNames, final String annotation) {
if (log.isDebugEnabled()) {
log.debug("includeField(: {}{}{})", log("place", place), andlog("fieldNames", fieldNames),
andlog("annotation", annotation));
}
final ManagedObject object = place.getObject();
final Element xmlElement = place.getXmlElement();
// we use a copy of the path so that we can safely traverse collections
// without side-effects
final Vector<String> originalNames = fieldNames;
final Vector<String> names = new Vector<>();
for (final Enumeration<String> e = originalNames.elements(); e.hasMoreElements();) {
names.addElement(e.nextElement());
}
// see if we have any fields to process
if (names.size() == 0) {
return true;
}
// take the first field name from the list, and remove
final String fieldName = names.elementAt(0);
names.removeElementAt(0);
if (log.isDebugEnabled()) {
log.debug("includeField(Pl, Vec, Str):{}{}", log("processing field", fieldName),
andlog("left", "" + names.size()));
}
// locate the field in the object's class
final ObjectSpecification nos = object.getSpecification();
// HACK: really want a ObjectSpecification.hasField method to
// check first.
val field = nos.getAssociation(fieldName).orElse(null);
if (field == null) {
if (log.isInfoEnabled()) {
log.info("includeField(Pl, Vec, Str): could not locate field, skipping");
}
return false;
}
// locate the corresponding XML element
// (the corresponding XSD element will later be attached to xmlElement
// as its userData)
if (log.isDebugEnabled()) {
log.debug("includeField(Pl, Vec, Str): locating corresponding XML element");
}
val xmlFieldElements = elementsUnder(xmlElement, field.getId());
if (xmlFieldElements.size() != 1) {
if (log.isInfoEnabled()) {
log.info("includeField(Pl, Vec, Str): could not locate {}",
log("field", field.getId()) + andlog("xmlFieldElements.size", "" + xmlFieldElements.size()));
}
return false;
}
final Element xmlFieldElement = xmlFieldElements.elementAt(0);
if (names.size() == 0 && annotation != null) {
// nothing left in the path, so we will apply the annotation now
causewayMetaModel.setAnnotationAttribute(xmlFieldElement, annotation);
}
final Place fieldPlace = new Place(object, xmlFieldElement);
if (field instanceof OneToOneAssociation) {
if (field.getElementType().streamAssociations(MixedIn.INCLUDED).limit(1).count() == 0L) {
if (log.isDebugEnabled()) {
log.debug("includeField(Pl, Vec, Str): field is value; done");
}
return false;
}
if (log.isDebugEnabled()) {
log.debug("includeField(Pl, Vec, Str): field is 1->1");
}
final OneToOneAssociation oneToOneAssociation = ((OneToOneAssociation) field);
if(oneToOneAssociation.isExcludedFromSnapshots()) {
return false;
}
final ManagedObject referencedObject = oneToOneAssociation.get(fieldPlace.getObject(),
InteractionInitiatedBy.FRAMEWORK);
if (referencedObject == null) {
return true; // not a failure if the reference was null
}
final boolean appendedXml = appendXmlThenIncludeRemaining(fieldPlace, referencedObject, names, annotation);
if (log.isDebugEnabled()) {
log.debug("includeField(Pl, Vec, Str): 1->1: invoked appendXmlThenIncludeRemaining for {}{}",
log("referencedObj", referencedObject), andlog("returned", "" + appendedXml));
}
return appendedXml;
} else if (field instanceof OneToManyAssociation) {
if (log.isDebugEnabled()) {
log.debug("includeField(Pl, Vec, Str): field is 1->M");
}
final OneToManyAssociation oneToManyAssociation = (OneToManyAssociation) field;
final ManagedObject collection = oneToManyAssociation.get(fieldPlace.getObject(),
InteractionInitiatedBy.FRAMEWORK);
if (log.isDebugEnabled()) {
log.debug("includeField(Pl, Vec, Str): 1->M: {}",
log("collection.size", "" + CollectionFacet.elementCount(collection)));
}
final boolean[] allFieldsNavigated = { true }; // fast non-thread-safe value reference
CollectionFacet.streamAdapters(collection).forEach(referencedObject -> {
final boolean appendedXml = appendXmlThenIncludeRemaining(fieldPlace, referencedObject, names,
annotation);
if (log.isDebugEnabled()) {
log.debug("includeField(Pl, Vec, Str): 1->M: + invoked appendXmlThenIncludeRemaining for {}{}",
log("referencedObj", referencedObject), andlog("returned", "" + appendedXml));
}
allFieldsNavigated[0] = allFieldsNavigated[0] && appendedXml;
});
log.debug("includeField(Pl, Vec, Str): {}", log("returning", "" + allFieldsNavigated));
return allFieldsNavigated[0];
}
return false; // fall through, shouldn't get here but just in
// case.
}