001/*
002 * (C) Copyright 2006-2007 Nuxeo SAS (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Nuxeo - initial API and implementation
016 *
017 * $Id: DirectoryAwareComponent.java 29914 2008-02-06 14:46:40Z atchertchian $
018 */
019
020package org.nuxeo.ecm.platform.ui.web.directory;
021
022import java.io.Serializable;
023import java.util.ArrayList;
024import java.util.Collections;
025import java.util.HashMap;
026import java.util.LinkedHashMap;
027import java.util.List;
028import java.util.Map;
029
030import javax.el.ELException;
031import javax.el.ValueExpression;
032import javax.faces.FacesException;
033import javax.faces.component.UIInput;
034import javax.faces.context.FacesContext;
035import javax.faces.model.SelectItem;
036
037import org.apache.commons.lang.StringUtils;
038
039/**
040 * Directory-aware abstract component.
041 *
042 * @author <a href="mailto:glefter@nuxeo.com">George Lefter</a>
043 * @author <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a>
044 */
045public abstract class DirectoryAwareComponent extends UIInput {
046
047    protected String directoryName;
048
049    protected Map<String, SelectItem> options;
050
051    protected Boolean displayIdAndLabel;
052
053    protected Boolean displayObsoleteEntries;
054
055    protected Boolean localize;
056
057    protected Boolean notDisplayDefaultOption;
058
059    protected Boolean displayValueOnly;
060
061    protected String displayValueOnlyStyle;
062
063    protected String displayValueOnlyStyleClass;
064
065    /**
066     * This field is used to specify what to display from the entry of a directory,the id, label or both of them.
067     */
068    protected String display;
069
070    protected String onchange;
071
072    protected String onclick;
073
074    protected String onselect;
075
076    protected String filter;
077
078    protected String size;
079
080    protected String ordering;
081
082    protected VocabularyEntryList directoryValues;
083
084    protected Boolean caseSensitive;
085
086    protected String getStringValue(String name, String defaultValue) {
087        ValueExpression ve = getValueExpression(name);
088        if (ve != null) {
089            try {
090                return (String) ve.getValue(getFacesContext().getELContext());
091            } catch (ELException e) {
092                throw new FacesException(e);
093            }
094        } else {
095            return defaultValue;
096        }
097    }
098
099    protected Boolean getBooleanValue(String name, boolean defaultValue) {
100        ValueExpression ve = getValueExpression(name);
101        if (ve != null) {
102            try {
103                return !Boolean.FALSE.equals(ve.getValue(getFacesContext().getELContext()));
104            } catch (ELException e) {
105                throw new FacesException(e);
106            }
107        } else {
108            return defaultValue;
109        }
110    }
111
112    public String getDirectoryName() {
113        if (directoryName != null) {
114            return directoryName;
115        }
116        return getStringValue("directoryName", null);
117    }
118
119    public void setDirectoryName(String directoryName) {
120        this.directoryName = directoryName;
121    }
122
123    public Boolean getDisplayIdAndLabel() {
124        if (displayIdAndLabel != null) {
125            return displayIdAndLabel;
126        }
127        return getBooleanValue("displayIdAndLabel", false);
128    }
129
130    public void setDisplayIdAndLabel(Boolean displayIdAndLabel) {
131        this.displayIdAndLabel = displayIdAndLabel;
132    }
133
134    public Boolean getLocalize() {
135        if (localize != null) {
136            return localize;
137        }
138        return getBooleanValue("localize", false);
139    }
140
141    public void setLocalize(Boolean localize) {
142        this.localize = localize;
143    }
144
145    public Boolean getCaseSensitive() {
146        if (caseSensitive != null) {
147            return caseSensitive;
148        }
149        return getBooleanValue("caseSensitive", false);
150    }
151
152    public void setCaseSensitive(Boolean caseSensitive) {
153        this.caseSensitive = caseSensitive;
154    }
155
156    public Map<String, SelectItem> getOptions() {
157        // rebuild systematically since a single component may be rendered
158        // several times in the same page for different directories
159        VocabularyEntryList directoryValues = getDirectoryValues();
160        String directoryName = getDirectoryName();
161
162        options = new LinkedHashMap<String, SelectItem>();
163        if (StringUtils.isEmpty(directoryName) && directoryValues == null) {
164            return options;
165            // throw new RuntimeException("directoryName and directoryValues
166            // cannot be both null");
167        }
168
169        Map<String, Serializable> filter = new HashMap<String, Serializable>();
170        String parentFilter = getFilter();
171        if (parentFilter != null) {
172            filter.put("parent", parentFilter);
173        }
174        if (!getDisplayObsoleteEntries()) {
175            filter.put("obsolete", 0);
176        }
177
178        List<DirectorySelectItem> optionList;
179        if (!StringUtils.isEmpty(directoryName)) {
180            optionList = DirectoryHelper.instance().getSelectItems(directoryName, filter, getLocalize());
181        } else if (directoryValues != null) {
182            optionList = DirectoryHelper.getSelectItems(directoryValues, filter, getLocalize());
183        } else {
184            optionList = new ArrayList<DirectorySelectItem>();
185        }
186        String ordering = getOrdering();
187        Boolean caseSensitive = getCaseSensitive();
188        if (ordering != null && !"".equals(ordering)) {
189            Collections.sort(optionList, new DirectorySelectItemComparator(ordering, caseSensitive));
190        }
191
192        for (DirectorySelectItem item : optionList) {
193            options.put((String) item.getValue(), item);
194        }
195
196        return options;
197    }
198
199    public void setOptions(Map<String, SelectItem> options) {
200        this.options = options;
201    }
202
203    public Boolean getDisplayObsoleteEntries() {
204        if (displayObsoleteEntries != null) {
205            return displayObsoleteEntries;
206        }
207        return getBooleanValue("displayObsoleteEntries", false);
208    }
209
210    public void setDisplayObsoleteEntries(Boolean displayObsoleteEntries) {
211        this.displayObsoleteEntries = displayObsoleteEntries;
212    }
213
214    public Boolean getNotDisplayDefaultOption() {
215        if (notDisplayDefaultOption != null) {
216            return notDisplayDefaultOption;
217        }
218        return getBooleanValue("notDisplayDefaultOption", false);
219    }
220
221    public void setNotDisplayDefaultOption(Boolean notDisplayDefaultOption) {
222        this.notDisplayDefaultOption = notDisplayDefaultOption;
223    }
224
225    public Boolean getDisplayValueOnly() {
226        if (displayValueOnly != null) {
227            return displayValueOnly;
228        }
229        return getBooleanValue("displayValueOnly", false);
230    }
231
232    public void setDisplayValueOnly(Boolean displayValueOnly) {
233        this.displayValueOnly = displayValueOnly;
234    }
235
236    public String getDisplayValueOnlyStyle() {
237        if (displayValueOnlyStyle != null) {
238            return displayValueOnlyStyle;
239        }
240        return getStringValue("displayValueOnlyStyle", null);
241    }
242
243    public void setDisplayValueOnlyStyle(String displayValueOnlyStyle) {
244        this.displayValueOnlyStyle = displayValueOnlyStyle;
245    }
246
247    public String getDisplayValueOnlyStyleClass() {
248        if (displayValueOnlyStyleClass != null) {
249            return displayValueOnlyStyleClass;
250        }
251        return getStringValue("displayValueOnlyStyleClass", null);
252    }
253
254    public void setDisplayValueOnlyStyleClass(String displayValueOnlyStyleClass) {
255        this.displayValueOnlyStyleClass = displayValueOnlyStyleClass;
256    }
257
258    public String getDisplay() {
259        if (display != null) {
260            return display;
261        }
262        return getStringValue("display", null);
263    }
264
265    public void setDisplay(String display) {
266        this.display = display;
267    }
268
269    public String getOnchange() {
270        if (onchange != null) {
271            return onchange;
272        }
273        return getStringValue("onchange", null);
274    }
275
276    public void setOnchange(String onchange) {
277        this.onchange = onchange;
278    }
279
280    public String getOnclick() {
281        if (onclick != null) {
282            return onclick;
283        }
284        return getStringValue("onclick", null);
285    }
286
287    public void setOnclick(String onclick) {
288        this.onclick = onclick;
289    }
290
291    public String getOnselect() {
292        if (onselect != null) {
293            return onselect;
294        }
295        return getStringValue("onselect", null);
296    }
297
298    public void setOnselect(String onselect) {
299        this.onselect = onselect;
300    }
301
302    public String getFilter() {
303        if (filter != null) {
304            return filter;
305        }
306        return getStringValue("filter", null);
307    }
308
309    public void setFilter(String filter) {
310        this.filter = filter;
311    }
312
313    public String getSize() {
314        if (size != null) {
315            return size;
316        }
317        return getStringValue("size", null);
318    }
319
320    public void setSize(String size) {
321        this.size = size;
322    }
323
324    public String getOrdering() {
325        if (ordering != null) {
326            return ordering;
327        }
328        return getStringValue("ordering", "label");
329    }
330
331    public void setOrdering(String ordering) {
332        this.ordering = ordering;
333    }
334
335    public VocabularyEntryList getDirectoryValues() {
336        ValueExpression ve = getValueExpression("directoryValues");
337        if (ve != null) {
338            try {
339                return (VocabularyEntryList) ve.getValue(getFacesContext().getELContext());
340            } catch (ELException e) {
341                throw new FacesException(e);
342            }
343        } else {
344            // default value
345            return null;
346        }
347    }
348
349    public void setDirectoryValues(VocabularyEntryList directoryValues) {
350        this.directoryValues = directoryValues;
351    }
352
353    @Override
354    public Object saveState(FacesContext context) {
355        Object[] values = new Object[19];
356        values[0] = super.saveState(context);
357        values[1] = directoryName;
358        values[2] = options;
359        values[3] = displayIdAndLabel;
360        values[4] = displayObsoleteEntries;
361        values[5] = localize;
362        values[6] = notDisplayDefaultOption;
363        values[7] = displayValueOnly;
364        values[8] = displayValueOnlyStyle;
365        values[9] = displayValueOnlyStyleClass;
366        values[10] = display;
367        values[11] = onchange;
368        values[12] = filter;
369        values[13] = size;
370        values[14] = ordering;
371        values[15] = directoryValues;
372        values[16] = caseSensitive;
373        values[17] = onclick;
374        values[18] = onselect;
375        return values;
376    }
377
378    @SuppressWarnings("unchecked")
379    @Override
380    public void restoreState(FacesContext context, Object state) {
381        Object[] values = (Object[]) state;
382        super.restoreState(context, values[0]);
383        directoryName = (String) values[1];
384        options = (Map<String, SelectItem>) values[2];
385        displayIdAndLabel = (Boolean) values[3];
386        displayObsoleteEntries = (Boolean) values[4];
387        localize = (Boolean) values[5];
388        notDisplayDefaultOption = (Boolean) values[6];
389        displayValueOnly = (Boolean) values[7];
390        displayValueOnlyStyle = (String) values[8];
391        displayValueOnlyStyleClass = (String) values[9];
392        display = (String) values[10];
393        onchange = (String) values[11];
394        filter = (String) values[12];
395        size = (String) values[13];
396        ordering = (String) values[14];
397        directoryValues = (VocabularyEntryList) values[15];
398        caseSensitive = (Boolean) values[16];
399        onclick = (String) values[17];
400        onselect = (String) values[18];
401    }
402
403    public Boolean getBooleanProperty(String key, Boolean defaultValue) {
404        Map<String, Object> map = getAttributes();
405        Boolean value = (Boolean) map.get(key);
406        if (value == null) {
407            value = defaultValue;
408        }
409        return value;
410    }
411
412    public String getStringProperty(String key, String defaultValue) {
413        Map<String, Object> map = getAttributes();
414        String value = (String) map.get(key);
415        if (value == null) {
416            value = defaultValue;
417        }
418        return value;
419    }
420
421}