public record CollectionPresentationSelectorHelper()

in viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collection/selector/CollectionPresentationSelectorHelper.java [46:218]


public record CollectionPresentationSelectorHelper(
        CollectionModel collectionModel,
        Can<ComponentFactoryKey> factoryKeys,
        ComponentHintKey componentHintKey
    )
implements Serializable {

    static final String UIHINT_EVENT_VIEW_KEY = CollectionModelParented.HINT_KEY_SELECTED_ITEM;

    public CollectionPresentationSelectorHelper(
            final CollectionModel collectionModel,
            final ComponentFactoryRegistry componentFactoryRegistry) {
        this(collectionModel, componentFactoryRegistry, ComponentHintKey.noop());
    }

    public CollectionPresentationSelectorHelper(
            final CollectionModel collectionModel,
            final ComponentFactoryRegistry componentFactoryRegistry,
            final ComponentHintKey componentHintKey) {
        this(collectionModel,
            gatherComponentFactories(componentFactoryRegistry, collectionModel),
            componentHintKey != null
                ? componentHintKey
                : ComponentHintKey.noop());
    }

    public String honourViewHintElseDefault(final Component component) {
        // honour hints ...
        final UiHintContainer hintContainer = getUiHintContainer(component);
        if (hintContainer != null) {
            String viewStr = hintContainer.getHint(component, UIHINT_EVENT_VIEW_KEY);
            if (viewStr != null) return viewStr;
        }

        // ... else default
        String initialFactory = determineInitialFactory();
        if (hintContainer != null) {
            hintContainer.setHint(component, UIHINT_EVENT_VIEW_KEY, initialFactory);
            // don't broadcast (no AjaxRequestTarget, still configuring initial setup)
        }
        return initialFactory;
    }

    Can<CollectionPresentationChoice> collectionPresentationChoices() {
        return factoryKeys
            .map(k->CollectionPresentationChoice.of(k.componentFactory()));
    }

    CollectionPresentationChoice find(final Can<CollectionPresentationChoice> presentationChoices, final String selected) {
        CollectionPresentationChoice componentFactory = doFind(presentationChoices, selected);
        if (componentFactory != null) return componentFactory;

        final String fallback = collectionModel.getVariant().isParented()
                ? CollectionContentsHiddenPanelFactory.NAME
                : CollectionContentsAsAjaxTablePanelFactory.NAME;
        componentFactory = doFind(presentationChoices, fallback);
        if(componentFactory == null) {
            throw new IllegalStateException(String.format(
                    "Could not locate '%s' (as the fallback collection panel)",
                    fallback));
        }
        return componentFactory;
    }

    // -- helpers

    /**
     * return the index of {@link CollectionContentsHiddenPanelFactory unresolved panel} if present and not eager loading;
     * else the index of {@link org.apache.causeway.viewer.wicket.ui.components.collection.present.ajaxtable.CollectionContentsAsAjaxTablePanelFactory ajax table} if present,
     * otherwise first factory.
     */
    private String determineInitialFactory() {

        // try to load from session, if can
        final Bookmark bookmark = collectionModel.parentedHintingBookmark().orElse(null);
        final String sessionAttribute = componentHintKey.get(bookmark);
        if(sessionAttribute != null) return sessionAttribute;

        // else grid layout hint
        final CollectionLayoutData layoutData = toParentedEntityCollectionModel(collectionModel)
                .map(CollectionModelParented::getLayoutData)
                .orElse(null);

        if(layoutData != null) {
            final String defaultView = layoutData.getDefaultView();
            if(defaultView != null) {
                return defaultView;
            }
        }

        // else @CollectionLayout#defaultView attribute
        if (hasDefaultViewFacet(collectionModel)) {

            final String viewName = Facets.defaultViewName(collectionModel.getMetaModel())
                    .orElseThrow(); // null case guarded by if clause

            for (ComponentFactoryKey componentFactory : factoryKeys) {
                final String componentName = componentFactory.id();
                if (componentName.equalsIgnoreCase(viewName)) {
                    return componentName;
                }
            }
        }

        // else honour @CollectionLayout#renderEagerly
        return hasRenderEagerlySemantics(collectionModel)
                || collectionModel.getVariant().isStandalone()
                    ? CollectionContentsAsAjaxTablePanelFactory.NAME
                    : CollectionContentsHiddenPanelFactory.NAME;

    }

    private static UiHintContainer getUiHintContainer(final Component component) {
        return UiHintContainer.Util.hintContainerOf(component, CollectionModelParented.class);
    }

    private static boolean hasRenderEagerlySemantics(final IModel<?> model) {
        return toParentedEntityCollectionModel(model)
        .map(CollectionModelParented::getMetaModel)
        .map(Facets::defaultViewIsTable)
        .orElse(false);
    }

    private static boolean hasDefaultViewFacet(final IModel<?> model) {
        return toParentedEntityCollectionModel(model)
        .map(CollectionModelParented::getMetaModel)
        .map(Facets::defaultViewIsPresent)
        .orElse(false);
    }

    private CollectionPresentationChoice doFind(final Can<CollectionPresentationChoice> presentationChoices, final String selected) {
        for (CollectionPresentationChoice componentFactory : presentationChoices) {
            if(selected.equals(componentFactory.id())) return componentFactory;
        }
        return null;
    }

    public int lookup(final String view) {
        int i=0;
        for (ComponentFactoryKey componentFactory : factoryKeys) {
            if(view.equals(componentFactory.id())) {
                return i;
            }
            i++;
        }
        return 0;
    }

    // -- HELPER

    private static Optional<CollectionModelParented> toParentedEntityCollectionModel(
            final @Nullable IModel<?> model) {
        if (model instanceof CollectionModelParented) {
            return Optional.of((CollectionModelParented) model);
        }
        return Optional.empty();
    }

    private static Can<ComponentFactoryKey> gatherComponentFactories(
        final ComponentFactoryRegistry componentFactoryRegistry,
        final CollectionModel collectionModel) {
    return componentFactoryRegistry
        .streamComponentFactories(ImmutableEnumSet.of(
                UiComponentType.COLLECTION_CONTENTS,
                UiComponentType.COLLECTION_CONTENTS_EXPORT),
                collectionModel)
        .filter(componentFactory ->
            componentFactory.getClass() != CollectionContentsMultipleViewsPanelFactory.class)
        .map(ComponentFactory::key)
        .collect(Can.toCan());
}

}