001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.ade.contenteditor;
029
030import org.opencms.main.OpenCms;
031import org.opencms.widgets.I_CmsComplexWidget;
032import org.opencms.widgets.I_CmsWidget;
033import org.opencms.xml.CmsXmlContentDefinition;
034import org.opencms.xml.CmsXmlUtils;
035import org.opencms.xml.content.I_CmsXmlContentHandler;
036import org.opencms.xml.content.I_CmsXmlContentHandler.DisplayType;
037import org.opencms.xml.types.I_CmsXmlContentValue;
038import org.opencms.xml.types.I_CmsXmlSchemaType;
039
040import java.util.ArrayList;
041import java.util.List;
042
043import org.apache.commons.collections4.CollectionUtils;
044
045/**
046 * Utility methods for getting widget informations out of content definitions.<p>
047 */
048public final class CmsWidgetUtil {
049
050    /**
051     * Bean representing widget information.<p>
052     */
053    public static class WidgetInfo {
054
055        /** The display type. */
056        private DisplayType m_displayType;
057
058        /** A widget instance. */
059        private I_CmsWidget m_widget;
060
061        /** The complex widget. */
062        private I_CmsComplexWidget m_complexWidget;
063
064        /**
065         * Gets the complex widget.<p>
066         *
067         * @return the complex widget
068         */
069        public I_CmsComplexWidget getComplexWidget() {
070
071            return m_complexWidget;
072        }
073
074        /**
075         * Gets the display type.<p>
076         *
077         * @return the display type
078         */
079        public DisplayType getDisplayType() {
080
081            return m_displayType;
082        }
083
084        /**
085         * Gets the widget instance.<p>
086         *
087         * @return the widget instance
088         */
089        public I_CmsWidget getWidget() {
090
091            return m_widget;
092        }
093
094        /**
095         * Sets the complex widget.<p>
096         *
097         * @param complexWidget the complex widget to set
098         */
099        public void setComplexWidget(I_CmsComplexWidget complexWidget) {
100
101            m_complexWidget = complexWidget;
102
103        }
104
105        /**
106         * Sets the display type.<p>
107         *
108         * @param displayType the display type
109         */
110        public void setDisplayType(DisplayType displayType) {
111
112            m_displayType = displayType;
113        }
114
115        /**
116         * Sets the widget.<p>
117         *
118         * @param widget the widget
119         */
120        public void setWidget(I_CmsWidget widget) {
121
122            m_widget = widget;
123        }
124    }
125
126    /**
127     * Hidden default constructor.
128     */
129    private CmsWidgetUtil() {
130        // hidden default constructor
131    }
132
133    /**
134     * Collects widget information for a given content definition and content value path.<p>
135     *
136     * @param rootContentDefinition the content definition
137     * @param path the path relative to the given content definition
138     *
139     * @return the widget information for the given path
140     */
141    public static WidgetInfo collectWidgetInfo(CmsXmlContentDefinition rootContentDefinition, String path) {
142
143        String widgetConfig = null;
144        DisplayType configuredType = DisplayType.none;
145        I_CmsXmlSchemaType schemaType = rootContentDefinition.getSchemaType(path);
146
147        I_CmsWidget widget = null;
148        I_CmsComplexWidget complexWidget = null;
149        I_CmsXmlContentHandler contentHandler = schemaType.getContentDefinition().getContentHandler();
150        final List<I_CmsWidget> configuredWidgets = new ArrayList<>();
151        final List<String> configuredWidgetConfigs = new ArrayList<>();
152        final List<DisplayType> configuredDisplayTypes = new ArrayList<>();
153        final List<I_CmsComplexWidget> configuredComplexWidgets = new ArrayList<>();
154
155        // Use lists to store found widget configurations, and then use the first elements of each list.
156        // Because we iterate from the top level schema down to the nested schema, configurations in higher level schemas
157        // will have precedence over those in lower level schemas for the same element.
158
159        rootContentDefinition.findSchemaTypesForPath(path, (nestedType, remainingPath) -> {
160            remainingPath = CmsXmlUtils.concatXpath(nestedType.getName(), remainingPath);
161            I_CmsXmlContentHandler handler = nestedType.getContentDefinition().getContentHandler();
162            CollectionUtils.addIgnoreNull(configuredWidgets, handler.getUnconfiguredWidget(remainingPath));
163            CollectionUtils.addIgnoreNull(configuredWidgetConfigs, handler.getConfiguration(remainingPath));
164            CollectionUtils.addIgnoreNull(
165                configuredDisplayTypes,
166                handler.getConfiguredDisplayType(remainingPath, null));
167            CollectionUtils.addIgnoreNull(
168                configuredComplexWidgets,
169                handler.getUnconfiguredComplexWidget(remainingPath));
170
171        });
172        if (!configuredWidgets.isEmpty()) {
173            widget = configuredWidgets.get(0).newInstance();
174        } else {
175            widget = OpenCms.getXmlContentTypeManager().getWidgetDefault(schemaType.getTypeName());
176        }
177        if (!configuredDisplayTypes.isEmpty()) {
178            configuredType = configuredDisplayTypes.get(0);
179        }
180        if (!configuredWidgetConfigs.isEmpty()) {
181            widgetConfig = configuredWidgetConfigs.get(0);
182        } else if (widget != null) {
183            widgetConfig = OpenCms.getXmlContentTypeManager().getWidgetDefaultConfiguration(widget);
184        }
185        if (widget != null) {
186            widget.setConfiguration(widgetConfig);
187        }
188        // default complex widget and default c. widget config have lower priorities than those directly defined, so put them at the end of the list
189        CollectionUtils.addIgnoreNull(configuredComplexWidgets, contentHandler.getDefaultComplexWidget());
190        List<String> complexWidgetConfigs = new ArrayList<>(configuredWidgetConfigs);
191        CollectionUtils.addIgnoreNull(complexWidgetConfigs, contentHandler.getDefaultComplexWidgetConfiguration());
192        if (!configuredComplexWidgets.isEmpty()) {
193            String config = "";
194            if (!complexWidgetConfigs.isEmpty()) {
195                config = complexWidgetConfigs.get(0);
196            }
197            complexWidget = configuredComplexWidgets.get(0).configure(config);
198        }
199        WidgetInfo result = new WidgetInfo();
200        result.setComplexWidget(complexWidget);
201        result.setDisplayType(configuredType);
202        result.setWidget(widget);
203        return result;
204    }
205
206    /**
207     * Collects widget information for a given content value.<p>
208     *
209     * @param value a content value
210     *
211     * @return the widget information for the given value
212     */
213
214    public static WidgetInfo collectWidgetInfo(I_CmsXmlContentValue value) {
215
216        CmsXmlContentDefinition contentDef = value.getDocument().getContentDefinition();
217        String path = value.getPath();
218        return collectWidgetInfo(contentDef, path);
219    }
220
221}