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 buff = new StringBuilder();
057        if (defs != null) {
058            for (FieldDefinition def : defs) {
059                buff.append(def.getPropertyName()).append(" ");
060            }
061        }
062        return buff.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<LayoutRow>();
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<LayoutRow>();
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<String>();
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 = new Integer(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        StringBuffer builder = new StringBuffer();
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() + "(" + widget.getCategory() + ")").append(",");
167                }
168            }
169        }
170        builder.append(";");
171
172        Map<String, Map<String, Serializable>> properties = layoutRowDef.getProperties();
173        if (properties != null) {
174            builder.append(properties.toString());
175        }
176        builder.append(";");
177
178        Integer intValue = new Integer(builder.toString().hashCode());
179        return intValue.toString();
180
181    }
182
183    /**
184     * Returns an identifier computed from this definition so that an identical definition will have the same id.
185     *
186     * @since 5.5
187     */
188    public static String computeWidgetDefinitionId(WidgetDefinition widgetDef) {
189        StringBuffer builder = new StringBuffer();
190        builder.append(widgetDef.getName()).append(";");
191        builder.append(widgetDef.getType()).append(";");
192        builder.append(widgetDef.getTypeCategory()).append(";");
193
194        FieldDefinition[] fieldDefinitions = widgetDef.getFieldDefinitions();
195        if (fieldDefinitions != null) {
196            for (FieldDefinition fieldDef : fieldDefinitions) {
197                builder.append(fieldDef.getPropertyName() + ",");
198            }
199        }
200        builder.append(";");
201
202        Map<String, String> labels = widgetDef.getLabels();
203        if (labels != null) {
204            builder.append(labels.toString());
205        }
206        builder.append(";");
207        Map<String, String> helpLabels = widgetDef.getHelpLabels();
208        if (helpLabels != null) {
209            builder.append(helpLabels.toString());
210        }
211        builder.append(";");
212
213        WidgetDefinition[] subWidgets = widgetDef.getSubWidgetDefinitions();
214        if (subWidgets != null) {
215            for (WidgetDefinition widget : subWidgets) {
216                if (widget != null) {
217                    builder.append(computeWidgetDefinitionId(widget)).append(",");
218                }
219            }
220        }
221        builder.append(";");
222
223        WidgetReference[] subWidgetRefs = widgetDef.getSubWidgetReferences();
224        if (subWidgetRefs != null) {
225            for (WidgetReference widget : subWidgetRefs) {
226                if (widget != null) {
227                    builder.append(widget.getName() + "(" + widget.getCategory() + ")").append(",");
228                }
229            }
230        }
231        builder.append(";");
232
233        Map<String, Map<String, Serializable>> properties = widgetDef.getProperties();
234        if (properties != null) {
235            builder.append(properties.toString());
236        }
237        builder.append(";");
238        Map<String, Map<String, Serializable>> widgetModeProperties = widgetDef.getWidgetModeProperties();
239        if (widgetModeProperties != null) {
240            builder.append(widgetModeProperties.toString());
241        }
242        builder.append(";");
243
244        builder.append(widgetDef.isTranslated()).append(";");
245        builder.append(widgetDef.isHandlingLabels()).append(";");
246
247        Map<String, String> modes = widgetDef.getModes();
248        if (modes != null) {
249            builder.append(modes.toString());
250        }
251        builder.append(";");
252
253        WidgetSelectOption[] selectOptions = widgetDef.getSelectOptions();
254        if (selectOptions != null) {
255            for (WidgetSelectOption option : selectOptions) {
256                if (option != null) {
257                    builder.append(option.getTagConfigId()).append(",");
258                }
259            }
260        }
261        builder.append(";");
262
263        Map<String, Map<String, Serializable>> controls = widgetDef.getControls();
264        if (controls != null) {
265            builder.append(controls.toString());
266        }
267        builder.append(";");
268
269        Integer intValue = new Integer(builder.toString().hashCode());
270        return intValue.toString();
271    }
272
273    /**
274     * Sorter that re-arranges rows according to the row names order.
275     *
276     * @since 5.6
277     */
278    public static class LayoutRowsSorter implements Comparator<LayoutRow> {
279
280        protected List<String> orderedRowNames;
281
282        private LayoutRowsSorter(List<String> orderedRowNames) {
283            super();
284            this.orderedRowNames = orderedRowNames;
285        }
286
287        @Override
288        public int compare(LayoutRow o1, LayoutRow o2) {
289            if (orderedRowNames == null || orderedRowNames.size() == 0) {
290                return 0;
291            }
292            if (o1 == null && o2 == null) {
293                return 0;
294            }
295            if (o1 == null) {
296                return -1;
297            }
298            if (o2 == null) {
299                return 1;
300            }
301            String id1 = o1.getName();
302            String id2 = o2.getName();
303            if (id1 == null && id2 == null) {
304                return 0;
305            }
306            if (id1 == null) {
307                return -1;
308            }
309            if (id2 == null) {
310                return 1;
311            }
312            if (orderedRowNames.indexOf(id1) <= orderedRowNames.indexOf(id2)) {
313                return -1;
314            } else {
315                return 1;
316            }
317        }
318
319    }
320
321}