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