in core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/grid/GridSystemServiceAbstract.java [126:368]
protected abstract boolean validateAndNormalize(
final Grid grid,
final Class<?> domainClass);
/**
* Overwrites (replaces) any existing facets in the metamodel with info taken from the grid.
*
* @implNote This code uses {@link FacetUtil#updateFacet(Facet)}
* because the layout might be reloaded from XML if reloading is supported.
*/
private void overwriteFacets(
final G fcGrid,
final Class<?> domainClass) {
var objectSpec = specificationLoader.specForTypeElseFail(domainClass);
var oneToOneAssociationById = ObjectMember.mapById(objectSpec.streamProperties(MixedIn.INCLUDED));
var oneToManyAssociationById = ObjectMember.mapById(objectSpec.streamCollections(MixedIn.INCLUDED));
var objectActionById = ObjectMember.mapById(objectSpec.streamRuntimeActions(MixedIn.INCLUDED));
// governs, whether annotations win over XML grid, based on whether XML grid is fallback or 'explicit'
var precedence = fcGrid.isFallback()
? Facet.Precedence.LOW // fallback case: XML layout is overruled by layout from annotations
: Facet.Precedence.HIGH; // non-fallback case: XML layout overrules layout from annotations
final AtomicInteger propertySequence = new AtomicInteger(0);
fcGrid.visit(new Grid.VisitorAdapter() {
private int collectionSequence = 1;
private int actionDomainObjectSequence = 1;
private int actionPropertyGroupSequence = 1;
private int actionPropertySequence = 1;
private int actionCollectionSequence = 1;
@Override
public void visit(final DomainObjectLayoutData domainObjectLayoutData) {
updateFacetIfPresent(
BookmarkPolicyFacetForDomainObjectLayoutXml
.create(domainObjectLayoutData, objectSpec, precedence));
updateFacetIfPresent(
CssClassFacetForDomainObjectLayoutXml
.create(domainObjectLayoutData, objectSpec, precedence));
updateFacetIfPresent(
FaFacetForDomainObjectLayoutXml
.create(domainObjectLayoutData, objectSpec, precedence));
updateFacetIfPresent(
ObjectDescribedFacetForDomainObjectLayoutXml
.create(domainObjectLayoutData, objectSpec, precedence));
updateFacetIfPresent(
ObjectNamedFacetForDomainObjectLayoutXml
.create(domainObjectLayoutData, objectSpec, precedence));
updateFacetIfPresent(
TableDecoratorFacetForDomainObjectLayoutXml
.create(domainObjectLayoutData, objectSpec, precedence));
}
@Override
public void visit(final ActionLayoutData actionLayoutData) {
var actionLayoutDataOwner = actionLayoutData.getOwner();
var objectAction = objectActionById.get(actionLayoutData.getId());
if(objectAction == null) {
return;
}
{
GroupIdAndName groupIdAndName = null;
int memberOrderSequence;
if(actionLayoutDataOwner instanceof FieldSet) {
var fieldSet = (FieldSet) actionLayoutDataOwner;
for (var propertyLayoutData : fieldSet.getProperties()) {
// any will do; choose the first one that we know is valid
if(oneToOneAssociationById.containsKey(propertyLayoutData.getId())) {
groupIdAndName = GroupIdAndName
.forPropertyLayoutData(propertyLayoutData)
.orElse(null);
break;
}
}
memberOrderSequence = actionPropertyGroupSequence++;
} else if(actionLayoutDataOwner instanceof PropertyLayoutData) {
groupIdAndName = GroupIdAndName
.forPropertyLayoutData((PropertyLayoutData) actionLayoutDataOwner)
.orElse(null);
memberOrderSequence = actionPropertySequence++;
} else if(actionLayoutDataOwner instanceof CollectionLayoutData) {
groupIdAndName = GroupIdAndName
.forCollectionLayoutData((CollectionLayoutData) actionLayoutDataOwner)
.orElse(null);
memberOrderSequence = actionCollectionSequence++;
} else {
// don't add: any existing metadata should be preserved
groupIdAndName = null;
memberOrderSequence = actionDomainObjectSequence++;
}
updateFacet(
LayoutOrderFacetForLayoutXml.create(memberOrderSequence, objectAction, precedence));
//XXX hotfix: always override LayoutGroupFacetFromActionLayoutAnnotation, otherwise actions are not shown - don't know why
var precedenceHotfix = fcGrid.isFallback()
? Facet.Precedence.DEFAULT
: Facet.Precedence.HIGH;
updateFacetIfPresent(
LayoutGroupFacetForLayoutXml.create(groupIdAndName, objectAction, precedenceHotfix));
}
// fix up the action position if required
if(actionLayoutDataOwner instanceof FieldSet) {
if(actionLayoutData.getPosition() == null ||
actionLayoutData.getPosition() == org.apache.causeway.applib.annotation.ActionLayout.Position.BELOW ||
actionLayoutData.getPosition() == org.apache.causeway.applib.annotation.ActionLayout.Position.RIGHT) {
actionLayoutData.setPosition(org.apache.causeway.applib.annotation.ActionLayout.Position.PANEL);
}
} else if(actionLayoutDataOwner instanceof PropertyLayoutData) {
if(actionLayoutData.getPosition() == null ||
actionLayoutData.getPosition() == org.apache.causeway.applib.annotation.ActionLayout.Position.PANEL_DROPDOWN ||
actionLayoutData.getPosition() == org.apache.causeway.applib.annotation.ActionLayout.Position.PANEL) {
actionLayoutData.setPosition(org.apache.causeway.applib.annotation.ActionLayout.Position.BELOW);
}
} else {
// doesn't do anything for DomainObject or Collection
actionLayoutData.setPosition(null);
}
updateFacetIfPresent(
ActionPositionFacetForActionLayoutXml.create(actionLayoutData, objectAction, precedence));
updateFacetIfPresent(
CssClassFacetForActionLayoutXml.create(actionLayoutData, objectAction, precedence));
updateFacetIfPresent(
FaFacetForActionLayoutXml.create(actionLayoutData, objectAction, precedence));
updateFacetIfPresent(
MemberDescribedFacetForActionLayoutXml.create(actionLayoutData, objectAction, precedence));
updateFacetIfPresent(
HiddenFacetForActionLayoutXml.create(actionLayoutData, objectAction, precedence));
updateFacetIfPresent(
MemberNamedFacetForActionLayoutXml.create(actionLayoutData, objectAction, precedence));
updateFacetIfPresent(
Optional.ofNullable(actionLayoutData)
.map(ActionLayoutData::getPromptStyle)
.map(promptStyle->new PromptStyleFacet("ActionLayoutXml", promptStyle, objectAction, precedence, true)));
}
@Override
public void visit(final PropertyLayoutData propertyLayoutData) {
var oneToOneAssociation = oneToOneAssociationById.get(propertyLayoutData.getId());
if(oneToOneAssociation == null) return;
updateFacetIfPresent(
CssClassFacetForPropertyLayoutXml.create(propertyLayoutData, oneToOneAssociation, precedence));
updateFacetIfPresent(
MemberDescribedFacetForPropertyLayoutXml.create(propertyLayoutData, oneToOneAssociation, precedence));
updateFacetIfPresent(
HiddenFacetForPropertyLayoutXml.create(propertyLayoutData, oneToOneAssociation, precedence));
updateFacetIfPresent(
LabelAtFacetForPropertyLayoutXml.create(propertyLayoutData, oneToOneAssociation, precedence));
updateFacetIfPresent(
MultiLineFacetForPropertyLayoutXml.create(propertyLayoutData, oneToOneAssociation, precedence));
updateFacetIfPresent(
MemberNamedFacetForPropertyLayoutXml.create(propertyLayoutData, oneToOneAssociation, precedence));
updateFacetIfPresent(
Optional.ofNullable(propertyLayoutData)
.map(PropertyLayoutData::getPromptStyle)
.map(promptStyle->new PromptStyleFacet("PropertyLayoutXml", promptStyle, oneToOneAssociation, precedence, true)));
updateFacetIfPresent(
RenderedAdjustedFacetForPropertyLayoutXml.create(propertyLayoutData, oneToOneAssociation, precedence));
updateFacetIfPresent(
UnchangingFacetForPropertyLayoutXml.create(propertyLayoutData, oneToOneAssociation, precedence));
updateFacetIfPresent(
TypicalLengthFacetForPropertyLayoutXml.create(propertyLayoutData, oneToOneAssociation, precedence));
// Layout group-name based on owning property group, Layout sequence monotonically increasing
// nb for any given field set the sequence won't reset to zero; however this is what we want so that
// table columns are shown correctly (by fieldset, then property order within that fieldset).
final FieldSet fieldSet = propertyLayoutData.getOwner();
updateFacet(LayoutOrderFacetForLayoutXml.create(propertySequence.incrementAndGet(), oneToOneAssociation, precedence));
updateFacetIfPresent(
LayoutGroupFacetForLayoutXml.create(fieldSet, oneToOneAssociation, precedence));
}
@Override
public void visit(final CollectionLayoutData collectionLayoutData) {
var oneToManyAssociation = oneToManyAssociationById.get(collectionLayoutData.getId());
if(oneToManyAssociation == null) {
return;
}
updateFacetIfPresent(
CssClassFacetForCollectionLayoutXml
.create(collectionLayoutData, oneToManyAssociation, precedence));
updateFacetIfPresent(
DefaultViewFacetForCollectionLayoutXml
.create(collectionLayoutData, oneToManyAssociation, precedence));
updateFacetIfPresent(
TableDecoratorFacetForCollectionLayoutXml
.create(collectionLayoutData, oneToManyAssociation, precedence));
updateFacetIfPresent(
MemberDescribedFacetForCollectionLayoutXml
.create(collectionLayoutData, oneToManyAssociation, precedence));
updateFacetIfPresent(
HiddenFacetForCollectionLayoutXml
.create(collectionLayoutData, oneToManyAssociation, precedence));
updateFacetIfPresent(
MemberNamedFacetForCollectionLayoutXml
.create(collectionLayoutData, oneToManyAssociation, precedence));
updateFacetIfPresent(
PagedFacetForCollectionLayoutXml
.create(collectionLayoutData, oneToManyAssociation, precedence));
updateFacetIfPresent(
SortedByFacetForCollectionLayoutXml
.create(collectionLayoutData, oneToManyAssociation, precedence));
updateFacet(LayoutOrderFacetForLayoutXml
.create(collectionSequence++, oneToManyAssociation, precedence));
}
});
}