KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > riotfamily > forms > element > collection > ListEditor


1 /* ***** BEGIN LICENSE BLOCK *****
2  * Version: MPL 1.1
3  * The contents of this file are subject to the Mozilla Public License Version
4  * 1.1 (the "License"); you may not use this file except in compliance with
5  * the License. You may obtain a copy of the License at
6  * http://www.mozilla.org/MPL/
7  *
8  * Software distributed under the License is distributed on an "AS IS" basis,
9  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
10  * for the specific language governing rights and limitations under the
11  * License.
12  *
13  * The Original Code is Riot.
14  *
15  * The Initial Developer of the Original Code is
16  * Neteye GmbH.
17  * Portions created by the Initial Developer are Copyright (C) 2006
18  * the Initial Developer. All Rights Reserved.
19  *
20  * Contributor(s):
21  * Felix Gnass [fgnass at neteye dot de]
22  *
23  * ***** END LICENSE BLOCK ***** */

24 package org.riotfamily.forms.element.collection;
25
26 import java.util.ArrayList JavaDoc;
27 import java.util.Collection JavaDoc;
28 import java.util.Collections JavaDoc;
29 import java.util.Comparator JavaDoc;
30 import java.util.HashSet JavaDoc;
31 import java.util.Iterator JavaDoc;
32 import java.util.Set JavaDoc;
33
34 import org.riotfamily.common.beans.PropertyUtils;
35 import org.riotfamily.forms.Container;
36 import org.riotfamily.forms.DHTMLElement;
37 import org.riotfamily.forms.Editor;
38 import org.riotfamily.forms.ElementFactory;
39 import org.riotfamily.forms.ErrorUtils;
40 import org.riotfamily.forms.TemplateUtils;
41 import org.riotfamily.forms.element.TemplateElement;
42 import org.riotfamily.forms.event.Button;
43 import org.riotfamily.forms.event.ClickEvent;
44 import org.riotfamily.forms.event.ClickListener;
45 import org.riotfamily.forms.request.FormRequest;
46 import org.riotfamily.forms.resource.FormResource;
47 import org.riotfamily.forms.resource.ResourceElement;
48 import org.riotfamily.forms.resource.Resources;
49 import org.springframework.beans.BeanUtils;
50 import org.springframework.util.StringUtils;
51
52
53 /**
54  * A list widget to edit lists and sets.
55  */

