org.opensingular.form.wicket.util.WicketFormUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.opensingular.form.wicket.util.WicketFormUtils.java

Source

/*
 * Copyright (C) 2016 Singular Studios (a.k.a Atom Tecnologia) - www.opensingular.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.opensingular.form.wicket.util;

import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

import org.apache.commons.lang3.StringUtils;
import org.apache.wicket.Component;
import org.apache.wicket.MarkupContainer;
import org.apache.wicket.MetaDataKey;
import org.apache.wicket.model.IModel;
import org.opensingular.form.SIList;
import org.opensingular.form.SInstance;
import org.opensingular.form.wicket.WicketBuildContext;
import org.opensingular.form.wicket.model.ISInstanceAwareModel;
import org.opensingular.lib.wicket.util.util.WicketUtils;

import com.google.common.base.Objects;
import com.google.common.collect.Lists;

public abstract class WicketFormUtils {
    private static final MetaDataKey<Integer> KEY_INSTANCE_ID = new MetaDataKey<Integer>() {
    };
    private static final MetaDataKey<Boolean> KEY_IS_CELL_CONTAINER = new MetaDataKey<Boolean>() {
    };
    private static final MetaDataKey<MarkupContainer> KEY_CELL_CONTAINER = new MetaDataKey<MarkupContainer>() {
    };
    private static final MetaDataKey<MarkupContainer> KEY_ROOT_CONTAINER = new MetaDataKey<MarkupContainer>() {
    };

    private WicketFormUtils() {
    }

    public static void setRootContainer(Component component, MarkupContainer rootContainer) {
        component.setMetaData(KEY_ROOT_CONTAINER, rootContainer);
    }

    public static MarkupContainer getRootContainer(Component component) {
        return component.getMetaData(KEY_ROOT_CONTAINER);
    }

    public static void setInstanceId(Component component, SInstance instance) {
        component.setMetaData(KEY_INSTANCE_ID, instance.getId());
    }

    public static boolean isForInstance(Component component, SInstance instance) {
        return Objects.equal(component.getMetaData(KEY_INSTANCE_ID), instance.getId());
    }

    public static void markAsCellContainer(MarkupContainer container) {
        container.setMetaData(KEY_IS_CELL_CONTAINER, Boolean.TRUE);
    }

    public static boolean isMarkedAsCellContainer(Component container) {
        return Boolean.TRUE.equals(container.getMetaData(KEY_IS_CELL_CONTAINER));
    }

    public static void setCellContainer(Component component, MarkupContainer container) {
        container.setOutputMarkupId(true);
        component.setMetaData(KEY_CELL_CONTAINER, container);
    }

    public static Optional<MarkupContainer> findCellContainer(Component component) {
        // ele mesmo
        if (isMarkedAsCellContainer(component))
            return Optional.of((MarkupContainer) component);

        // referencia direta
        final MarkupContainer container = component.getMetaData(KEY_CELL_CONTAINER);
        if (container != null)
            return Optional.of(container);

        // busca nos ascendentes
        return streamAscendants(component).filter(WicketFormUtils::isMarkedAsCellContainer).findFirst();
    }

    public static Component resolveRefreshingComponent(Component component) {
        Component comp = component;
        while ((comp != null) && (comp.getParent() != null) && (!comp.getParent().isVisibleInHierarchy()))
            comp = comp.getParent();
        return comp;
    }

    public static MarkupContainer getCellContainer(Component component) {
        return findCellContainer(component).orElse(null);
    }

    public static Optional<Component> findChildByInstance(Component root, SInstance instance) {
        return streamDescendants(root).filter(c -> instanciaIfAware(c.getDefaultModel()).orElse(null) == instance)
                .findAny();
    }

    private static Optional<SInstance> instanciaIfAware(IModel<?> model) {
        return (model instanceof ISInstanceAwareModel<?>)
                ? Optional.ofNullable(((ISInstanceAwareModel<?>) model).getSInstance())
                : Optional.empty();
    }

    public static Stream<MarkupContainer> streamAscendants(Component root) {
        return WicketUtils.listParents(root).stream();
    }

    @SuppressWarnings("unchecked")
    public static Stream<Component> streamDescendants(Component root) {
        return Stream.of(root).flatMap(
                WicketUtils.$L.recursiveIterable(c -> (c instanceof Iterable<?>) ? (Iterable<Component>) c : null));
    }

    public static Optional<SInstance> resolveInstance(Component component) {
        return (component != null) ? resolveInstance(component.getDefaultModel()) : Optional.empty();
    }

    public static Optional<SInstance> resolveInstance(final IModel<?> model) {
        return (model instanceof ISInstanceAwareModel<?>)
                ? Optional.ofNullable(((ISInstanceAwareModel<?>) model).getSInstance())
                : Optional.empty();
    }

    public static String generateTitlePath(Component parentContainer, SInstance parentContext,
            Component childComponent, SInstance childInstance) {

        List<Component> components = Lists.newArrayList(childComponent);
        WicketUtils.appendListOfParents(components, childComponent, parentContainer);

        Deque<String> titles = new LinkedList<>();
        SInstance lastInstance = null;
        String lastTitle = null;
        for (Component comp : components) {

            SInstance instance = WicketFormUtils.instanciaIfAware(comp.getDefaultModel()).orElse(null);

            String title = findTitle(comp);
            if (title != null && !Objects.equal(title, lastTitle)) {
                lastTitle = title;
                addTitle(titles, title, instance, lastInstance);
            }
            lastInstance = instance;
        }

        if (!titles.isEmpty()) {
            return titles.stream().collect(Collectors.joining(" > "));
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    private static void addTitle(Deque<String> titles, String title, SInstance instance, SInstance lastInstance) {
        if ((lastInstance != null) && (instance instanceof SIList<?>)) {
            int pos = findPos((SIList<SInstance>) instance, lastInstance);
            if (pos != -1) {
                titles.addFirst(title + " [" + pos + "]");
            }
        } else {
            titles.addFirst(title);
        }
    }

    private static int findPos(@Nonnull SIList<SInstance> instance, @Nonnull SInstance lastInstance) {
        int pos = 1;
        for (SInstance itemInstance : instance) {
            if (lastInstance == itemInstance || lastInstance.isDescendantOf(itemInstance)) {
                return pos;
            }
            pos++;
        }
        return -1;
    }

    private static @Nullable String findTitle(Component comp) {
        WicketBuildContext wbc = WicketBuildContext.find(comp).orElse(null);
        if (wbc != null) {
            return wbc.resolveContainerTitle().map(it -> StringUtils.trimToNull(it.getObject())).orElse(null);
        }
        return null;

    }
}