de.metas.ui.web.window.descriptor.DocumentLayoutElementDescriptor.java Source code

Java tutorial

Introduction

Here is the source code for de.metas.ui.web.window.descriptor.DocumentLayoutElementDescriptor.java

Source

package de.metas.ui.web.window.descriptor;

import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Set;
import java.util.stream.Stream;

import org.adempiere.exceptions.AdempiereException;
import org.slf4j.Logger;

import com.google.common.base.Joiner;
import com.google.common.base.MoreObjects;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableSet;

import de.metas.i18n.IMsgBL;
import de.metas.i18n.ITranslatableString;
import de.metas.i18n.ImmutableTranslatableString;
import de.metas.logging.LogManager;
import de.metas.ui.web.window.datatypes.MediaType;
import de.metas.ui.web.window.exceptions.DocumentLayoutBuildException;
import de.metas.util.Check;
import de.metas.util.GuavaCollectors;
import de.metas.util.Services;
import lombok.NonNull;

/*
 * #%L
 * metasfresh-webui-api
 * %%
 * Copyright (C) 2016 metas GmbH
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as
 * published by the Free Software Foundation, either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program. If not, see
 * <http://www.gnu.org/licenses/gpl-2.0.html>.
 * #L%
 */

public final class DocumentLayoutElementDescriptor {
    public static final Builder builder() {
        return new Builder();
    }

    public static final Builder builder(final DocumentFieldDescriptor... fields) {
        Check.assumeNotEmpty(fields, "fields is not empty");

        final DocumentFieldDescriptor firstField = fields[0];

        final Builder elementBuilder = new Builder().setCaption(firstField.getCaption())
                // .setDescription(firstField.getDescription())
                .setWidgetType(firstField.getWidgetType()).setWidgetSize(firstField.getWidgetSize());

        for (final DocumentFieldDescriptor field : fields) {
            elementBuilder.addField(DocumentLayoutElementFieldDescriptor.builder(field.getFieldName())
                    .setPublicField(true).setLookupSource(field.getLookupSourceType())
                    .setLookupTableName(field.getLookupTableName()).setSupportZoomInto(field.isSupportZoomInto()));
        }

        return elementBuilder;
    }

    public static final Builder builder(@NonNull final DocumentEntityDescriptor entityDescriptor,
            @NonNull final String... fieldNames) {
        Check.assumeNotEmpty(fieldNames, "fieldNames is not empty");

        final DocumentFieldDescriptor[] elementFields = Stream.of(fieldNames)
                .map(fieldName -> entityDescriptor.getFieldOrNull(fieldName)).filter(Predicates.notNull())
                .toArray(size -> new DocumentFieldDescriptor[size]);

        return builder(elementFields);
    }

    private final String internalName;
    private final boolean gridElement;

    private final ITranslatableString caption;
    private final ITranslatableString description;

    private final DocumentFieldWidgetType widgetType;
    private final boolean allowShowPassword; // in case widgetType is Password
    private final boolean multilineText; // in case widgetType is Text
    private final int multilineTextLines; // in case widgetType is Text
    private final ButtonFieldActionDescriptor buttonActionDescriptor;

    private final LayoutType layoutType;
    private final WidgetSize widgetSize;
    private final boolean advancedField;
    private final ImmutableSet<MediaType> restrictToMediaTypes;

    private final LayoutAlign gridAlign;
    private final ViewEditorRenderMode viewEditorRenderMode;
    private final boolean viewAllowSorting;

    private final Set<DocumentLayoutElementFieldDescriptor> fields;

    private String _captionAsFieldNames; // lazy

    private static final Joiner JOINER_FieldNames = Joiner.on(" | ").skipNulls();

