View Javadoc
1 /* 2 * Angkor Web Framework 3 * 4 * Distributable under LGPL license. 5 * See terms of license at gnu.org. 6 */ 7 8 package com.tirsen.angkor.beans; 9 10 import com.tirsen.angkor.Debug; 11 import org.apache.log4j.Category; 12 13 import java.beans.IndexedPropertyDescriptor; 14 import java.beans.IntrospectionException; 15 import java.beans.Introspector; 16 import java.beans.PropertyDescriptor; 17 import java.beans.PropertyEditor; 18 import java.beans.PropertyEditorManager; 19 import java.lang.reflect.Array; 20 import java.lang.reflect.InvocationTargetException; 21 import java.util.AbstractList; 22 import java.util.Collection; 23 import java.util.Iterator; 24 import java.util.List; 25 26 /*** 27 * 28 * <!-- $Id: PropertySupport.java,v 1.2 2002/10/09 21:37:37 tirsen Exp $ --> 29 * 30 * @author $Author: tirsen $ 31 * @version $Revision: 1.2 $ 32 */ 33 class PropertySupport 34 { 35 private static final Category logger = Debug.getCategory(); 36 37 private BeanModel beanModel; 38 private PropertyDescriptor property; 39 private Class propertyClass; 40 41 public PropertySupport(BeanModel proxy, String property, Class propertyClass) 42 { 43 this.beanModel = proxy; 44 this.propertyClass = propertyClass; 45 this.property = findPropertyDescriptor(proxy.getObjectClass(), property); 46 } 47 48 private static PropertyDescriptor findPropertyDescriptor(Class klass, String property) 49 { 50 PropertyDescriptor[] properties; 51 try 52 { 53 properties = Introspector.getBeanInfo(klass).getPropertyDescriptors(); 54 } 55 catch (IntrospectionException e) 56 { 57 throw new RuntimeException(e.getMessage()); 58 } 59 60 PropertyDescriptor propertyDesc = null; 61 for (int i = 0; i < properties.length; i++) 62 { 63 if (properties[i].getName().equals(property)) 64 { 65 propertyDesc = properties[i]; 66 break; 67 } 68 } 69 if (propertyDesc == null) throw new RuntimeException("No property " + property + " in bean of type " + klass.getName()); 70 71 return propertyDesc; 72 } 73 74 Object getBean() 75 { 76 return beanModel.getBean(); 77 } 78 79 public Object getValue() 80 { 81 Object bean = getBean(); 82 try 83 { 84 System.out.println("getPropertyDescriptor().getReadMethod() = " + getPropertyDescriptor().getReadMethod()); 85 System.out.println("bean = " + bean); 86 return getPropertyDescriptor().getReadMethod().invoke(bean, null); 87 } 88 catch (IllegalAccessException e) 89 { 90 throw new IllegalAccessError(e.getMessage()); 91 } 92 catch (InvocationTargetException e) 93 { 94 // handle this better? 95 throw new RuntimeException(e.getMessage()); 96 } 97 } 98 99 public boolean isReadOnly() 100 { 101 return property.getWriteMethod() == null || getPropertyEditor() == null; 102 } 103 104 public void setValue(Object value) 105 { 106 if (isReadOnly()) throw new IllegalStateException("Trying to update a read-only property."); 107 try 108 { 109 property.getWriteMethod().invoke(getBean(), new Object[]{value}); 110 } 111 catch (IllegalAccessException e) 112 { 113 throw new IllegalAccessError("Could not access property \"" + property.getName() + "\"." + 114 "Note: If you are using inner classes as models they need to be public."); 115 } 116 catch (InvocationTargetException e) 117 { 118 // handle this better? 119 throw new RuntimeException(e.getMessage()); 120 } 121 } 122 123 public PropertyEditor getPropertyEditor() 124 { 125 PropertyEditor editor = null; 126 127 Class editorClass = property.getPropertyEditorClass(); 128 if (editorClass != null) 129 { 130 try 131 { 132 editor = (PropertyEditor) editorClass.newInstance(); 133 } 134 catch (InstantiationException ignore) 135 { 136 } 137 catch (IllegalAccessException ignore) 138 { 139 } 140 } 141 142 if (editor == null) 143 { 144 editor = PropertyEditorManager.findEditor(getPropertyDescriptor().getPropertyType()); 145 } 146 147 return editor; 148 } 149 150 public PropertyDescriptor getPropertyDescriptor() 151 { 152 return property; 153 } 154 155 private class MultiValueList extends AbstractList 156 { 157 public Object get(int index) 158 { 159 return getValue(index); 160 } 161 162 public int size() 163 { 164 return PropertySupport.this.size(); 165 } 166 } 167 168 public List getList() 169 { 170 return new MultiValueList(); 171 } 172 173 public Object getValue(int index) 174 { 175 PropertyDescriptor property = getPropertyDescriptor(); 176 if (property instanceof IndexedPropertyDescriptor) return indexedGetValue(index); 177 Class type = property.getPropertyType(); 178 Object value; 179 if (type.isArray()) 180 { 181 value = Array.get(getValue(), index); 182 } 183 else if (List.class.isAssignableFrom(type)) 184 { 185 List list = (List) getValue(); 186 value = list.get(index); 187 } 188 else if (Iterator.class.isAssignableFrom(type)) 189 { 190 Iterator iterator = (Iterator) getValue(); 191 value = getComponentFromIterator(iterator, index); 192 } 193 else if (Collection.class.isAssignableFrom(type)) 194 { 195 Collection collection = (Collection) getValue(); 196 Iterator iterator = collection.iterator(); 197 value = getComponentFromIterator(iterator, index); 198 } 199 else 200 { 201 throw new IllegalStateException("Unsupported type of multi-valued property: " + type.getName()); 202 } 203 return value; 204 } 205 206 private Object getComponentFromIterator(Iterator iterator, int index) 207 { 208 Object value; 209 value = null; 210 int currentIndex = 0; 211 while (currentIndex <= index) 212 { 213 value = iterator.next(); 214 currentIndex++; 215 } 216 if (value == null) throw new IndexOutOfBoundsException("Property " + getPropertyDescriptor().getName() + " does not have value at index " + index); 217 return value; 218 } 219 220 public Object indexedGetValue(int index) 221 { 222 Object bean = getBean(); 223 try 224 { 225 System.out.println("getPropertyDescriptor().getReadMethod() = " + getPropertyDescriptor().getReadMethod()); 226 System.out.println("bean = " + bean); 227 IndexedPropertyDescriptor property = (IndexedPropertyDescriptor) getPropertyDescriptor(); 228 return property.getIndexedReadMethod().invoke(bean, new Object[]{new Integer(index)}); 229 } 230 catch (IllegalAccessException e) 231 { 232 throw new IllegalAccessError(e.getMessage()); 233 } 234 catch (InvocationTargetException e) 235 { 236 if (e.getTargetException() instanceof RuntimeException) 237 { 238 throw (RuntimeException) e.getTargetException(); 239 } 240 if (e.getTargetException() instanceof Error) 241 { 242 throw (Error) e.getTargetException(); 243 } 244 throw new RuntimeException(e.getMessage()); 245 } 246 } 247 248 private int indexedSize() 249 { 250 IndexedPropertyDescriptor descriptor = (IndexedPropertyDescriptor) getPropertyDescriptor(); 251 int size = 0; 252 try 253 { 254 while (size < Integer.MAX_VALUE) 255 { 256 indexedGetValue(size); 257 size++; 258 } 259 } 260 catch (IndexOutOfBoundsException expected) 261 { 262 } 263 return size; 264 } 265 266 public int size() 267 { 268 PropertyDescriptor property = getPropertyDescriptor(); 269 if (property instanceof IndexedPropertyDescriptor) return indexedSize(); 270 Class type = property.getPropertyType(); 271 int size; 272 if (type.isArray()) 273 { 274 Object value = getValue(); 275 if (value == null) 276 return 0; 277 else 278 size = Array.getLength(value); 279 } 280 else if (Collection.class.isAssignableFrom(type)) 281 { 282 Collection collection = (Collection) getValue(); 283 size = collection.size(); 284 } 285 else if (Iterator.class.isAssignableFrom(type)) 286 { 287 Iterator iterator = (Iterator) getValue(); 288 size = 0; 289 while (iterator.hasNext()) 290 { 291 iterator.next(); 292 size++; 293 } 294 } 295 else 296 { 297 throw new IllegalStateException("Unsupported type of multi-valued property: " + type.getName()); 298 } 299 return size; 300 } 301 302 public Class getComponentType() 303 { 304 Class type; 305 if (propertyClass != null) 306 { 307 type = propertyClass; 308 } 309 else 310 { 311 type = getPropertyDescriptor().getPropertyType(); 312 if (type.isArray()) 313 { 314 type = type.getComponentType(); 315 } 316 else if (type == List.class) 317 { 318 throw new RuntimeException("Could not determine component type of " + property + " with type " + type + "." + 319 "You have to specify it manually."); 320 } 321 } 322 return type; 323 } 324 }

This page was automatically generated by Maven