001/*
002 * (C) Copyright 2011 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Anahide Tchertchian
018 */
019package org.nuxeo.ecm.platform.forms.layout.functions;
020
021import java.io.Serializable;
022import java.util.ArrayList;
023import java.util.Collections;
024import java.util.Comparator;
025import java.util.List;
026import java.util.Map;
027
028import org.nuxeo.ecm.platform.forms.layout.api.FieldDefinition;
029import org.nuxeo.ecm.platform.forms.layout.api.Layout;
030import org.nuxeo.ecm.platform.forms.layout.api.LayoutDefinition;
031import org.nuxeo.ecm.platform.forms.layout.api.LayoutRow;
032import org.nuxeo.ecm.platform.forms.layout.api.LayoutRowDefinition;
033import org.nuxeo.ecm.platform.forms.layout.api.WidgetDefinition;
034import org.nuxeo.ecm.platform.forms.layout.api.WidgetReference;
035import org.nuxeo.ecm.platform.forms.layout.api.WidgetSelectOption;
036import org.nuxeo.ecm.platform.forms.layout.api.WidgetTypeDefinition;
037import org.nuxeo.ecm.platform.forms.layout.api.service.LayoutStore;
038import org.nuxeo.runtime.api.Framework;
039
040/**
041 * Provides helper methods, declared as static, to be used by the rendering framework.
042 *
043 * @since 5.5
044 */
045public class LayoutFunctions {
046
047    public static WidgetTypeDefinition getWidgetTypeDefinition(String category, String typeName) {
048        LayoutStore layoutService = Framework.getService(LayoutStore.class);
049        return layoutService.getWidgetTypeDefinition(category, typeName);
050    }
051
052    /**
053     * Returns a String representing each of the field definitions property name, separated by a space.
054     */
055    public static String getFieldDefinitionsAsString(FieldDefinition[] defs) {
056        StringBuilder sb = new StringBuilder();
057        if (defs != null) {
058            for (FieldDefinition def : defs) {
059                sb.append(def.getPropertyName()).append(" ");
060            }
061        }
062        return sb.toString().trim();
063    }
064
065    public static List<LayoutRow> getSelectedRows(Layout layout, List<String> selectedRowNames,
066            boolean showAlwaysSelected) {
067        LayoutRow[] rows = layout.getRows();
068        List<LayoutRow> selectedRows = new ArrayList<>();
069        if (rows != null) {
070            for (LayoutRow row : rows) {
071                if (row.isAlwaysSelected() && showAlwaysSelected) {
072                    selectedRows.add(row);
073                } else if (selectedRowNames == null && row.isSelectedByDefault() && !row.isAlwaysSelected()) {
074                    selectedRows.add(row);
075                } else if (selectedRowNames != null && selectedRowNames.contains(row.getName())) {
076                    selectedRows.add(row);
077                }
078            }
079        }
080        // preserve selected rows order
081        Collections.sort(selectedRows, new LayoutRowsSorter(selectedRowNames));
082        return selectedRows;
083    }
084
085    public static List<LayoutRow> getNotSelectedRows(Layout layout, List<String> selectedRowNames) {
086        LayoutRow[] rows = layout.getRows();
087        List<LayoutRow> notSelectedRows = new ArrayList<>();
088        if (rows != null) {
089            for (LayoutRow row : rows) {
090                if (selectedRowNames == null && !row.isSelectedByDefault() && !row.isAlwaysSelected()) {
091                    notSelectedRows.add(row);
092                } else if (selectedRowNames != null && !row.isAlwaysSelected()
093                        && !selectedRowNames.contains(row.getName())) {
094                    notSelectedRows.add(row);
095                }
096            }
097        }
098        return notSelectedRows;
099    }
100
101    public static List<String> getDefaultSelectedRowNames(Layout layout, boolean showAlwaysSelected) {
102        List<LayoutRow> selectedRows = getSelectedRows(layout, null, showAlwaysSelected);
103        List<String> selectedRowNames = null;
104        if (selectedRows != null && !selectedRows.isEmpty()) {
105            selectedRowNames = new ArrayList<>();
106            for (LayoutRow row : selectedRows) {
107                selectedRowNames.add(row.getName());
108            }
109        }
110        return selectedRowNames;
111    }
112
113    /**
114     * Returns an identifier computed from this definition so that an identical definition will have the same id.
115     *
116     * @since 5.5
117     */
118    public static String computeLayoutDefinitionId(LayoutDefinition layoutDef) {
119        StringBuilder builder = new StringBuilder();
120        builder.append(layoutDef.getName()).append(";");
121        Map<String, String> templates = layoutDef.getTemplates();
122        if (templates != null) {
123            builder.append(templates.toString());
124        }
125        builder.append(";");
126        LayoutRowDefinition[] rows = layoutDef.getRows();
127        if (rows != null) {
128            for (LayoutRowDefinition row : rows) {
129                if (row != null) {
130                    builder.append(computeLayoutRowDefinitionId(row)).append(",");
131                }
132            }
133        }
134        builder.append(";");
135        Map<String, Map<String, Serializable>> properties = layoutDef.getProperties();
136        if (properties != null) {
137            builder.append(properties.toString());
138        }
139        builder.append(";");
140        Map<String, WidgetDefinition> widgetDefs = layoutDef.getWidgetDefinitions();
141        if (widgetDefs != null) {
142            for (WidgetDefinition widgetDef : widgetDefs.values()) {
143                builder.append(computeWidgetDefinitionId(widgetDef)).append(",");
144            }
145        }
146        builder.append(";");
147
148        Integer intValue = Integer.valueOf(builder.toString().hashCode());
149        return intValue.toString();
150    }
151
152    /**
153     * Returns an identifier computed from this definition so that an identical definition will have the same id.
154     *
155     * @since 5.5
156     */
157    public static String computeLayoutRowDefinitionId(LayoutRowDefinition layoutRowDef) {
158        StringBuilder builder = new StringBuilder();
159        builder.append(layoutRowDef.getName()).append(";");
160        builder.append(layoutRowDef.isSelectedByDefault()).append(";");
161        builder.append(layoutRowDef.isAlwaysSelected()).append(";");
162        WidgetReference[] widgets = layoutRowDef.getWidgetReferences();
163        if (widgets != null) {
164            for (WidgetReference widget : widgets) {
165                if (widget != null) {
166                    builder.append(widget.getName())
167                           .append("(")
168                           .append(widget.getCategory())
169                           .append(")")
170                           .append(",");
171                }
172            }
173        }
174        builder.append(";");
175
176        Map<String, Map<String, Serializable>> properties = layoutRowDef.getProperties();
177        if (properties != null) {
178            builder.append(properties.toString());
179        }
180        builder.append(";");
181
182        Integer intValue = Integer.valueOf(builder.toString().hashCode());
183        return intValue.toString();
184
185    }
186
187    /**
188     * Returns an identifier computed from this definition so that an identical definition will have the same id.
189     *
190     * @since 5.5
191     */
192    public static String computeWidgetDefinitionId(WidgetDefinition widgetDef) {
193        StringBuilder builder = new StringBuilder();
194        builder.append(widgetDef.getName()).append(";");
195        builder.append(widgetDef.getType()).append(";");
196        builder.append(widgetDef.getTypeCategory()).append(";");
197
198        FieldDefinition[] fieldDefinitions = widgetDef.getFieldDefinitions();
199        if (fieldDefinitions != null) {
200            for (FieldDefinition fieldDef : fieldDefinitions) {
201                builder.append(fieldDef.getPropertyName()).append(",");
202            }
203        }
204        builder.append(";");
205
206        Map<String, String> labels = widgetDef.getLabels();
207        if (labels != null) {
208            builder.append(labels.toString());
209        }
210        builder.append(";");
211        Map<String, String> helpLabels = widgetDef.getHelpLabels();
212        if (helpLabels != null) {
213            builder.append(helpLabels.toString());
214        }
215        builder.append(";");
216
217        WidgetDefinition[] subWidgets = widgetDef.getSubWidgetDefinitions();
218        if (subWidgets != null) {
219            for (WidgetDefinition widget : subWidgets) {
220                if (widget != null) {
221                    builder.append(computeWidgetDefinitionId(widget)).append(",");
222                }
223            }
224        }
225        builder.append(";");
226
227        WidgetReference[] subWidgetRefs = widgetDef.getSubWidgetReferences();
228        if (subWidgetRefs != null) {
229            for (WidgetReference widget : subWidgetRefs) {
230                if (widget != null) {
231                    builder.append(widget.getName()).append("(").append(widget.getCategory()).append(")").append(",");
232                }
233            }
234        }
235        builder.append(";");
236
237        Map<String, Map<String, Serializable>> properties = widgetDef.getProperties();
238        if (properties != null) {
239            builder.append(properties.toString());
240        }
241        builder.append(";");
242        Map<String, Map<String, Serializable>> widgetModeProperties = widgetDef.getWidgetModeProperties();
243        if (widgetModeProperties != null) {
244            builder.append(widgetModeProperties.toString());
245        }
246        builder.append(";");
247
248        builder.append(widgetDef.isTranslated()).append(";");
249        builder.append(widgetDef.isHandlingLabels()).append(";");
250
251        Map<String, String> modes = widgetDef.getModes();
252        if (modes != null) {
253            builder.append(modes.toString());
254        }
255        builder.append(";");
256
257        WidgetSelectOption[] selectOptions = widgetDef.getSelectOptions();
258        if (selectOptions != null) {
259            for (WidgetSelectOption option : selectOptions) {
260                if (option != null) {
261                    builder.append(option.getTagConfigId()).append(",");
262                }
263            }
264        }
265        builder.append(";");
266
267        Map<String, Map<String, Serializable>> controls = widgetDef.getControls();
268        if (controls != null) {
269            builder.append(controls.toString());
270        }
271        builder.append(";");
272
273        Integer intValue = Integer.valueOf(builder.toString().hashCode());
274        return intValue.toString();
275    }
276
277    /**
278     * Sorter that re-arranges rows according to the row names order.
279     *
280     * @since 5.6
281     */
282    public static class LayoutRowsSorter implements Comparator<LayoutRow> {
283
284        protected List<String> orderedRowNames;
285
286        private LayoutRowsSorter(List<String> orderedRowNames) {
287            super();
288            this.orderedRowNames = orderedRowNames;
289        }
290
291        @Override
292        public int compare(LayoutRow o1, LayoutRow o2) {
293            if (orderedRowNames == null || orderedRowNames.size() == 0) {
294                return 0;
295            }
296            if (o1 == null && o2 == null) {
297                return 0;
298            }
299            if (o1 == null) {
300                return -1;
301            }
302            if (o2 == null) {
303                return 1;
304            }
305            String id1 = o1.getName();
306            String id2 = o2.getName();
307            if (id1 == null && id2 == null) {
308                return 0;
309            }
310            if (id1 == null) {
311                return -1;
312            }
313            if (id2 == null) {
314                return 1;
315            }
316            if (orderedRowNames.indexOf(id1) <= orderedRowNames.indexOf(id2)) {
317                return -1;
318            } else {
319                return 1;
320            }
321        }
322
323    }
324
325}