    private DocumentLayoutElementDescriptor(final Builder builder) {
        internalName = builder.getInternalName();
        gridElement = builder.isGridElement();

        caption = builder.getCaption();
        description = builder.getDescription();

        widgetType = builder.getWidgetType();
        allowShowPassword = builder.isAllowShowPassword();
        multilineText = builder.isMultilineText();
        multilineTextLines = builder.getMultilineTextLines();
        buttonActionDescriptor = builder.getButtonActionDescriptor();

        layoutType = builder.getLayoutType();
        widgetSize = builder.getWidgetSize();
        restrictToMediaTypes = builder.getRestrictToMediaTypes();

        gridAlign = builder.getGridAlign();
        viewEditorRenderMode = builder.getViewEditorRenderMode();
        viewAllowSorting = builder.isViewAllowSorting();

        advancedField = builder.isAdvancedField();

        fields = ImmutableSet.copyOf(builder.buildFields());
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(this).omitNullValues().add("internalName", internalName)
                .add("caption", caption).add("description", description).add("widgetType", widgetType)
                .add("advancedField", advancedField).add("fields", fields.isEmpty() ? null : fields).toString();
    }

    public boolean isGridElement() {
        return gridElement;
    }

    public String getCaption(final String adLanguage) {
        return caption.translate(adLanguage);
    }

    public String getCaptionAsFieldNames() {
        if (_captionAsFieldNames == null) {
            _captionAsFieldNames = fields.stream().filter(field -> field.isPublicField()) // only those which are public
                    .map(field -> field.getField()).collect(GuavaCollectors.toString(JOINER_FieldNames));
        }
        return _captionAsFieldNames;
    }

    public String getDescription(final String adLanguage) {
        return description.translate(adLanguage);
    }

    public DocumentFieldWidgetType getWidgetType() {
        return widgetType;
    }

    public Set<MediaType> getRestrictToMediaTypes() {
        return restrictToMediaTypes;
    }

    public boolean isAllowShowPassword() {
        return allowShowPassword;
    }

    public boolean isMultilineText() {
        return multilineText;
    }

    public int getMultilineTextLines() {
        return multilineTextLines;
    }

    public LayoutType getLayoutType() {
        return layoutType;
    }

    public WidgetSize getWidgetSize() {
        return widgetSize;
    }

    public LayoutAlign getGridAlign() {
        return gridAlign;
    }

    public ViewEditorRenderMode getViewEditorRenderMode() {
        return viewEditorRenderMode;
    }

    public boolean isViewAllowSorting() {
        return viewAllowSorting;
    }

    public boolean isAdvancedField() {
        return advancedField;
    }

    public Set<DocumentLayoutElementFieldDescriptor> getFields() {
        return fields;
    }

    public boolean hasFields() {
        return !fields.isEmpty();
    }

    public String getFirstFieldName() {
        return fields.iterator().next().getField();
    }

    public ButtonFieldActionDescriptor getButtonActionDescriptor() {
        return buttonActionDescriptor;
    }

    public static final class Builder {
        private static final Logger logger = LogManager.getLogger(DocumentLayoutElementDescriptor.Builder.class);

        private String _internalName;
        private ITranslatableString _caption = null;
        private ITranslatableString _description = null;

        private DocumentFieldWidgetType _widgetType;
        private boolean _allowShowPassword = false; // in case widgetType is Password
        private boolean _multilineText = false; // in case widgetType is Text
        private int _multilineTextLines = 0; // in case widgetType is Text
        private ButtonFieldActionDescriptor buttonActionDescriptor = null;

        private LayoutType _layoutType;
        private WidgetSize _widgetSize;
        private Set<MediaType> restrictToMediaTypes = new HashSet<>();

        private boolean _gridElement = false;
        private ViewEditorRenderMode viewEditorRenderMode = null;
        private boolean viewAllowSorting = true;

        private boolean _advancedField = false;
        private final LinkedHashMap<String, DocumentLayoutElementFieldDescriptor.Builder> _fieldsBuilders = new LinkedHashMap<>();
        private boolean excludeSpecialFields = false;
        private boolean consumed = false;

        private Builder() {
        }

        @Override
        public String toString() {
            return MoreObjects.toStringHelper(this).omitNullValues().add("internalName", _internalName)
                    .add("caption", _caption).add("description", _description).add("widgetType", _widgetType)
                    .add("consumed", consumed ? Boolean.TRUE : null).add("fields-count", _fieldsBuilders.size())
                    .toString();
        }

