KickJava   Java API By Example, From Geeks To Geeks.

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


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.HashMap JavaDoc;
29 import java.util.HashSet JavaDoc;
30 import java.util.Iterator JavaDoc;
31 import java.util.Map 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.Editor;
37 import org.riotfamily.forms.ElementFactory;
38 import org.riotfamily.forms.ErrorUtils;
39 import org.riotfamily.forms.TemplateUtils;
40 import org.riotfamily.forms.element.TemplateElement;
41 import org.riotfamily.forms.element.select.OptionsModel;
42 import org.riotfamily.forms.element.select.SelectElement;
43 import org.riotfamily.forms.event.Button;
44 import org.riotfamily.forms.event.ClickEvent;
45 import org.riotfamily.forms.event.ClickListener;
46 import org.springframework.beans.BeanUtils;
47 import org.springframework.util.Assert;
48
49
50 /**
51  * A list widget to edit maps.
52  */

53 public class MapEditor extends TemplateElement implements Editor {
54     
55     /** Class to use for newly created maps */
56     private Class JavaDoc mapClass = HashMap JavaDoc.class;
57     
58     private OptionsModel keyOptionsModel;
59     
60     private String JavaDoc labelProperty;
61     
62     private Container items = new Container();
63
64     private ElementFactory keyElementFactory;
65     
66     private Editor keyEditor;
67     
68     /** Factory to create elements for newly added items */
69     private ElementFactory itemElementFactory;
70     
71     
72     public MapEditor() {
73         addComponent("items", items);
74         setTemplate(TemplateUtils.getTemplatePath(MapEditor.class));
75     }
76     
77     public void setKeyOptionsModel(OptionsModel keyOptionsModel) {
78         this.keyOptionsModel = keyOptionsModel;
79     }
80
81     public void setLabelProperty(String JavaDoc labelProperty) {
82         this.labelProperty = labelProperty;
83     }
84     
85     /**
86      * Sets the factory that is used to create an element for each map key.
87      */

88     public void setKeyElementFactory(ElementFactory keyElementFactory) {
89         this.keyElementFactory = keyElementFactory;
90     }
91     
92     protected void initCompositeElement() {
93         if (keyElementFactory != null) {
94             keyEditor = (Editor) keyElementFactory.createElement(this, getForm());
95             keyEditor.setFieldName(getFieldName() + ".add");
96             if (keyEditor instanceof SelectElement) {
97                 SelectElement se = (SelectElement) keyEditor;
98                 se.setOptionsModel(new MapOptionsModel(se));
99             }
100             addComponent("keyEditor", keyEditor);
101             
102             Button addButton = new Button();
103             addButton.setLabelKey("label.form.map.add");
104             addButton.setLabel("Add");
105             addButton.setPartitialSubmit(getId());
106             addButton.addClickListener(new ClickListener() {
107                 public void clicked(ClickEvent event) {
108                     Object JavaDoc key = keyEditor.getValue();
109                     if (key == null) {
110                         ErrorUtils.reject(keyEditor, "map.emptyKey");
111                     }
112                     else if (getKeys().contains(key)) {
113                         ErrorUtils.reject(keyEditor, "map.duplicateKey");
114                     }
115                     else {
116                         addItem(key, null);
117                         keyEditor.setValue(null);
118                         getFormListener().elementChanged(keyEditor);
119                     }
120                 }
121             });
122             addComponent("addButton", addButton);
123         }
124     }
125     
126
127     /**
128      * Sets the class to use if a new map instance needs to be created.
129      * Default is <code>java.util.HashMap</code>.
130      *
131      * @param mapClass the class to use for new collections
132      */

133     public void setMapClass(Class JavaDoc mapClass) {
134         Assert.isAssignable(Map JavaDoc.class, mapClass);
135         this.mapClass = mapClass;
136     }
137     
138     /**
139      * Sets the factory that is used to create an element for each map value.
140      */

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

148     public void setValue(Object JavaDoc value) {
149         Map JavaDoc map = null;
150         if (value != null) {
151             Assert.isInstanceOf(Map JavaDoc.class, value, "Value must implement the Map interface");
152             map = (Map JavaDoc) value;
153         }
154         
155         Collection JavaDoc keys = null;
156         if (keyOptionsModel != null) {
157             keys = keyOptionsModel.getOptionValues();
158         }
159         else if (map != null) {
160             keys = map.keySet();
161         }
162         
163         if (keys != null) {
164             Iterator JavaDoc it = keys.iterator();
165             while (it.hasNext()) {
166                 Object JavaDoc key = it.next();
167                 Object JavaDoc obj = map != null ? map.get(key) : null;
168                 addItem(key, obj);
169             }
170         }
171     }
172     
173     public Object JavaDoc getValue() {
174         Map JavaDoc map = createOrClearMap();
175         Iterator JavaDoc it = items.getElements().iterator();
176         while (it.hasNext()) {
177             MapItem item = (MapItem) it.next();
178             map.put(item.getKey(), item.getValue());
179         }
180         return map;
181     }
182                 
183     private Map JavaDoc createOrClearMap() {
184         Map JavaDoc map = (Map JavaDoc) getEditorBinding().getValue();
185         if (map == null) {
186             map = (Map JavaDoc) BeanUtils.instantiateClass(mapClass);
187         }
188         else {
189             map.clear();
190         }
191         return map;
192     }
193
194     private Set JavaDoc getKeys() {
195         HashSet JavaDoc keys = new HashSet JavaDoc();
196         Iterator JavaDoc it = items.getElements().iterator();
197         while (it.hasNext()) {
198             MapItem item = (MapItem) it.next();
199             keys.add(item.getKey());
200         }
201         return keys;
202     }
203     
204     protected void addItem(Object JavaDoc key, Object JavaDoc value) {
205         MapItem item = new MapItem(key, keyEditor != null);
206         items.addElement(item);
207         item.focus();
208         item.setValue(value);
209     }
210     
211     protected void removeItem(MapItem item) {
212         items.removeElement(item);
213         if (keyEditor != null) {
214             ErrorUtils.removeErrors(keyEditor);
215             getFormListener().elementChanged(keyEditor);
216         }
217     }
218                     
219     public class MapItem extends TemplateElement {
220         
221         private Object JavaDoc key;
222         
223         private Editor element;
224         
225         private Button removeButton;
226         
227         public MapItem(Object JavaDoc key, boolean removable) {
228             super("item");
229             this.key = key;
230             setSurroundBySpan(false);
231             element = (Editor) itemElementFactory.createElement(this, getForm());
232             addComponent("element", element);
233             if (removable) {
234                 removeButton = new Button();
235                 removeButton.setLabelKey("label.form.map.remove");
236                 removeButton.setLabel("Remove");
237                 removeButton.setTabIndex(2);
238                 removeButton.addClickListener(new ClickListener() {
239                     public void clicked(ClickEvent event) {
240                         removeItem(MapItem.this);
241                     }
242                 });
243                 addComponent("removeButton", removeButton);
244             }
245         }
246         
247         public String JavaDoc getLabel() {
248             if (labelProperty != null) {
249                 return PropertyUtils.getPropertyAsString(key, labelProperty);
250             }
251             return String.valueOf(key);
252         }
253         
254         public Editor getElement() {
255             return element;
256         }
257         
258         public Object JavaDoc getKey() {
259             return this.key;
260         }
261         
262         public Object JavaDoc getValue() {
263             return element.getValue();
264         }
265         
266         public void setValue(Object JavaDoc value) {
267             element.setEditorBinding(new CollectionItemEditorBinding(element, value));
268             element.setValue(value);
269         }
270         
271         public void focus() {
272             element.focus();
273         }
274                 
275     }
276     
277     private class MapOptionsModel implements OptionsModel {
278         
279         private OptionsModel model;
280         
281         public MapOptionsModel(SelectElement keyElement) {
282             this.model = keyElement.getOptionsModel();
283         }
284
285         public Collection JavaDoc getOptionValues() {
286             Collection JavaDoc keys = getKeys();
287             ArrayList JavaDoc result = new ArrayList JavaDoc();
288             Iterator JavaDoc it = model.getOptionValues().iterator();
289             while (it.hasNext()) {
290                 Object JavaDoc key = (Object JavaDoc) it.next();
291                 if (!keys.contains(key)) {
292                     result.add(key);
293                 }
294             }
295             return result;
296         }
297     }
298 }
299
Popular Tags