001/*
002 * (C) Copyright 2006-2007 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:at@nuxeo.com">Anahide Tchertchian</a>
018 *
019 * $Id: UIDirectorySelectItems.java 29556 2008-01-23 00:59:39Z jcarsique $
020 */
021
022package org.nuxeo.ecm.platform.ui.web.directory;
023
024import java.util.Collections;
025import java.util.List;
026import java.util.Locale;
027
028import javax.faces.context.FacesContext;
029import javax.faces.model.SelectItem;
030
031import org.apache.commons.lang.StringUtils;
032import org.apache.commons.logging.Log;
033import org.apache.commons.logging.LogFactory;
034import org.nuxeo.common.utils.i18n.I18NUtils;
035import org.nuxeo.ecm.core.api.DocumentModel;
036import org.nuxeo.ecm.core.api.model.PropertyNotFoundException;
037import org.nuxeo.ecm.platform.ui.web.component.UISelectItems;
038import org.nuxeo.ecm.platform.ui.web.util.ComponentUtils;
039
040/**
041 * Component that deals with a list of select items from a directory.
042 *
043 * @author <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a>
044 */
045public class UIDirectorySelectItems extends UISelectItems {
046
047    private static final Log log = LogFactory.getLog(UIDirectorySelectItems.class);
048
049    public static final String COMPONENT_TYPE = UIDirectorySelectItems.class.getName();
050
051    protected enum DirPropertyKeys {
052        directoryName, keySeparator, itemOrdering, allValues, notDisplayDefaultOption,
053        //
054        displayAll, displayObsoleteEntries, filter, localize, dbl10n;
055    }
056
057    // setters & getters
058
059    public Long getItemOrdering() {
060        return (Long) getStateHelper().eval(DirPropertyKeys.itemOrdering);
061    }
062
063    public void setItemOrdering(Long itemOrdering) {
064        getStateHelper().put(DirPropertyKeys.itemOrdering, itemOrdering);
065    }
066
067    public String getKeySeparator() {
068        return (String) getStateHelper().eval(DirPropertyKeys.keySeparator, ChainSelect.DEFAULT_KEY_SEPARATOR);
069    }
070
071    public void setKeySeparator(String keySeparator) {
072        getStateHelper().put(DirPropertyKeys.keySeparator, keySeparator);
073    }
074
075    public String getDirectoryName() {
076        return (String) getStateHelper().eval(DirPropertyKeys.directoryName);
077    }
078
079    public void setDirectoryName(String directoryName) {
080        getStateHelper().put(DirPropertyKeys.directoryName, directoryName);
081    }
082
083    public SelectItem[] getAllValues() {
084        return (SelectItem[]) getStateHelper().eval(DirPropertyKeys.allValues);
085    }
086
087    public void setAllValues(SelectItem[] allValues) {
088        getStateHelper().put(DirPropertyKeys.allValues, allValues);
089    }
090
091    @SuppressWarnings("boxing")
092    public boolean isDisplayAll() {
093        return (Boolean) getStateHelper().eval(DirPropertyKeys.displayAll, Boolean.TRUE);
094    }
095
096    @SuppressWarnings("boxing")
097    public void setDisplayAll(boolean displayAll) {
098        getStateHelper().put(DirPropertyKeys.displayAll, displayAll);
099    }
100
101    @SuppressWarnings("boxing")
102    public boolean isDisplayObsoleteEntries() {
103        return (Boolean) getStateHelper().eval(DirPropertyKeys.displayObsoleteEntries, Boolean.FALSE);
104    }
105
106    @SuppressWarnings("boxing")
107    public void setDisplayObsoleteEntries(boolean displayObsoleteEntries) {
108        getStateHelper().put(DirPropertyKeys.displayObsoleteEntries, displayObsoleteEntries);
109    }
110
111    public String getFilter() {
112        return (String) getStateHelper().eval(DirPropertyKeys.filter);
113    }
114
115    public void setFilter(String filter) {
116        getStateHelper().put(DirPropertyKeys.filter, filter);
117    }
118
119    public boolean isNotDisplayDefaultOption() {
120        return (Boolean) getStateHelper().eval(DirPropertyKeys.notDisplayDefaultOption, Boolean.TRUE);
121    }
122
123    public void setNotDisplayDefaultOption(boolean notDisplayDefaultOption) {
124        getStateHelper().put(DirPropertyKeys.notDisplayDefaultOption, notDisplayDefaultOption);
125    }
126
127    @Override
128    @SuppressWarnings("boxing")
129    public boolean isLocalize() {
130        return (Boolean) getStateHelper().eval(DirPropertyKeys.localize, Boolean.FALSE);
131    }
132
133    @Override
134    @SuppressWarnings("boxing")
135    public void setLocalize(boolean localize) {
136        getStateHelper().put(DirPropertyKeys.localize, localize);
137    }
138
139    @Override
140    @SuppressWarnings("boxing")
141    public boolean isdbl10n() {
142        return (Boolean) getStateHelper().eval(DirPropertyKeys.dbl10n, Boolean.FALSE);
143    }
144
145    @Override
146    @SuppressWarnings("boxing")
147    public void setdbl10n(boolean dbl10n) {
148        getStateHelper().put(DirPropertyKeys.dbl10n, dbl10n);
149    }
150
151    @Override
152    public Object getValue() {
153        DirectorySelectItemsFactory f = new DirectorySelectItemsFactory() {
154
155            @Override
156            protected String getVar() {
157                return UIDirectorySelectItems.this.getVar();
158            }
159
160            @Override
161            protected DirectorySelectItem createSelectItem(String label, Long ordering) {
162                return UIDirectorySelectItems.this.createSelectItem(label, ordering);
163            }
164
165            @Override
166            protected String getDirectoryName() {
167                return UIDirectorySelectItems.this.getDirectoryName();
168            }
169
170            @Override
171            protected boolean isDisplayObsoleteEntries() {
172                return UIDirectorySelectItems.this.isDisplayObsoleteEntries();
173            }
174
175            @Override
176            protected boolean isNotDisplayDefaultOption() {
177                return UIDirectorySelectItems.this.isNotDisplayDefaultOption();
178            }
179
180            @Override
181            protected String getFilter() {
182                return UIDirectorySelectItems.this.getFilter();
183            }
184
185            @Override
186            protected String[] retrieveSelectEntryId() {
187                return UIDirectorySelectItems.this.retrieveSelectEntryId();
188            }
189
190            @Override
191            protected Object retrieveItemLabel() {
192                return UIDirectorySelectItems.this.getItemLabel();
193            }
194
195            @Override
196            protected String retrieveLabelFromEntry(DocumentModel directoryEntry) {
197                return UIDirectorySelectItems.this.retrieveLabelFromEntry(directoryEntry);
198            }
199
200            @Override
201            protected Long retrieveOrderingFromEntry(DocumentModel directoryEntry) {
202                return UIDirectorySelectItems.this.retrieveOrderingFromEntry(directoryEntry);
203            }
204
205        };
206
207        List<DirectorySelectItem> items;
208        if (isDisplayAll()) {
209            items = f.createAllDirectorySelectItems();
210        } else {
211            Object value = getStateHelper().eval(PropertyKeys.value);
212            items = f.createDirectorySelectItems(value, getKeySeparator());
213        }
214
215        String ordering = getOrdering();
216        boolean caseSensitive = isCaseSensitive();
217        if (!StringUtils.isBlank(ordering)) {
218            Collections.sort(items, new DirectorySelectItemComparator(ordering, Boolean.valueOf(caseSensitive)));
219        }
220
221        if (!isNotDisplayDefaultOption()) {
222            String defaultLabel = ComponentUtils.translate(getFacesContext(), "label.vocabulary.selectValue");
223            DirectorySelectItem defaultValue = new DirectorySelectItem("", defaultLabel);
224            // If isNotDisplayDefault is put to false, add a default select item to the top of the list
225            items.add(0, defaultValue);
226        }
227
228        DirectorySelectItem[] res = items.toArray(new DirectorySelectItem[0]);
229        if (isDisplayAll()) {
230            setAllValues(res);
231        }
232        return res;
233
234    }
235
236    protected DirectorySelectItem createSelectItem(String label, Long ordering) {
237        if (!isItemRendered()) {
238            return null;
239        }
240        Object valueObject = getItemValue();
241        String value = valueObject == null ? null : valueObject.toString();
242        if (isDisplayIdAndLabel() && label != null) {
243            label = value + getDisplayIdAndLabelSeparator() + label;
244        }
245        // make sure label is never blank
246        if (StringUtils.isBlank(label)) {
247            label = value;
248        }
249        String labelPrefix = getItemLabelPrefix();
250        if (!StringUtils.isBlank(labelPrefix)) {
251            label = labelPrefix + getItemLabelPrefixSeparator() + label;
252        }
253        String labelSuffix = getItemLabelSuffix();
254        if (!StringUtils.isBlank(labelSuffix)) {
255            label = label + getItemLabelSuffixSeparator() + labelSuffix;
256        }
257        return new DirectorySelectItem(value, label, ordering == null ? 0L : ordering.longValue(), isItemDisabled(),
258                isItemEscaped());
259    }
260
261    protected String[] retrieveSelectEntryId() {
262        // assume option id and vocabulary entry id will match
263        Object itemValue = getItemValue();
264        String id = itemValue != null ? itemValue.toString() : null;
265        if (StringUtils.isBlank(id)) {
266            return null;
267        }
268        String keySeparator = getKeySeparator();
269        if (!StringUtils.isBlank(keySeparator)) {
270            String[] split = id.split(keySeparator);
271            return split;
272        }
273        return new String[] {id};
274    }
275
276    protected String retrieveLabelFromEntry(DocumentModel docEntry) {
277        if (docEntry == null) {
278            return null;
279        }
280        String schema = docEntry.getSchemas()[0];
281        // compute label
282        Object labelObject = getItemLabel();
283        String label = labelObject != null ? labelObject.toString() : null;
284        FacesContext ctx = FacesContext.getCurrentInstance();
285        Locale locale = ctx.getViewRoot().getLocale();
286        if (StringUtils.isBlank(label)) {
287            if (isLocalize() && isdbl10n()) {
288                // lookup label property, hardcode the "label_" prefix for
289                // now
290                String defaultPattern = "label_en";
291                String pattern = "label_" + locale.getLanguage();
292                try {
293                    label = (String) docEntry.getProperty(schema, pattern);
294                } catch (PropertyNotFoundException e) {
295                    // prop may not exist for current language
296                }
297                if (StringUtils.isBlank(label)) {
298                    label = (String) docEntry.getProperty(schema, defaultPattern);
299                }
300                if (StringUtils.isBlank(label)) {
301                    label = docEntry.getId();
302                    log.warn("Could not find label column for entry " + label + " (falling back on entry id)");
303                }
304            } else {
305                label = (String) docEntry.getProperties(schema).get("label");
306                if (isLocalize()) {
307                    label = translate(ctx, locale, label);
308                }
309            }
310        } else if (isLocalize()) {
311            label = translate(ctx, locale, label);
312        }
313        return label;
314    }
315
316    protected Long retrieveOrderingFromEntry(DocumentModel docEntry) {
317        Long ordering = getItemOrdering();
318        if (ordering != null) {
319            return ordering;
320        }
321        // fallback on default ordering key
322        if (docEntry == null) {
323            return null;
324        }
325        String schema = docEntry.getSchemas()[0];
326        try {
327            ordering = (Long) docEntry.getProperties(schema).get("ordering");
328        } catch (ClassCastException e) {
329            // nevermind
330        }
331        return ordering;
332    }
333
334    @Override
335    protected String translate(FacesContext context, Locale locale, String label) {
336        if (StringUtils.isBlank(label)) {
337            return label;
338        }
339        String bundleName = context.getApplication().getMessageBundle();
340        label = I18NUtils.getMessageString(bundleName, label, null, locale);
341        return label;
342    }
343
344}