        public DocumentLayoutElementDescriptor build() {
            setConsumed();

            final DocumentLayoutElementDescriptor result = new DocumentLayoutElementDescriptor(this);

            logger.trace("Built {} for {}", result, this);
            return result;
        }

        private Set<DocumentLayoutElementFieldDescriptor> buildFields() {
            return _fieldsBuilders.values().stream().filter(fieldBuilder -> checkValid(fieldBuilder))
                    .map(fieldBuilder -> fieldBuilder.build()).collect(GuavaCollectors.toImmutableSet());
        }

        private boolean checkValid(final DocumentLayoutElementFieldDescriptor.Builder fieldBuilder) {
            if (fieldBuilder.isConsumed()) {
                logger.trace("Skip adding {} to {} because it's already consumed", fieldBuilder, this);
                return false;
            }

            if (!fieldBuilder.isPublicField()) {
                logger.trace("Skip adding {} to {} because it's not a public field", fieldBuilder, this);
                return false;
            }

            if (excludeSpecialFields && fieldBuilder.isSpecialFieldToExcludeFromLayout()) {
                logger.trace(
                        "Skip adding {} to {} because it's a special field and we were asked to exclude special fields",
                        fieldBuilder, this);
                return false;
            }

            return true;
        }

        public Builder setInternalName(final String internalName) {
            _internalName = internalName;
            return this;
        }

        private String getInternalName() {
            return _internalName;
        }

        public Builder setCaption(final ITranslatableString caption) {
            _caption = caption == null ? ImmutableTranslatableString.empty() : caption;
            return this;
        }

        public Builder setCaption(final String caption) {
            setCaption(ImmutableTranslatableString.constant(caption));
            return this;
        }

        public Builder setCaptionFromAD_Message(final String adMessage) {
            setCaption(Services.get(IMsgBL.class).translatable(adMessage));
            return this;
        }

        public Builder setCaptionNone() {
            setCaption(ImmutableTranslatableString.empty());
            return this;
        }

        private ITranslatableString getCaption() {
            if (_caption != null) {
                return _caption;
            }

            final DocumentLayoutElementFieldDescriptor.Builder firstField = getFirstField();
            if (firstField != null) {
                final String fieldName = firstField.getFieldName();
                return Services.get(IMsgBL.class).translatable(fieldName);
            }

            return ImmutableTranslatableString.empty();
        }

        public Builder setDescription(final ITranslatableString description) {
            _description = description == null ? ImmutableTranslatableString.empty() : description;
            return this;
        }

        private ITranslatableString getDescription() {
            if (_description != null) {
                return _description;
            }

            return ImmutableTranslatableString.empty();
        }

        public Builder setWidgetType(final DocumentFieldWidgetType widgetType) {
            _widgetType = widgetType;
            return this;
        }

        public boolean isWidgetTypeSet() {
            return _widgetType != null;
        }

        public boolean isWidgetSizeSet() {
            return _widgetSize != null;
        }

        public DocumentFieldWidgetType getWidgetType() {
            Check.assumeNotNull(_widgetType, DocumentLayoutBuildException.class,
                    "Parameter widgetType is not null for {}", this);
            return _widgetType;
        }

        public Builder restrictToMediaType(@NonNull final MediaType mediaType) {
            restrictToMediaTypes.add(mediaType);
            return this;
        }

        public Builder restrictToMediaTypes(@NonNull final Collection<MediaType> mediaTypes) {
            restrictToMediaTypes.addAll(mediaTypes);
            return this;
        }

        private ImmutableSet<MediaType> getRestrictToMediaTypes() {
            return ImmutableSet.copyOf(restrictToMediaTypes);
        }

        public Builder setAllowShowPassword(boolean allowShowPassword) {
            this._allowShowPassword = allowShowPassword;
            return this;
        }

        private boolean isAllowShowPassword() {
            return _allowShowPassword;
        }

