001/*
002 * (C) Copyright 2013 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 *     <a href="mailto:grenard@nuxeo.com">Guillaume</a>
018 */
019package org.nuxeo.ecm.platform.ui.select2.common;
020
021import java.util.ArrayList;
022import java.util.Arrays;
023import java.util.List;
024
025import net.sf.json.JSONArray;
026import net.sf.json.JSONObject;
027
028import org.apache.commons.lang.StringUtils;
029import org.apache.commons.logging.Log;
030import org.apache.commons.logging.LogFactory;
031import org.nuxeo.ecm.core.schema.types.Schema;
032import org.nuxeo.ecm.platform.usermanager.UserConfig;
033import org.nuxeo.runtime.api.Framework;
034import org.nuxeo.runtime.services.config.ConfigurationService;
035
036/**
037 * Group fields and methods used at initialization and runtime for select2 feature.
038 *
039 * @since 5.7.3
040 */
041public class Select2Common {
042
043    private static final Log log = LogFactory.getLog(Select2Common.class);
044
045    private static final String FORCE_DISPLAY_EMAIL_IN_SUGGESTION = "nuxeo.ui.displayEmailInUserSuggestion";
046
047    public static final String LANG_TOKEN = "{lang}";
048
049    public static final String DEFAULT_LANG = "en";
050
051    public static final String ID = "id";
052
053    public static final String LABEL = "displayLabel";
054
055    public static final String DIRECTORY_DEFAULT_LABEL_COL_NAME = "label";
056
057    public static final String PARENT_FIELD_ID = "parent";
058
059    public static final String PLACEHOLDER = "placeholder";
060
061    public static final String COMPUTED_ID = "computedId";
062
063    public static final String DEFAULT_KEY_SEPARATOR = "/";
064
065    public static final String OBSOLETE_FIELD_ID = "obsolete";
066
067    public static final List<String> SELECT2_USER_WIDGET_TYPE_LIST = new ArrayList<String>(Arrays.asList(
068            "singleUserSuggestion", "multipleUsersSuggestion"));
069
070    public static final List<String> SELECT2_DOC_WIDGET_TYPE_LIST = new ArrayList<String>(Arrays.asList(
071            "singleDocumentSuggestion", "multipleDocumentsSuggestion"));
072
073    public static final String USER_TYPE = "USER_TYPE";
074
075    public static final String GROUP_TYPE = "GROUP_TYPE";
076
077    public static final String TYPE_KEY_NAME = "type";
078
079    public static final String PREFIXED_ID_KEY_NAME = "prefixed_id";
080
081    public static final String SUGGESTION_FORMATTER = "suggestionFormatter";
082
083    public static final String SELECTION_FORMATTER = "selectionFormatter";
084
085    public static final String USER_DEFAULT_SUGGESTION_FORMATTER = "userEntryDefaultFormatter";
086
087    public static final String DOC_DEFAULT_SUGGESTION_FORMATTER = "docEntryDefaultFormatter";
088
089    public static final String WARN_MESSAGE_LABEL = "warn_message";
090
091    public static final List<String> SELECT2_DIR_WIDGET_TYPE_LIST = new ArrayList<String>(Arrays.asList(
092            "suggestOneDirectory", "suggestManyDirectory"));
093
094    public static final List<String> SELECT2_DEFAULT_DOCUMENT_SCHEMAS = new ArrayList<String>(Arrays.asList(
095            "dublincore", "common"));
096
097    public static final String DIR_DEFAULT_SUGGESTION_FORMATTER = "dirEntryDefaultFormatter";
098
099    public static final String READ_ONLY_PARAM = "readonly";
100
101    public static final String RERENDER_JS_FUNCTION_NAME = "reRenderFunctionName";
102
103    public static final String AJAX_RERENDER = "ajaxReRender";
104
105    public static final String USER_DEFAULT_SELECTION_FORMATTER = "userSelectionDefaultFormatter";
106
107    public static final String DOC_DEFAULT_SELECTION_FORMATTER = "docSelectionDefaultFormatter";
108
109    public static final String DIR_DEFAULT_SELECTION_FORMATTER = "dirSelectionDefaultFormatter";
110
111    public static final String WIDTH = "width";
112
113    public static final String DEFAULT_WIDTH = "300";
114
115    public static final String MIN_CHARS = "minChars";
116
117    public static final int DEFAULT_MIN_CHARS = 3;
118
119    public static final String TITLE = "title";
120
121    public static final String DISPLAY_ICON = "displayIcon";
122
123    public static final String OPERATION_ID = "operationId";
124
125    public static final String DIRECTORY_ORDER_FIELD_NAME = "ordering";
126
127    public static final String ABSOLUTE_LABEL = "absoluteLabel";
128
129    private static Boolean forceDisplayEmailInSuggestion = null;
130
131    public static final String ICON = "icon";
132
133    private static boolean isForceDisplayEmailInSuggestion() {
134        if (forceDisplayEmailInSuggestion == null) {
135            ConfigurationService cs = Framework.getService(ConfigurationService.class);
136            forceDisplayEmailInSuggestion = cs.isBooleanPropertyTrue(FORCE_DISPLAY_EMAIL_IN_SUGGESTION);
137        }
138        return forceDisplayEmailInSuggestion;
139    }
140
141    /**
142     * @since 5.9.3
143     */
144    public static String[] getDefaultSchemas() {
145        return getSchemas(null);
146    }
147
148    /**
149     * Compute the field name of the directory that holds the value that we want to display.
150     *
151     * @param schema the directory schema
152     * @param dbl10n are translations carried by directory fields
153     * @param labelFieldName the name or pattern of the fields that held values
154     * @param lang the current language
155     * @throws IllegalArgumentException when cannot compute label field name
156     * @return the final field name where we pick up the value
157     * @since 5.7.3
158     */
159    public static String getLabelFieldName(final Schema schema, boolean dbl10n, String labelFieldName, final String lang) {
160        if (labelFieldName == null || labelFieldName.isEmpty()) {
161            // No labelFieldName provided, we assume it is 'label'
162            labelFieldName = DIRECTORY_DEFAULT_LABEL_COL_NAME;
163        }
164        if (dbl10n) {
165            int i = labelFieldName.indexOf(LANG_TOKEN);
166            if (i >= 0) {
167                // a pattern is provided, let's compute the field name
168                // according
169                // to the current lang
170                StringBuffer buf = new StringBuffer();
171                buf.append(labelFieldName.substring(0, i));
172                buf.append(lang);
173                buf.append(labelFieldName.substring(i + LANG_TOKEN.length()));
174                String result = buf.toString();
175                if (schema.getField(result) != null) {
176                    return result;
177                } else {
178                    // there is no field for the current lang, let's pick
179                    // english by default
180                    buf = new StringBuffer();
181                    buf.append(labelFieldName.substring(0, i));
182                    buf.append(DEFAULT_LANG);
183                    buf.append(labelFieldName.substring(i + LANG_TOKEN.length()));
184                    return buf.toString();
185                }
186            } else {
187                // No pattern
188                String result = labelFieldName + "_" + lang;
189                if (schema.getField(result) != null) {
190                    // we assume that fields are named like 'xxx_en',
191                    // 'xxx_fr', etc.
192                    return result;
193                }
194
195                log.warn(String.format(
196                        "Unable to find field %s in directory schema %s. Trying to fallback on default one.",
197                        labelFieldName, schema.getName()));
198
199                result = DIRECTORY_DEFAULT_LABEL_COL_NAME + "_" + DEFAULT_LANG;
200                if (schema.getField(result) != null) {
201                    // no available locale, fallback to english by default
202                    return result;
203                }
204                result = DIRECTORY_DEFAULT_LABEL_COL_NAME;
205                if (schema.getField(result) != null) {
206                    // no available default locale, fallback to label
207                    return result;
208                }
209
210                if (schema.getField(labelFieldName) != null) {
211                    // let's pretend this is not dbl10n
212                    return labelFieldName;
213                }
214
215                throw new IllegalArgumentException(String.format("Unable to find field %s in directory schema %s",
216                        labelFieldName, schema.getName()));
217            }
218        } else {
219            if (schema.getField(labelFieldName) != null) {
220                return labelFieldName;
221            } else {
222                throw new IllegalArgumentException(String.format("Unable to find field %s in directory schema %s",
223                        labelFieldName, schema.getName()));
224            }
225        }
226    }
227
228    /**
229     * Returns an array containing the given schema names plus the default ones if not included
230     *
231     * @param schemaNames
232     * @since 5.8
233     */
234    public static String[] getSchemas(final String schemaNames) {
235        List<String> result = new ArrayList<String>();
236        result.addAll(Select2Common.SELECT2_DEFAULT_DOCUMENT_SCHEMAS);
237        String[] temp = null;
238        if (schemaNames != null && !schemaNames.isEmpty()) {
239            temp = schemaNames.split(",");
240        }
241        if (temp != null) {
242            for (String s : temp) {
243                result.add(s);
244            }
245        }
246        return result.toArray(new String[result.size()]);
247    }
248
249    public static void computeUserLabel(final JSONObject obj, final String firstLabelField,
250            final String secondLabelField, final String thirdLabelField, final boolean hideFirstLabel,
251            final boolean hideSecondLabel, final boolean hideThirdLabel, boolean displayEmailInSuggestion,
252            final String userId) {
253        String result = "";
254        if (obj != null) {
255
256            if (StringUtils.isNotBlank(firstLabelField) && !hideFirstLabel) {
257                // If firtLabelField given and first label not hidden
258                final String firstLabel = obj.optString(firstLabelField);
259                result += StringUtils.isNotBlank(firstLabel) ? firstLabel : "";
260            } else if (!hideFirstLabel) {
261                // Else we use firstname
262                final String firstname = obj.optString(UserConfig.FIRSTNAME_COLUMN);
263                result += StringUtils.isNotBlank(firstname) ? firstname : "";
264            }
265
266            if (StringUtils.isNotBlank(secondLabelField) && !hideSecondLabel) {
267                // If secondLabelField given and second label not hidden
268                final String secondLabel = obj.optString(firstLabelField);
269                if (StringUtils.isNotBlank(secondLabel)) {
270                    if (StringUtils.isNotBlank(result)) {
271                        result += " ";
272                    }
273                    result += secondLabel;
274                }
275            } else if (!hideSecondLabel) {
276                // Else we use lastname
277                final String lastname = obj.optString(UserConfig.LASTNAME_COLUMN);
278                if (StringUtils.isNotBlank(lastname)) {
279                    if (StringUtils.isNotBlank(result)) {
280                        result += " ";
281                    }
282                    result += lastname;
283                }
284            }
285            if (StringUtils.isBlank(result)) {
286                // At this point, if returned label is empty, we use user id
287                result += StringUtils.isNotBlank(userId) ? userId : "";
288            }
289
290            if (isForceDisplayEmailInSuggestion() || (displayEmailInSuggestion && !hideThirdLabel)) {
291                if (StringUtils.isNotBlank(thirdLabelField)) {
292                    final String thirdLabel = obj.optString(thirdLabelField);
293                    if (StringUtils.isNotBlank(thirdLabel)) {
294                        if (StringUtils.isNotBlank(result)) {
295                            result += " ";
296                        }
297                        result += thirdLabel;
298                    }
299                } else {
300                    // Else we use email
301                    String email = obj.optString(UserConfig.EMAIL_COLUMN);
302                    if (StringUtils.isNotBlank(email)) {
303                        if (StringUtils.isNotBlank(result)) {
304                            result += " ";
305                        }
306                        result += email;
307                    }
308                }
309            }
310
311            obj.put(LABEL, result);
312        }
313    }
314
315    public static void computeGroupLabel(final JSONObject obj, final String groupId, final String groupLabelField,
316            final boolean hideFirstLabel) {
317        String label = null;
318        if (hideFirstLabel) {
319            label = groupId;
320        } else {
321            String groupLabelValue = obj.optString(groupLabelField);
322            if (StringUtils.isNotBlank(groupLabelValue)) {
323                label = groupLabelValue;
324            } else {
325                label = groupId;
326            }
327        }
328        obj.put(LABEL, label);
329    }
330
331    public static void computeUserGroupIcon(final JSONObject obj, final boolean hideIcon) {
332        if (obj != null) {
333            if (!hideIcon) {
334                String userGroupType = obj.optString(TYPE_KEY_NAME);
335                obj.element(DISPLAY_ICON, StringUtils.isNotBlank(userGroupType)
336                        && (userGroupType.equals(USER_TYPE) || userGroupType.equals(GROUP_TYPE)));
337            }
338        }
339    }
340
341    /**
342     * @since 6.0
343     */
344    public static String resolveDefaultEntries(final List<String> list) {
345        if (list == null || list.isEmpty()) {
346            return "[]";
347        } else {
348            JSONArray result = new JSONArray();
349            for (String l : list) {
350                JSONObject obj = new JSONObject();
351                obj.element(Select2Common.ID, l);
352                obj.element(Select2Common.LABEL, l);
353                result.add(obj);
354            }
355            return result.toString();
356        }
357    }
358
359}