protected abstract boolean validateAndNormalize()

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));
            }
        });
    }