        public Builder setMultilineText(boolean multilineText) {
            this._multilineText = multilineText;
            return this;
        }

        private boolean isMultilineText() {
            return _multilineText;
        }

        public Builder setMultilineTextLines(final int multilineTextLines) {
            this._multilineTextLines = multilineTextLines;
            return this;
        }

        private int getMultilineTextLines() {
            return _multilineTextLines;
        }

        public Builder setLayoutType(final LayoutType layoutType) {
            _layoutType = layoutType;
            return this;
        }

        public Builder setLayoutTypeNone() {
            _layoutType = null;
            return this;
        }

        private LayoutType getLayoutType() {
            return _layoutType;
        }

        public Builder setWidgetSize(final WidgetSize widgetSize) {
            _widgetSize = widgetSize;
            return this;
        }

        private WidgetSize getWidgetSize() {
            return _widgetSize;
        }

        public Builder setAdvancedField(final boolean advancedField) {
            _advancedField = advancedField;
            return this;
        }

        public boolean isAdvancedField() {
            return _advancedField;
        }

        public Builder removeFieldByFieldName(final String fieldName) {
            _fieldsBuilders.remove(fieldName);
            return this;
        }

        public Builder addField(@NonNull final DocumentLayoutElementFieldDescriptor.Builder fieldBuilder) {
            final DocumentLayoutElementFieldDescriptor.Builder previousFieldBuilder = _fieldsBuilders
                    .put(fieldBuilder.getFieldName(), fieldBuilder);
            if (previousFieldBuilder != null) {
                new AdempiereException(
                        "Field " + fieldBuilder.getFieldName() + " already exists in element: " + this)
                                .throwIfDeveloperModeOrLogWarningElse(logger);
            }
            return this;
        }

        public Set<String> getFieldNames() {
            return _fieldsBuilders.keySet();
        }

        public DocumentLayoutElementFieldDescriptor.Builder getField(final String fieldName) {
            return _fieldsBuilders.get(fieldName);
        }

        public DocumentLayoutElementFieldDescriptor.Builder getFirstField() {
            return _fieldsBuilders.values().iterator().next();
        }

        public int getFieldsCount() {
            return _fieldsBuilders.size();
        }

        public boolean hasFieldName(final String fieldName) {
            return _fieldsBuilders.containsKey(fieldName);
        }

        public Builder setExcludeSpecialFields() {
            excludeSpecialFields = true;
            return this;
        }

        private Builder setConsumed() {
            consumed = true;
            return this;
        }

        public boolean isConsumed() {
            return consumed;
        }

        public boolean isGridElement() {
            return _gridElement;
        }

        /**
         * Flags this element as a "grid element".
         */
        public Builder setGridElement() {
            _gridElement = true;
            return this;
        }

        /**
         * Reset the "grid element" flag.
         *
         * NOTE: this is false by default, but the main purpose of this method is intention revealing.
         *
         * @see #setGridElement()
         */
        public Builder setNotGridElement() {
            _gridElement = false;
            return this;
        }

        private LayoutAlign getGridAlign() {
            return isGridElement() ? getWidgetType().getGridAlign() : null;
        }

        public Builder setViewEditorRenderMode(final ViewEditorRenderMode gridEditorRenderMode) {
            this.viewEditorRenderMode = gridEditorRenderMode;
            return this;
        }

        private ViewEditorRenderMode getViewEditorRenderMode() {
            return viewEditorRenderMode;
        }

        public Builder setViewAllowSorting(boolean viewAllowSorting) {
            this.viewAllowSorting = viewAllowSorting;
            return this;
        }

        private boolean isViewAllowSorting() {
            return viewAllowSorting;
        }

        public Builder setButtonActionDescriptor(final ButtonFieldActionDescriptor buttonActionDescriptor) {
            this.buttonActionDescriptor = buttonActionDescriptor;
            return this;
        }

        /* package */ ButtonFieldActionDescriptor getButtonActionDescriptor() {
            return buttonActionDescriptor;
        }
    }
}