Source Code Cross Referenced for ScalarPropertyAccessor.java in  » ERP-CRM-Financial » jmoney » net » sf » jmoney » model2 » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » ERP CRM Financial » jmoney » net.sf.jmoney.model2 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package net.sf.jmoney.model2;
002:
003:        import java.lang.reflect.InvocationTargetException;
004:        import java.lang.reflect.Method;
005:        import java.util.Comparator;
006:
007:        import org.eclipse.swt.widgets.Composite;
008:
009:        public class ScalarPropertyAccessor<V> extends PropertyAccessor {
010:
011:            private int weight;
012:
013:            private int minimumWidth;
014:
015:            private boolean sortable;
016:
017:            /**
018:             * never null
019:             */
020:            private IPropertyControlFactory<V> propertyControlFactory;
021:
022:            /**
023:             * never null
024:             */
025:            private Method theGetMethod;
026:
027:            /**
028:             * never null
029:             */
030:            private Method theSetMethod;
031:
032:            /**
033:             * The class of the property values (if the method signatures show int,
034:             * long, boolean, or char, this field will be Integer.class, Long.class,
035:             * Boolean.class, or Character.class)
036:             */
037:            private Class<V> classOfValueObject;
038:
039:            /**
040:             * The class of the property values (if the method signatures show int,
041:             * long, boolean, or char, this field will be int.class, long.class,
042:             * boolean.class, or char.class)
043:             */
044:            private Class<?> classOfValueType;
045:
046:            private boolean nullAllowed;
047:
048:            /**
049:             * Index into the array of scalar properties.
050:             */
051:            private int indexIntoScalarProperties = -1;
052:
053:            private Comparator<ExtendableObject> parentComparator;
054:
055:            /*
056:             * Helper class to tie types together in a type safe manner.
057:             */
058:            // TODO: If we added the type of the containing object as a type parameter
059:            // of this ScalarPropertyAccessor class then this class would no longer
060:            // be necessary.
061:            private class TypesafePropertyDependency<E> {
062:                Class<E> classOfContainingObject;
063:                IPropertyDependency<E> dependency;
064:
065:                TypesafePropertyDependency(Class<E> classOfContainingObject,
066:                        IPropertyDependency<E> dependency) {
067:                    this .classOfContainingObject = classOfContainingObject;
068:                    this .dependency = dependency;
069:                }
070:
071:                public boolean isApplicable(ExtendableObject containingObject) {
072:                    return dependency.isApplicable(classOfContainingObject
073:                            .cast(containingObject));
074:                }
075:            }
076:
077:            private TypesafePropertyDependency<?> typesafeDependency;
078:
079:            public <E> ScalarPropertyAccessor(Class<V> classOfValueObject,
080:                    PropertySet<E> propertySet, String localName,
081:                    String displayName, int weight, int minimumWidth,
082:                    final IPropertyControlFactory<V> propertyControlFactory,
083:                    IPropertyDependency<E> propertyDependency) {
084:                super (propertySet, localName, displayName);
085:
086:                this .weight = weight;
087:                this .minimumWidth = minimumWidth;
088:                this .sortable = true;
089:                this .propertyControlFactory = propertyControlFactory;
090:
091:                this .typesafeDependency = (propertyDependency == null) ? null
092:                        : new TypesafePropertyDependency<E>(propertySet
093:                                .getImplementationClass(), propertyDependency);
094:
095:                Class implementationClass = propertySet
096:                        .getImplementationClass();
097:
098:                if (classOfValueObject.isPrimitive()) {
099:                    throw new MalformedPluginException(
100:                            "Property '"
101:                                    + localName
102:                                    + "' in '"
103:                                    + implementationClass.getName()
104:                                    + "' has been parameterized by a primitive type ("
105:                                    + classOfValueObject.getName()
106:                                    + ").  Although primitive types may be used by the getters and setters, the equivalent object classes must be used for parameterization.");
107:                }
108:
109:                // Use introspection on the interface to find the getter method.
110:                // Following the Java beans pattern, we allow the getter for a
111:                // boolean property to have a prefix of either "get" or "is".
112:                try {
113:                    theGetMethod = findMethod("get", localName, null);
114:                } catch (MalformedPluginException e) {
115:                    try {
116:                        theGetMethod = findMethod("is", localName, null);
117:                        if (theGetMethod.getReturnType() != boolean.class) {
118:                            throw new MalformedPluginException("Method '"
119:                                    + theGetMethod.getName() + "' in '"
120:                                    + implementationClass.getName()
121:                                    + "' must return boolean.");
122:                        }
123:                    } catch (MalformedPluginException e2) {
124:                        String propertyNamePart = localName.toUpperCase()
125:                                .substring(0, 1)
126:                                + localName.substring(1, localName.length());
127:                        throw new MalformedPluginException(
128:                                "The "
129:                                        + propertySet.getImplementationClass()
130:                                                .getName()
131:                                        + " class must have a method with a signature of get"
132:                                        + propertyNamePart
133:                                        + "() or, if a boolean property, a signature of is"
134:                                        + propertyNamePart + "().");
135:                    }
136:                }
137:
138:                if (theGetMethod.getReturnType() == void.class) {
139:                    throw new MalformedPluginException("Method '"
140:                            + theGetMethod.getName() + "' in '"
141:                            + implementationClass.getName()
142:                            + "' must not return void.");
143:                }
144:
145:                classOfValueType = theGetMethod.getReturnType();
146:
147:                Class<?> classOfObjectReturnedByGetter;
148:                if (classOfValueType == int.class) {
149:                    classOfObjectReturnedByGetter = Integer.class;
150:                    nullAllowed = false;
151:                } else if (classOfValueType == long.class) {
152:                    classOfObjectReturnedByGetter = Long.class;
153:                    nullAllowed = false;
154:                } else if (classOfValueType == boolean.class) {
155:                    classOfObjectReturnedByGetter = Boolean.class;
156:                    nullAllowed = false;
157:                } else if (classOfValueType == char.class) {
158:                    classOfObjectReturnedByGetter = Character.class;
159:                    nullAllowed = false;
160:                } else {
161:                    classOfObjectReturnedByGetter = classOfValueType;
162:                    nullAllowed = true;
163:                }
164:
165:                if (classOfObjectReturnedByGetter != classOfValueObject) {
166:                    throw new MalformedPluginException(
167:                            "Method '"
168:                                    + theGetMethod.getName()
169:                                    + "' in '"
170:                                    + implementationClass.getName()
171:                                    + "' returns type '"
172:                                    + theGetMethod.getReturnType().getName()
173:                                    + "' but code metadata indicates the type should be '"
174:                                    + classOfValueObject.getName() + "'.");
175:                }
176:
177:                this .classOfValueObject = classOfValueObject;
178:
179:                // Use introspection on the implementation class to find the setter method.
180:                Class parameterTypes[] = { classOfValueType };
181:                theSetMethod = findMethod("set", localName, parameterTypes);
182:
183:                if (theSetMethod.getReturnType() != void.class) {
184:                    throw new MalformedPluginException("Method '"
185:                            + theSetMethod.getName() + "' in '"
186:                            + implementationClass.getName()
187:                            + "' must return void type .");
188:                }
189:
190:                /*
191:                 * Set the comparator, if any.
192:                 * 
193:                 * If this object has been given a comparator to compare the values of
194:                 * the properties, then return a comparator that compares the parent
195:                 * objects by getting the property value from each parent and comparing
196:                 * those values.  Otherwise return null to indicate that there is no
197:                 * ordering.
198:                 */
199:                if (propertyControlFactory.getComparator() != null) {
200:                    parentComparator = new Comparator<ExtendableObject>() {
201:                        public int compare(ExtendableObject object1,
202:                                ExtendableObject object2) {
203:                            V value1 = object1
204:                                    .getPropertyValue(ScalarPropertyAccessor.this );
205:                            V value2 = object2
206:                                    .getPropertyValue(ScalarPropertyAccessor.this );
207:                            if (value1 == null && value2 == null)
208:                                return 0;
209:                            if (value1 == null)
210:                                return 1;
211:                            if (value2 == null)
212:                                return -1;
213:                            return propertyControlFactory.getComparator()
214:                                    .compare(value1, value2);
215:                        }
216:                    };
217:                } else {
218:                    parentComparator = null;
219:                }
220:            }
221:
222:            /**
223:             * The width weighting to be used when this property is displayed
224:             * in a table or a grid.  If the width available for the table
225:             * or grid is more than the sum of the minimum widths then the
226:             * excess width is distributed across the columns.
227:             * This weight indicates how much the property
228:             * can benefit from being given excess width.  For example
229:             * a property containing a description can benefit, whereas
230:             * a property containing a date cannot. 
231:             */
232:            public int getWeight() {
233:                return weight;
234:            }
235:
236:            /**
237:             * The minimum width to be used when this property is displayed
238:             * in a table or a grid.  
239:             */
240:            public int getMinimumWidth() {
241:                return minimumWidth;
242:            }
243:
244:            /**
245:             * Indicates whether users are able to sort views based on this property.
246:             */
247:            public boolean isSortable() {
248:                return sortable;
249:            }
250:
251:            /**
252:             * Indicates whether the property may take null values.
253:             * 
254:             * All properties may take null values except properties whose values are
255:             * the intrinsic types (int, long, boolean, char).  Properties of type Integer,
256:             * Long, Boolean, and Character may take null values.
257:             */
258:            public boolean isNullAllowed() {
259:                return nullAllowed;
260:            }
261:
262:            /**
263:             * The default value for a property is suitable for uses such
264:             * as:
265:             * 
266:             * - setting the default columnn value in a database
267:             * - providing values when the value is missing from an
268:             * 		XML file
269:             * 
270:             * It is expected that this value is constant (the same value
271:             * is always returned for a given property).  The results will
272:             * be unpredicable if this is not the case.
273:             * 
274:             * @return the default value to use for this property, which may
275:             * 		be null if the property is of a nullable type
276:             */
277:            public V getDefaultValue() {
278:                return propertyControlFactory.getDefaultValue();
279:            }
280:
281:            /**
282:             * Indicates whether the property may be edited by the user.
283:             */
284:            public boolean isEditable() {
285:                return (propertyControlFactory.isEditable());
286:            }
287:
288:            /**
289:             * Return a comparator to be used to compare two extendable objects based on the value
290:             * of this property.  This method looks to the comparator, if any, provided by
291:             * the IPropertyControlFactory implementation.  The ordering is thus defined by the
292:             * plug-in that added this property.
293:             * 
294:             * @return a comparator, or null if no comparator was provided
295:             * 		for use with this property
296:             */
297:            public Comparator<ExtendableObject> getComparator() {
298:                return parentComparator;
299:            }
300:
301:            public Method findMethod(String prefix, String propertyName,
302:                    Class[] parameters) {
303:                String methodName = prefix
304:                        + propertyName.toUpperCase().charAt(0)
305:                        + propertyName.substring(1, propertyName.length());
306:
307:                try {
308:                    return getDeclaredMethodRecursively(propertySet
309:                            .getImplementationClass(), methodName, parameters);
310:                } catch (NoSuchMethodException e) {
311:                    String parameterText = "";
312:                    if (parameters != null) {
313:                        for (int paramIndex = 0; paramIndex < parameters.length; paramIndex++) {
314:                            if (paramIndex > 0) {
315:                                parameterText = parameterText + ", ";
316:                            }
317:                            String className = parameters[paramIndex].getName();
318:                            if (parameters[paramIndex].isArray()) {
319:                                // The returned class name seems to be a mess when the class is an array,
320:                                // so we tidy it up.
321:                                parameterText = parameterText
322:                                        + className.substring(2, className
323:                                                .length() - 1) + "[]";
324:                            } else {
325:                                parameterText = parameterText + className;
326:                            }
327:                        }
328:                    }
329:                    throw new MalformedPluginException("The "
330:                            + propertySet.getImplementationClass().getName()
331:                            + " class must have a method with a signature of "
332:                            + methodName + "(" + parameterText + ").");
333:                }
334:            }
335:
336:            /**
337:             * Gets a method from an interface.  
338:             * Whereas Class.getDeclaredMethod finds a method from an
339:             * interface, it will not find the method if the method is
340:             * defined in an interface which the given interface extends.
341:             * This method will find the method if any of the interfaces
342:             * extended by this interface define the method. 
343:             */
344:            private Method getDeclaredMethodRecursively(
345:                    Class implementationClass, String methodName,
346:                    Class[] arguments) throws NoSuchMethodException {
347:                Class classToTry = implementationClass;
348:                do {
349:                    try {
350:                        return classToTry.getDeclaredMethod(methodName,
351:                                arguments);
352:                    } catch (NoSuchMethodException e) {
353:                        classToTry = classToTry.getSuperclass();
354:                    }
355:                } while (classToTry != null);
356:
357:                throw new NoSuchMethodException();
358:            }
359:
360:            /**
361:             */
362:            public V invokeGetMethod(Object invocationTarget) {
363:                try {
364:                    Object value = theGetMethod.invoke(invocationTarget,
365:                            (Object[]) null);
366:                    return classOfValueObject.cast(value);
367:                } catch (InvocationTargetException e) {
368:                    // TODO Process this properly
369:                    e.printStackTrace();
370:                    throw new RuntimeException("Plugin error");
371:                } catch (Exception e) {
372:                    // IllegalAccessException and IllegalArgumentException exceptions should
373:                    // not be possible here because the method was checked
374:                    // for correct access rights and parameters during initialization.
375:                    // Therefore throw a runtime exception.
376:                    e.printStackTrace();
377:                    throw new RuntimeException("internal error");
378:                }
379:            }
380:
381:            public void invokeSetMethod(Object invocationTarget, V value) {
382:                try {
383:                    Object parameters[] = new Object[] { value };
384:                    theSetMethod.invoke(invocationTarget, parameters);
385:                } catch (InvocationTargetException e) {
386:                    // TODO Process this properly
387:                    e.getCause().printStackTrace();
388:                    throw new RuntimeException("Plugin error");
389:                } catch (Exception e) {
390:                    // IllegalAccessException and IllegalArgumentException exceptions should
391:                    // not be possible here because the method was checked
392:                    // for correct access rights and parameters during initialization.
393:                    // Therefore throw a runtime exception.
394:                    e.printStackTrace();
395:                    throw new RuntimeException("internal error");
396:                }
397:            }
398:
399:            /**
400:             * Create a Control object that edits the property.
401:             * 
402:             * @param parent
403:             * @return An interface to a wrapper class.
404:             */
405:            public IPropertyControl createPropertyControl(Composite parent) {
406:                // When a PropertyAccessor object is created, it is
407:                // provided with an interface to a factory that constructs
408:                // control objects that edit the property.
409:                // We call into that factory to create an edit control.
410:                return propertyControlFactory.createPropertyControl(parent,
411:                        this );
412:            }
413:
414:            /**
415:             * Format the value of a property so it can be embedded into a
416:             * message.
417:             *
418:             * The returned value will look sensible when embedded in a message.
419:             * Therefore null values and empty values are returned as non-empty
420:             * text such as "none" or "empty".  Text values are placed in
421:             * quotes unless sure that only a single word will be returned that
422:             * would be readable without quotes.
423:             *
424:             * @return The value of the property formatted as appropriate.
425:             */
426:            public String formatValueForMessage(ExtendableObject object) {
427:                // When a PropertyAccessor object is created, it is
428:                // provided with an interface to a factory that constructs
429:                // control objects that edit the property.
430:                // This factory can also format values for us.
431:                // We call into that factory to obtain the property value
432:                // and format it.
433:
434:                // If null or the empty string is returned to us, 
435:                // change to "empty".
436:                String formattedValue = propertyControlFactory
437:                        .formatValueForMessage(object, this );
438:                return (formattedValue == null || formattedValue.length() == 0) ? "empty"
439:                        : formattedValue;
440:            }
441:
442:            /**
443:             * Format the value of a property as appropriate for displaying in a
444:             * table.
445:             * 
446:             * The returned value is expected to be displayed in a table or some similar
447:             * view.  Null and empty values are therefore returned as empty strings.
448:             * Text values are not quoted.
449:             * 
450:             * @return The value of the property formatted as appropriate.
451:             */
452:            public String formatValueForTable(ExtendableObject object) {
453:                // When a PropertyAccessor object is created, it is
454:                // provided with an interface to a factory that constructs
455:                // control objects that edit the property.
456:                // This factory can also format values for us.
457:                // We call into that factory to obtain the property value
458:                // and format it.
459:
460:                // If null is returned to us, change to the empty string.
461:                String formattedValue = propertyControlFactory
462:                        .formatValueForTable(object, this );
463:                return (formattedValue == null) ? "" : formattedValue;
464:            }
465:
466:            /**
467:             * Indicates if the property is a list of objects.
468:             */
469:            @Override
470:            public boolean isList() {
471:                return false;
472:            }
473:
474:            /**
475:             * Returns the class for the values of this property. This is
476:             * usually the class that is returned by the getter method, but if
477:             * the getter method returns int, long, boolean, or char then this
478:             * method will return Integer.class, Long.class, Boolean.class, or
479:             * Character.class.
480:             * 
481:             * @return the class of the property values (if the method signatures show int,
482:             * long, boolean, or char, this field will be Integer.class, Long.class,
483:             * Boolean.class, or Character.class)
484:             */
485:            public Class<V> getClassOfValueObject() {
486:                return classOfValueObject;
487:            }
488:
489:            /**
490:             * Returns the class for the values of this property. This is the
491:             * class that is returned by the getter method.
492:             * 
493:             * @return the class of the property values (if the method signatures show int,
494:             * long, boolean, or char, this field will be int.class, long.class,
495:             * boolean.class, or char.class)
496:             */
497:            public Class<?> getClassOfValueType() {
498:                return classOfValueType;
499:            }
500:
501:            /**
502:             * It is often useful to have an array of property values
503:             * of an extendable object.  This array contains all scalar
504:             * properties in the extendable object, including extension
505:             * properties and properties from any base property sets.
506:             * <P>
507:             * In these arrays, the properties (including extension properties)
508:             * from the base property sets are put first in the array.
509:             * This means a given property will always be at the same index
510:             * in the array regardless of the actual derived property set.
511:             * <P>
512:             * This index is guaranteed to match the order in which
513:             * properties are returned by the PropertySet.getPropertyIterator_Scalar3().
514:             * i.e. if this method returns n then in every case where the
515:             * collection returned by getPropertyIterator_Scalar3 contains this property,
516:             * this property will be returned as the (n+1)'th element in the collection.
517:             * 
518:             * @return the index of this property in the list of scalar
519:             * 			properties for the class.  This method returns zero
520:             * 			for the first scalar property returned by
521:             * 			PropertySet.getPropertyIterator3() and so on. 
522:             */
523:            public int getIndexIntoScalarProperties() {
524:                return indexIntoScalarProperties;
525:            }
526:
527:            // TODO: This method should be accessible only from within the package. 
528:            public void setIndexIntoScalarProperties(
529:                    int indexIntoScalarProperties) {
530:                this .indexIntoScalarProperties = indexIntoScalarProperties;
531:            }
532:
533:            /**
534:             * Indicates if this property is applicable.  An instance of an object
535:             * containing this property is passed.  This method should look to the values
536:             * of the other properties in the object to determine if this property is applicable.
537:             * 
538:             * If the property is not applicable then the UI should not show a value for this
539:             * property nor allow it to be updated.
540:             * 
541:             * @return
542:             */
543:            public boolean isPropertyApplicable(
544:                    ExtendableObject containingObject) {
545:                if (typesafeDependency == null) {
546:                    return true;
547:                } else {
548:                    return typesafeDependency.isApplicable(containingObject);
549:                }
550:            }
551:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.