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