| 1 24 package org.riotfamily.forms.element.collection; 25 26 import java.util.ArrayList ; 27 import java.util.Collection ; 28 import java.util.HashMap ; 29 import java.util.HashSet ; 30 import java.util.Iterator ; 31 import java.util.Map ; 32 import java.util.Set ; 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 53 public class MapEditor extends TemplateElement implements Editor { 54 55 56 private Class mapClass = HashMap .class; 57 58 private OptionsModel keyOptionsModel; 59 60 private String labelProperty; 61 62 private Container items = new Container(); 63 64 private ElementFactory keyElementFactory; 65 66 private Editor keyEditor; 67 68 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 labelProperty) { 82 this.labelProperty = labelProperty; 83 } 84 85 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 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 133 public void setMapClass(Class mapClass) { 134 Assert.isAssignable(Map .class, mapClass); 135 this.mapClass = mapClass; 136 } 137 138 141 public void setItemElementFactory(ElementFactory itemElementFactory) { 142 this.itemElementFactory = itemElementFactory; 143 } 144 145 148 public void setValue(Object value) { 149 Map map = null; 150 if (value != null) { 151 Assert.isInstanceOf(Map .class, value, "Value must implement the Map interface"); 152 map = (Map ) value; 153 } 154 155 Collection 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 it = keys.iterator(); 165 while (it.hasNext()) { 166 Object key = it.next(); 167 Object obj = map != null ? map.get(key) : null; 168 addItem(key, obj); 169 } 170 } 171 } 172 173 public Object getValue() { 174 Map map = createOrClearMap(); 175 Iterator 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 createOrClearMap() { 184 Map map = (Map ) getEditorBinding().getValue(); 185 if (map == null) { 186 map = (Map ) BeanUtils.instantiateClass(mapClass); 187 } 188 else { 189 map.clear(); 190 } 191 return map; 192 } 193 194 private Set getKeys() { 195 HashSet keys = new HashSet (); 196 Iterator 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 key, Object 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 key; 222 223 private Editor element; 224 225 private Button removeButton; 226 227 public MapItem(Object 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 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 getKey() { 259 return this.key; 260 } 261 262 public Object getValue() { 263 return element.getValue(); 264 } 265 266 public void setValue(Object 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 getOptionValues() { 286 Collection keys = getKeys(); 287 ArrayList result = new ArrayList (); 288 Iterator it = model.getOptionValues().iterator(); 289 while (it.hasNext()) { 290 Object key = (Object ) it.next(); 291 if (!keys.contains(key)) { 292 result.add(key); 293 } 294 } 295 return result; 296 } 297 } 298 } 299 | Popular Tags |