56 public class ListEditor extends TemplateElement implements Editor,
57         ResourceElement, DHTMLElement {
58         
59     /** Class to use for newly created collections */
60     private Class JavaDoc collectionClass;
61         
62     private String JavaDoc parentProperty;
63     
64     /** Factory to create elements for newly added items */
65     private ElementFactory itemElementFactory;
66     
67     /** Container of ListItems */
68     private Container items = new Container();
69     
70     /** Button to add an item to the list */
71     private Button addButton;
72         
73     private int minSize;
74     
75     private int maxSize;
76         
77     private boolean sortable;
78     
79     public ListEditor() {
80         addComponent("items", items);
81         addButton = new Button();
82         addButton.setLabelKey("label.form.list.add");
83         addButton.setLabel("Add");
84         addButton.addClickListener(new ClickListener() {
85             public void clicked(ClickEvent event) {
86                 addItem();
87             }
88         });
89         addComponent("addButton", addButton);
90         setTemplate(TemplateUtils.getTemplatePath(ListEditor.class));
91     }
92     
93     public void setSortable(boolean sortable) {
94         this.sortable = sortable;
95     }
96     
97     public boolean isSortable() {
98         return sortable;
99     }
100
101     public void setMinSize(int minSize) {
102         this.minSize = minSize;
103     }
104     
105     public void setMaxSize(int maxSize) {
106         this.maxSize = maxSize;
107     }
108     
109     public void setRequired(boolean required) {
110         minSize = required ? 1 : 0;
111     }
112     
113     public boolean isRequired() {
114         return minSize != 0;
115     }
116
117     public void setParentProperty(String JavaDoc parentProperty) {
118         this.parentProperty = parentProperty;
119     }
120
121     public FormResource getResource() {
122         return sortable ? Resources.SCRIPTACULOUS_DRAG_DROP : null;
123     }
124     
125     /**
126      * Sets the class to use if a new collection instance needs to be created.
127      * If no class is set, a suitable implementation will be selected according
128      * to the type of the property the element is bound to.
129      *
130      * @param collectionClass the class to use for new collections
131      */

132     public void setCollectionClass(Class JavaDoc collectionClass) {
133         this.collectionClass = collectionClass;
134     }
135     
136     /**
137      * Sets the factory that is used to create an element for each list item.
138      */

139     public void setItemElementFactory(ElementFactory itemElementFactory) {
140         this.itemElementFactory = itemElementFactory;
141     }
142     
143     /**
144      *
145      */

146     public void setValue(Object JavaDoc value) {
147         if (collectionClass == null) {
148             Class JavaDoc type = getEditorBinding().getPropertyType();
149             if (type.isInterface()) {
150                 if (Set JavaDoc.class.isAssignableFrom(type)) {
151                     collectionClass = HashSet JavaDoc.class;
152                 }
153                 else {
154                     collectionClass = ArrayList JavaDoc.class;
155                 }
156             }
157             else {
158                 collectionClass = type;
159             }
160         }
161         if (value != null) {
162             if (!(value instanceof Collection JavaDoc)) {
163                 throw new IllegalArgumentException JavaDoc("Value must implement " +
164                         "the java.util.Collection interface");
165             }
166             Collection JavaDoc collection = (Collection JavaDoc) value;
167             Iterator JavaDoc it = collection.iterator();
168             while (it.hasNext()) {
169                 ListItem item = addItem();
170                 item.setValue(it.next());
171             }
172         }
173     }
174     
175     public Object JavaDoc getValue() {
176         Collection JavaDoc collection = createOrClearCollection();
177         Iterator JavaDoc it = items.getElements().iterator();
178         while (it.hasNext()) {
179             ListItem item = (ListItem) it.next();
180             if (item.getElement().getValue() != null) {
181                 Object JavaDoc value = item.getElement().getValue();
182                 if (parentProperty != null) {
183                     PropertyUtils.setProperty(value, parentProperty,
184                             getEditorBinding().getEditorBinder().getBackingObject());
185                 }
186                 collection.add(value);
187             }
188         }
189         return collection;
190     }
191                 
192     private Collection JavaDoc createOrClearCollection() {
193         Collection JavaDoc collection = (Collection JavaDoc) getEditorBinding().getValue();
194         if (collection == null) {
195             collection = (Collection JavaDoc) BeanUtils.instantiateClass(collectionClass);
196         }
197         else {
198             collection.clear();
199         }
200         return collection;
201     }
202
203     protected ListItem addItem() {
204         ListItem item = new ListItem();
205         items.addElement(item);
206         item.focus();
207         
208         item.setValue(null);
209         
210         return item;
211     }
212     
213     protected void removeItem(ListItem item) {
214         items.removeElement(item);
215     }
216     
217     protected void validate() {
218         int size = ((Collection JavaDoc) getValue()).size();
219         if (minSize > 0 && size < minSize) {
220             ErrorUtils.reject(this, "list.size.tooSmall",
221                     new Object JavaDoc[] {new Integer JavaDoc(minSize)});
222         }
223         if (maxSize > 0 && size > maxSize) {
224             ErrorUtils.reject(this, "list.size.tooLarge",
225                     new Object JavaDoc[] {new Integer JavaDoc(maxSize)});
226         }
227     }
228     
229     public Container getItems() {
230         return this.items;
231     }
232     
233     public String JavaDoc getInitScript() {
234         if (sortable && !items.isEmpty()) {
235             return TemplateUtils.getInitScript(this);
236         }
237         else {
238             return null;
239         }
240     }
241         
242     protected void processRequestInternal(FormRequest request) {
243         if (sortable) {
244             String JavaDoc itemOrder = request.getParameter(getParamName());
245             if (StringUtils.hasLength(itemOrder)) {
246                 Collections.sort(items.getElements(),
247                         new ListItemComparator(itemOrder));
248             }
249         }
250     }
251     
252     public class ListItem extends TemplateElement implements DHTMLElement {
253         
254         private Editor element;
255         
256         private Button removeButton;
257                 
258         public ListItem() {
259             super("item");
260             setSurroundBySpan(false);
261             element = (Editor) itemElementFactory.createElement(this, getForm());
262             element.setRequired(true);
263             removeButton = new Button();
264             removeButton.setLabelKey("label.form.list.remove");
265             removeButton.setLabel("Remove");
266             removeButton.setTabIndex(2);
267             removeButton.addClickListener(new ClickListener() {
268                 public void clicked(ClickEvent event) {
269                     removeItem(ListItem.this);
270                 }
271             });
272             addComponent("element", element);
273             addComponent("removeButton", removeButton);
274         }
275         
276         public Editor getElement() {
277             return element;
278         }
279         
280         public void focus() {
281             element.focus();
282         }
283         
284         public boolean isShowDragHandle() {
285             return isSortable();
286         }
287         
288         public void setValue(Object JavaDoc value) {
289             element.setEditorBinding(new CollectionItemEditorBinding(element, value));
290             element.setValue(value);
291         }
292         
293         public String JavaDoc getInitScript() {
294             if (getForm().isRendering()) {
295                 return null;
296             }
297             return ListEditor.this.getInitScript();
298         }
299         
300     }
301     
302     private class ListItemComparator implements Comparator JavaDoc {
303
304         private String JavaDoc itemOrder;
305         
306         public ListItemComparator(String JavaDoc itemOrder) {
307             this.itemOrder = itemOrder;
308         }
309
310         public int compare(Object JavaDoc obj1, Object JavaDoc obj2) {
311             ListItem item1 = (ListItem) obj1;
312             ListItem item2 = (ListItem) obj2;
313             int pos1 = itemOrder.indexOf(item1.getId() + ',');
314             int pos2 = itemOrder.indexOf(item2.getId() + ',');
315             return pos1 - pos2;
316         }
317         
318     }
319 }
320
Popular Tags