KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > persist > Mapping


1 // $Id$
2

3 package net.sf.persist;
4
5 import java.lang.reflect.Method JavaDoc;
6 import java.sql.DatabaseMetaData JavaDoc;
7 import java.sql.SQLException JavaDoc;
8 import java.util.HashMap JavaDoc;
9 import java.util.Map JavaDoc;
10
11 public abstract class Mapping {
12
13     public abstract Method JavaDoc getGetterForColumn(String JavaDoc columnName);
14
15     public abstract Method JavaDoc getSetterForColumn(String JavaDoc columnName);
16
17     // ---------- utility methods ----------
18

19     /**
20      * Factory method to create a Mapping based on a Class. Will return a
21      * NoTableAnnotation if the class has a NoTable annotation set, or
22      * TableAnnotation otherwise.
23      */

24     public static final Mapping getMapping(final DatabaseMetaData JavaDoc metaData, final Class JavaDoc objectClass,
25             final NameGuesser nameGuesser) {
26
27         // get @NoTable annotation
28
final net.sf.persist.annotations.NoTable noTableAnnotation = (net.sf.persist.annotations.NoTable) objectClass
29                 .getAnnotation(net.sf.persist.annotations.NoTable.class);
30
31         // if @NoTable is set, build a NoTableAnnotation
32
if (noTableAnnotation != null) {
33             return new NoTableMapping(objectClass, nameGuesser);
34         }
35
36         // otherwise, build a TableAnnotation
37
else {
38             try {
39                 return new TableMapping(metaData, objectClass, nameGuesser);
40             } catch (SQLException JavaDoc e) {
41                 throw new RuntimeSQLException(e);
42             }
43         }
44     }
45
46     /**
47      * Returns an array with maps for annotations, getters and setters. Keys in
48      * each map are field names.
49      */

50     protected static final Map JavaDoc[] getFieldsMaps(final Class JavaDoc objectClass) {
51         final Method JavaDoc[] methods = objectClass.getMethods();
52
53         // create map with all getters and setters
54

55         final Map JavaDoc<String JavaDoc, Method JavaDoc[]> allMethods = new HashMap JavaDoc();
56         for (Method JavaDoc method : methods) {
57             final String JavaDoc name = method.getName();
58             final String JavaDoc suffix = name.substring(3);
59
60             Method JavaDoc[] getterSetter = allMethods.get(suffix);
61             if (getterSetter == null) {
62                 getterSetter = new Method JavaDoc[2];
63                 allMethods.put(suffix, getterSetter);
64             }
65
66             if (name.startsWith("get")) {
67                 getterSetter[0] = method;
68             } else if (name.startsWith("set")) {
69                 getterSetter[1] = method;
70             }
71         }
72
73         // assemble annotations, getters and setters maps
74
// a field is only taken into consideration if it has a getter and a
75
// setter
76

77         final Map JavaDoc<String JavaDoc, net.sf.persist.annotations.Column> annotationsMap = new HashMap JavaDoc();
78         final Map JavaDoc<String JavaDoc, Method JavaDoc> gettersMap = new HashMap JavaDoc();
79         final Map JavaDoc<String JavaDoc, Method JavaDoc> settersMap = new HashMap JavaDoc();
80
81         for (String JavaDoc suffix : allMethods.keySet()) {
82
83             final Method JavaDoc[] getterSetter = allMethods.get(suffix);
84
85             // only consider fields to have both getters and setters
86
if (getterSetter[0] != null && getterSetter[1] != null) {
87
88                 // field name (prefix with first char in lower case)
89
final String JavaDoc fieldName = suffix.substring(0, 1).toLowerCase() + suffix.substring(1);
90
91                 // column annotation
92
final net.sf.persist.annotations.Column getterAnnotation = getterSetter[0]
93                         .getAnnotation(net.sf.persist.annotations.Column.class);
94                 final net.sf.persist.annotations.Column setterAnnotation = getterSetter[1]
95                         .getAnnotation(net.sf.persist.annotations.Column.class);
96
97                 // if NoColumn is specified, don't use the field
98
final net.sf.persist.annotations.NoColumn noPersistGetter = getterSetter[0]
99                         .getAnnotation(net.sf.persist.annotations.NoColumn.class);
100
101                 final net.sf.persist.annotations.NoColumn noPersistSetter = getterSetter[1]
102                         .getAnnotation(net.sf.persist.annotations.NoColumn.class);
103
104                 // check conflicting NoColumn and Column annotations
105
if (noPersistGetter != null || noPersistSetter != null) {
106                     if (getterAnnotation != null || setterAnnotation != null) {
107                         throw new RuntimeSQLException("Field [" + fieldName + "] from class [" + objectClass.getName()
108                                 + "] has conflicting NoColumn and Column annotations");
109                     }
110                     continue;
111                 }
112
113                 // assert that getters and setters have valid and compatible
114
// types
115
if (getterSetter[1].getParameterTypes().length != 1) {
116                     throw new RuntimeSQLException("Setter [" + getterSetter[1]
117                             + "] should have a single parameter but has " + getterSetter[1].getParameterTypes().length);
118                 }
119                 if (getterSetter[0].getReturnType() == void.class) {
120                     throw new RuntimeSQLException("Getter [" + getterSetter[0] + "] must have a return parameter");
121                 }
122                 if (getterSetter[0].getReturnType() != getterSetter[1].getParameterTypes()[0]) {
123                     throw new RuntimeSQLException("Getter [" + getterSetter[0] + "] and setter [" + getterSetter[1]
124                             + "] have incompatible types");
125                 }
126
127                 // check for annotations on the getter/setter
128
net.sf.persist.annotations.Column annotation = null;
129
130                 if (getterAnnotation != null && setterAnnotation != null) {
131
132                     // if both getter and setter have annotations, make sure
133
// they are equals
134
if (!getterAnnotation.equals(setterAnnotation)) {
135
136                         final String JavaDoc getterAnn = getterAnnotation.toString().substring(
137                                 getterAnnotation.toString().indexOf('(') + 1,
138                                 getterAnnotation.toString().lastIndexOf(')'));
139
140                         final String JavaDoc setterAnn = setterAnnotation.toString().substring(
141                                 setterAnnotation.toString().indexOf('(') + 1,
142                                 setterAnnotation.toString().lastIndexOf(')'));
143
144                         throw new RuntimeSQLException("Annotations for getter [" + getterSetter[0] + "] and setter ["
145                                 + getterSetter[1] + "] have different annotations [" + getterAnn + "] [" + setterAnn
146                                 + "]");
147                     }
148
149                     annotation = getterAnnotation;
150                 } else if (getterAnnotation != null) {
151                     annotation = getterAnnotation;
152                 } else if (setterAnnotation != null) {
153                     annotation = setterAnnotation;
154                 }
155
156                 // make getter and setter accessible
157
getterSetter[0].setAccessible(true);
158                 getterSetter[1].setAccessible(true);
159
160                 annotationsMap.put(fieldName, annotation);
161                 gettersMap.put(fieldName, getterSetter[0]);
162                 settersMap.put(fieldName, getterSetter[1]);
163             }
164         }
165
166         return new Map JavaDoc[] { annotationsMap, gettersMap, settersMap };
167     }
168
169 }
170
Popular Tags