001: /*
002: * SimpleObjectDesc.java
003: *
004: * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved.
005: *
006: * See the file "LICENSE.txt" for information on usage and redistribution
007: * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
008: */
009: package org.pnuts.tinybeans;
010:
011: import java.util.*;
012: import java.lang.reflect.*;
013: import org.pnuts.lang.ObjectDesc;
014: import org.pnuts.lang.PropertyHandler;
015:
016: public class SimpleObjectDesc implements ObjectDesc {
017: private Class cls;
018: private Map properties;
019:
020: public SimpleObjectDesc(Class cls) {
021: this .cls = cls;
022: Map m = new HashMap();
023: analyze(cls, m);
024: this .properties = m;
025: }
026:
027: SimpleObjectDesc(Class cls, Map properties) {
028: this .cls = cls;
029: this .properties = properties;
030: }
031:
032: public Method[] getMethods() {
033: return cls.getMethods();
034: }
035:
036: public void handleProperties(PropertyHandler handler) {
037: for (Iterator it = properties.values().iterator(); it.hasNext();) {
038: ObjectProperty p = (ObjectProperty) it.next();
039: handler.handle(p.getName(), p.getType(), p.getReadMethod(),
040: p.getWriteMethod());
041: }
042: }
043:
044: public static void analyze(Class cls,
045: Map/*<String,ObjectProperty>*/properties) {
046: Method[] methods = cls.getMethods();
047: for (int i = 0; i < methods.length; i++) {
048: Method method = methods[i];
049: int mods = method.getModifiers();
050: if (Modifier.isStatic(mods)) {
051: continue;
052: }
053: analyze(method, properties);
054: }
055: }
056:
057: public static void analyze(Method method,
058: Map/*<String,ObjectProperty>*/properties) {
059: String name = method.getName();
060: Class argTypes[] = method.getParameterTypes();
061: Class resultType = method.getReturnType();
062: int argCount = argTypes.length;
063: ObjectProperty pd = null;
064: String propertyName = null;
065: String substr = null;
066: if (argCount == 0) {
067: if (name.startsWith("get")) {
068: substr = name.substring(3);
069: propertyName = decapitalize(substr);
070: pd = new ObjectProperty(propertyName, resultType,
071: method, null, isCanonicalName(substr));
072: } else if (resultType == boolean.class
073: && name.startsWith("is")) {
074: substr = name.substring(2);
075: propertyName = decapitalize(substr);
076: pd = new ObjectProperty(propertyName, resultType,
077: method, null, isCanonicalName(substr));
078: }
079: } else if (argCount == 1) {
080: if (resultType == void.class && name.startsWith("set")) {
081: substr = name.substring(3);
082: propertyName = decapitalize(substr);
083: pd = new ObjectProperty(propertyName, argTypes[0],
084: null, method, isCanonicalName(substr));
085: }
086: }
087: if (propertyName != null) {
088: ObjectProperty p = (ObjectProperty) properties
089: .get(propertyName);
090: if (p == null || !p.hasCanonicalName()
091: && isCanonicalName(substr)) {
092: properties.put(propertyName, pd);
093: } else if (p.type.equals(pd.type)) {
094: if (p.r == null && pd.r != null) {
095: p.r = pd.r;
096: } else if (p.w == null && pd.w != null) {
097: p.w = pd.w;
098: }
099: }
100: }
101: }
102:
103: static boolean isCanonicalName(String name) {
104: int len = name.length();
105: if (len == 1) {
106: return Character.isUpperCase(name.charAt(0));
107: } else if (len > 1) {
108: if (!Character.isUpperCase(name.charAt(0))) {
109: return false;
110: }
111: if (Character.isUpperCase(name.charAt(1))) {
112: return true;
113: }
114: for (int i = 2; i < len; i++) {
115: if (Character.isUpperCase(name.charAt(i))) {
116: return false;
117: }
118: }
119: return true;
120: }
121: return false;
122: }
123:
124: public static String decapitalize(String name) {
125: if (name == null || name.length() == 0) {
126: return name;
127: }
128: if (name.length() > 1 && Character.isUpperCase(name.charAt(1))
129: && Character.isUpperCase(name.charAt(0))) {
130: return name;
131: }
132: char chars[] = name.toCharArray();
133: chars[0] = Character.toLowerCase(chars[0]);
134: return new String(chars);
135: }
136:
137: }
|