001/*
002 * (C) Copyright 2006-2008 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 *     <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a>
016 *
017 * $Id: SuggestionActionsBean.java 59340 2008-12-12 14:07:40Z cbaican $
018 */
019
020package org.nuxeo.ecm.platform.ui.web.util;
021
022import static org.jboss.seam.ScopeType.EVENT;
023
024import java.io.Serializable;
025
026import javax.faces.component.EditableValueHolder;
027import javax.faces.component.UIComponent;
028import javax.faces.component.ValueHolder;
029import javax.faces.event.ActionEvent;
030
031import org.apache.commons.lang.StringUtils;
032import org.apache.commons.logging.Log;
033import org.apache.commons.logging.LogFactory;
034import org.jboss.seam.annotations.Name;
035import org.jboss.seam.annotations.Scope;
036import org.jboss.seam.annotations.web.RequestParameter;
037import org.nuxeo.ecm.platform.ui.web.component.list.UIEditableList;
038
039/**
040 * Suggestion actions helpers
041 *
042 * @author Anahide Tchertchian
043 * @since 5.2M4
044 */
045@Name("suggestionActions")
046@Scope(EVENT)
047public class SuggestionActionsBean implements Serializable {
048
049    private static final long serialVersionUID = 1L;
050
051    private static final Log log = LogFactory.getLog(SuggestionActionsBean.class);
052
053    /**
054     * Id of the input selector
055     * <p>
056     * Component must be an instance of {@link ValueHolder}
057     */
058    @RequestParameter
059    protected String suggestionInputSelectorId;
060
061    /**
062     * Id of the editable list component where selection ids are put.
063     * <p>
064     * Component must be an instance of {@link UIEditableList}
065     */
066    @RequestParameter
067    protected String suggestionSelectionListId;
068
069    /**
070     * Id of the output component where single selection is displayed
071     * <p>
072     * Component must be an instance of {@link ValueHolder}
073     */
074    @RequestParameter
075    protected String suggestionSelectionOutputId;
076
077    /**
078     * Id if the hidden component where single selection id is put
079     * <p>
080     * Component must be an instance of {@link EditableValueHolder}
081     */
082    @RequestParameter
083    protected String suggestionSelectionHiddenId;
084
085    /**
086     * Id of the delete component displayed next to single selection
087     * <p>
088     * Component must be an instance of {@link UIComponent}
089     */
090    @RequestParameter
091    protected String suggestionSelectionDeleteId;
092
093    protected String selectedValue;
094
095    public String getSelectedValue() {
096        return selectedValue;
097    }
098
099    public void setSelectedValue(String selectedValue) {
100        this.selectedValue = selectedValue;
101    }
102
103    /**
104     * Gets the base naming container from anchor.
105     * <p>
106     * Gets out of suggestion box as it's a naming container and we can't get components out of it with a relative path
107     * => take above first found container.
108     *
109     * @deprecated: use {@link ComponentUtils#getBase(UIComponent)} instead
110     */
111    @Deprecated
112    protected UIComponent getBase(UIComponent anchor) {
113        return ComponentUtils.getBase(anchor);
114    }
115
116    /**
117     * Adds selection from selector as a list element
118     * <p>
119     * Must pass request parameter "suggestionSelectionListId" holding the binding to model. Selection will be retrieved
120     * using the {@link #getSelectedValue()} method.
121     */
122    public void addBoundSelectionToList(ActionEvent event) {
123        UIComponent component = event.getComponent();
124        if (component == null) {
125            return;
126        }
127        UIComponent base = ComponentUtils.getBase(component);
128        UIEditableList list = ComponentUtils.getComponent(base, suggestionSelectionListId, UIEditableList.class);
129
130        if (list != null) {
131            // add selected value to the list
132            String selectedValue = getSelectedValue();
133            if (!StringUtils.isBlank(selectedValue)) {
134                list.addValue(selectedValue);
135            }
136        }
137    }
138
139    /**
140     * Adds selection from selector as a list element
141     * <p>
142     * Must pass request parameters "suggestionInputSelectorId" holding the value to pass to the binding component,
143     * "suggestionSelectionListId" holding the binding to model.
144     *
145     * @deprecated use {@link #addBoundSelectionToList(ActionEvent)} which retrieves selected value from bound method
146     *             instead of retrieving suggestion input.
147     */
148    @Deprecated
149    public void addSelectionToList(ActionEvent event) {
150        UIComponent component = event.getComponent();
151        if (component == null) {
152            return;
153        }
154        UIComponent base = ComponentUtils.getBase(component);
155        ValueHolder selector = ComponentUtils.getComponent(base, suggestionInputSelectorId, ValueHolder.class);
156        UIEditableList list = ComponentUtils.getComponent(base, suggestionSelectionListId, UIEditableList.class);
157
158        if (selector != null && list != null) {
159            // add selected value to the list
160            list.addValue(selector.getValue());
161        }
162    }
163
164    /**
165     * Adds selection from selector as single element
166     * <p>
167     * Must pass request parameters "suggestionSelectionOutputId" holding the value to show, and
168     * "suggestionSelectionHiddenId" holding the binding to model. Selection will be retrieved using the
169     * {@link #getSelectedValue()} method. Since 5.5, only one of these two parameters is required.
170     * <p>
171     * Additional optional request parameter "suggestionSelectionDeleteId" can be used to show an area where the "clear"
172     * button is shown.
173     */
174    public void addSingleBoundSelection(ActionEvent event) {
175        UIComponent component = event.getComponent();
176        if (component == null) {
177            return;
178        }
179        UIComponent base = ComponentUtils.getBase(component);
180        EditableValueHolder hiddenSelector = null;
181        if (suggestionSelectionHiddenId != null) {
182            hiddenSelector = ComponentUtils.getComponent(base, suggestionSelectionHiddenId, EditableValueHolder.class);
183        }
184        ValueHolder output = null;
185        if (suggestionSelectionOutputId != null) {
186            output = ComponentUtils.getComponent(base, suggestionSelectionOutputId, ValueHolder.class);
187        }
188
189        if (output != null || hiddenSelector != null) {
190            String selectedValue = getSelectedValue();
191            if (output != null) {
192                output.setValue(selectedValue);
193            }
194            if (hiddenSelector != null) {
195                hiddenSelector.setSubmittedValue(selectedValue);
196            }
197
198            // display delete component if needed
199            if (suggestionSelectionDeleteId != null) {
200                UIComponent deleteComponent = ComponentUtils.getComponent(base, suggestionSelectionDeleteId,
201                        UIComponent.class);
202                if (deleteComponent != null) {
203                    deleteComponent.setRendered(true);
204                }
205            }
206
207        }
208    }
209
210    /**
211     * Adds selection from selector as single element
212     * <p>
213     * Must pass request parameters "suggestionInputSelectorId" holding the value to pass to the binding component,
214     * "suggestionSelectionOutputId" holding the value to show, and "suggestionSelectionHiddenId" holding the binding to
215     * model.
216     * <p>
217     * Additional optional request parameter "suggestionSelectionDeleteId" can be used to show an area where the "clear"
218     * button is shown. *
219     *
220     * @deprecated use {@link #addBoundSelectionToList(ActionEvent)} which retrieves selected value from bound method
221     *             instead of retrieving suggestion input.
222     */
223    @Deprecated
224    public void addSingleSelection(ActionEvent event) {
225        UIComponent component = event.getComponent();
226        if (component == null) {
227            return;
228        }
229        UIComponent base = ComponentUtils.getBase(component);
230        ValueHolder selector = ComponentUtils.getComponent(base, suggestionInputSelectorId, ValueHolder.class);
231        EditableValueHolder hiddenSelector = ComponentUtils.getComponent(base, suggestionSelectionHiddenId,
232                EditableValueHolder.class);
233        ValueHolder output = ComponentUtils.getComponent(base, suggestionSelectionOutputId, ValueHolder.class);
234
235        if (selector != null && hiddenSelector != null && output != null) {
236            String selection = (String) selector.getValue();
237            output.setValue(selection);
238            hiddenSelector.setSubmittedValue(selection);
239
240            // display delete component if needed
241            if (suggestionSelectionDeleteId != null) {
242                UIComponent deleteComponent = ComponentUtils.getComponent(base, suggestionSelectionDeleteId,
243                        UIComponent.class);
244                if (deleteComponent != null) {
245                    deleteComponent.setRendered(true);
246                }
247            }
248
249        }
250    }
251
252    /**
253     * Clears single selection.
254     * <p>
255     * Must pass request parameters "suggestionSelectionOutputId" holding the value to show, and
256     * "suggestionSelectionHiddenId" holding the binding to model. Since 5.5, only one of these two parameters is
257     * required.
258     * <p>
259     * Additional optional request parameter "suggestionSelectionDeleteId" can be used to hide an area where the "clear"
260     * button is shown.
261     */
262    public void clearSingleSelection(ActionEvent event) {
263        UIComponent component = event.getComponent();
264        if (component == null) {
265            return;
266        }
267        UIComponent base = component;
268        EditableValueHolder hiddenSelector = null;
269        if (suggestionSelectionHiddenId != null) {
270            hiddenSelector = ComponentUtils.getComponent(base, suggestionSelectionHiddenId, EditableValueHolder.class);
271        }
272        ValueHolder output = null;
273        if (suggestionSelectionOutputId != null) {
274            output = ComponentUtils.getComponent(base, suggestionSelectionOutputId, ValueHolder.class);
275        }
276
277        if (output != null || hiddenSelector != null) {
278            if (output != null) {
279                output.setValue("");
280            }
281            if (hiddenSelector != null) {
282                hiddenSelector.setSubmittedValue("");
283            }
284
285            // hide delete component if needed
286            if (suggestionSelectionDeleteId != null) {
287                UIComponent deleteComponent = ComponentUtils.getComponent(base, suggestionSelectionDeleteId,
288                        UIComponent.class);
289                if (deleteComponent != null) {
290                    deleteComponent.setRendered(false);
291                }
292            }
293
294        }
295    }
296
297}