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