KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hibernate > cfg > AnnotationConfiguration


1 // $Id: AnnotationConfiguration.java,v 1.31 2005/07/22 00:42:33 epbernard Exp $
2
package org.hibernate.cfg;
3
4 import java.io.File JavaDoc;
5 import java.util.ArrayList JavaDoc;
6 import java.util.Collections JavaDoc;
7 import java.util.HashMap JavaDoc;
8 import java.util.Iterator JavaDoc;
9 import java.util.List JavaDoc;
10 import java.util.Map JavaDoc;
11 import java.util.Properties JavaDoc;
12 import java.util.Set JavaDoc;
13 import java.util.HashSet JavaDoc;
14 import javax.persistence.EmbeddableSuperclass;
15
16 import org.apache.commons.logging.Log;
17 import org.apache.commons.logging.LogFactory;
18 import org.dom4j.Attribute;
19 import org.dom4j.Element;
20 import org.hibernate.MappingException;
21 import org.hibernate.AnnotationException;
22 import org.hibernate.mapping.Column;
23 import org.hibernate.mapping.Join;
24 import org.hibernate.mapping.Table;
25 import org.hibernate.mapping.UniqueKey;
26 import org.hibernate.util.ReflectHelper;
27
28 /**
29  * Add JSR 175 configuration capability.
30  * For now, only programmatic configuration is available.
31  *
32  * @author Emmanuel Bernard
33  */

34 public class AnnotationConfiguration extends Configuration {
35     private static Log log = LogFactory.getLog(AnnotationConfiguration.class);
36
37     private Map JavaDoc namedGenerators;
38     private Map JavaDoc<String JavaDoc, Map JavaDoc<String JavaDoc, Join>> joins;
39     private Map JavaDoc<Class JavaDoc, AnnotatedClassType> classTypes;
40     private Map JavaDoc<String JavaDoc,Properties JavaDoc> generatorTables;
41     private Map JavaDoc<Table, List JavaDoc<String JavaDoc[]>> tableUniqueConstraints;
42     private Map JavaDoc<String JavaDoc, String JavaDoc> mappedByResolver;
43     private Map JavaDoc<String JavaDoc, String JavaDoc> propertyRefResolver;
44     private List JavaDoc<Class JavaDoc> annotatedClasses;
45     private List JavaDoc<CacheHolder> caches;
46
47     public AnnotationConfiguration() {
48         super();
49     }
50
51     public AnnotationConfiguration(SettingsFactory sf) {
52         super(sf);
53     }
54
55     /**
56      * Add a list of classes to configuration. This method will automatically sort classes based on any
57      * inheritance hierarchy
58      *
59      * @param classes
60      * @return return annotation configuration
61      * @deprecated use #addAnnotatedClass(Class)
62      */

63     public AnnotationConfiguration addAnnotatedClasses(List JavaDoc<Class JavaDoc> classes) {
64         List JavaDoc<Class JavaDoc> newList;
65         newList = orderHierarchy(classes);
66         for (Class JavaDoc clazz : newList) {
67             addAnnotatedClass(clazz);
68         }
69         return this;
70     }
71
72     protected List JavaDoc<Class JavaDoc> orderHierarchy(List JavaDoc<Class JavaDoc> original) {
73         List JavaDoc<Class JavaDoc> copy = new ArrayList JavaDoc<Class JavaDoc>(original);
74         List JavaDoc<Class JavaDoc> newList = new ArrayList JavaDoc<Class JavaDoc>();
75         while (copy.size() > 0) {
76             Class JavaDoc clazz = copy.get(0);
77             orderHierarchy(copy, newList, original, clazz);
78         }
79         return newList;
80     }
81
82     private static void orderHierarchy(List JavaDoc<Class JavaDoc> copy, List JavaDoc<Class JavaDoc> newList, List JavaDoc<Class JavaDoc> original, Class JavaDoc clazz) {
83         if ( Object JavaDoc.class.equals(clazz) ) return;
84         //process superclass first
85
orderHierarchy( copy, newList, original, clazz.getSuperclass() );
86         if ( original.contains(clazz) ) {
87             if ( !newList.contains(clazz) ) {
88                 newList.add(clazz);
89             }
90             copy.remove(clazz);
91         }
92     }
93
94     /**
95      * Read a mapping from the class annotation metadata (JSR 175).
96      *
97      * @param persistentClass the mapped class
98      *
99      * @return the configuration object
100      */

101     public AnnotationConfiguration addAnnotatedClass(Class JavaDoc persistentClass) throws MappingException {
102         try {
103             annotatedClasses.add(persistentClass);
104             return this;
105         }
106         catch (MappingException me) {
107             log.error("Could not compile the mapping annotations", me);
108             throw me;
109         }
110     }
111
112     /**
113      * Read package level metadata
114      *
115      * @param packageName java package name
116      * @return the configuration object
117      */

118     public AnnotationConfiguration addPackage(String JavaDoc packageName) throws MappingException {
119         log.info("Mapping package " + packageName);
120         try {
121             AnnotationBinder.bindPackage( packageName, createExtendedMappings() );
122             return this;
123         }
124         catch (MappingException me) {
125             log.error("Could not compile the mapping annotations", me);
126             throw me;
127         }
128     }
129
130     public ExtendedMappings createExtendedMappings() {
131         return new ExtendedMappings(
132                 classes,
133                 collections,
134                 tables,
135                 namedQueries,
136                 namedSqlQueries,
137                 sqlResultSetMappings,
138                 imports,
139                 secondPasses,
140                 propertyReferences,
141                 namingStrategy,
142                 typeDefs,
143                 filterDefinitions,
144                 namedGenerators,
145                 joins,
146                 classTypes,
147                 extendsQueue,
148                 generatorTables,
149                 tableUniqueConstraints,
150                 mappedByResolver,
151                 propertyRefResolver
152         );
153     }
154
155     @Override JavaDoc
156     public void setCacheConcurrencyStrategy(String JavaDoc clazz, String JavaDoc concurrencyStrategy, String JavaDoc region) throws MappingException {
157         caches.add( new CacheHolder(clazz, concurrencyStrategy, region, true) );
158     }
159
160     @Override JavaDoc
161     public void setCollectionCacheConcurrencyStrategy(String JavaDoc collectionRole, String JavaDoc concurrencyStrategy, String JavaDoc region)
162             throws MappingException {
163         caches.add( new CacheHolder(collectionRole, concurrencyStrategy, region, false) );
164     }
165
166     protected void reset() {
167         super.reset();
168         namedGenerators = new HashMap JavaDoc();
169         joins = new HashMap JavaDoc<String JavaDoc, Map JavaDoc<String JavaDoc, Join>>();
170         classTypes = new HashMap JavaDoc<Class JavaDoc, AnnotatedClassType>();
171         generatorTables = new HashMap JavaDoc<String JavaDoc, Properties JavaDoc>();
172         tableUniqueConstraints = new HashMap JavaDoc<Table, List JavaDoc<String JavaDoc[]>>();
173         mappedByResolver = new HashMap JavaDoc<String JavaDoc, String JavaDoc>();
174         propertyRefResolver = new HashMap JavaDoc<String JavaDoc, String JavaDoc>();
175         annotatedClasses = new ArrayList JavaDoc<Class JavaDoc>();
176         caches = new ArrayList JavaDoc<CacheHolder>();
177     }
178
179     protected void secondPassCompile() throws MappingException {
180         log.debug("Executing first pass of annotated classes");
181         //bind classes in the correct order calculating some inheritance state
182
List JavaDoc<Class JavaDoc> orderedClasses = orderHierarchy(annotatedClasses);
183         orderedClasses = addImplicitEmbeddedSuperClasses(orderedClasses);
184         Map JavaDoc<Class JavaDoc, InheritanceState> inheritanceStatePerClass = AnnotationBinder.buildInheritanceStates(orderedClasses);
185         for (Class JavaDoc clazz : orderedClasses) {
186             InheritanceState state = inheritanceStatePerClass.get( clazz);
187             if (state.hasParents == false && state.hasEmbeddedSuperclass == false && state.isEmbeddableSuperclass ==false) {
188                 //might have an implicit superclass
189

190             }
191         }
192         for (Class JavaDoc clazz : orderedClasses) {
193             //todo use the same extended mapping
194
AnnotationBinder.bindClass( clazz, inheritanceStatePerClass, createExtendedMappings() );
195         }
196         annotatedClasses.clear();
197         int cacheNbr = caches.size();
198         for (int index = 0 ; index < cacheNbr ; index++) {
199             CacheHolder cacheHolder = caches.get(index);
200             if (cacheHolder.isClass) {
201                 super.setCacheConcurrencyStrategy(cacheHolder.role, cacheHolder.usage, cacheHolder.region);
202             }
203             else {
204                 super.setCollectionCacheConcurrencyStrategy(cacheHolder.role, cacheHolder.usage, cacheHolder.region);
205             }
206         }
207         caches.clear();
208
209         log.debug("processing manytoone fk mappings");
210         Iterator JavaDoc iter = secondPasses.iterator();
211         while ( iter.hasNext() ) {
212             HbmBinder.SecondPass sp = (HbmBinder.SecondPass) iter.next();
213             //do the second pass of fk before the others and remove them
214
if (sp instanceof FkSecondPass) {
215                 sp.doSecondPass(classes, Collections.EMPTY_MAP); // TODO: align meta-attributes with normal bind...
216
iter.remove();
217             }
218         }
219         super.secondPassCompile();
220         Iterator JavaDoc tables = (Iterator JavaDoc<Map.Entry JavaDoc<Table, List JavaDoc<String JavaDoc[]>>>) tableUniqueConstraints.entrySet().iterator();
221         Table table;
222         Map.Entry JavaDoc entry;
223         String JavaDoc keyName;
224         int uniqueIndexPerTable;
225         while ( tables.hasNext() ) {
226             entry = (Map.Entry JavaDoc) tables.next();
227             table = (Table) entry.getKey();
228             List JavaDoc<String JavaDoc[]> uniqueConstraints = (List JavaDoc<String JavaDoc[]>) entry.getValue();
229             uniqueIndexPerTable = 0;
230             for (String JavaDoc[] columnNames : uniqueConstraints) {
231                 keyName = "key" + uniqueIndexPerTable++;
232                 buildUniqueKeyFromColumnNames(columnNames, table, keyName);
233             }
234         }
235     }
236
237     private List JavaDoc<Class JavaDoc> addImplicitEmbeddedSuperClasses(List JavaDoc<Class JavaDoc> orderedClasses) {
238         List JavaDoc<Class JavaDoc> newOrderedClasses = new ArrayList JavaDoc<Class JavaDoc>(orderedClasses);
239         for (Class JavaDoc clazz : orderedClasses) {
240             Class JavaDoc superClazz = clazz.getSuperclass();
241             if ( ! newOrderedClasses.contains( superClazz ) ) {
242                 //maybe an implicit embeddable superclass
243
addEmbeddedSuperclasses(clazz, newOrderedClasses);
244             }
245         }
246         return newOrderedClasses;
247     }
248
249     private void addEmbeddedSuperclasses(Class JavaDoc clazz, List JavaDoc<Class JavaDoc> newOrderedClasses) {
250         Class JavaDoc superClass = clazz.getSuperclass();
251         boolean hasToStop = false;
252         while( ! hasToStop ) {
253             if (superClass.isAnnotationPresent( EmbeddableSuperclass.class) ) {
254                 newOrderedClasses.add( 0, superClass );
255                 superClass = superClass.getSuperclass();
256             }
257             else {
258                 hasToStop = true;
259             }
260         }
261     }
262
263     private void buildUniqueKeyFromColumnNames(String JavaDoc[] columnNames, Table table, String JavaDoc keyName) {
264         UniqueKey uc;
265         int size = columnNames.length;
266         Column[] columns = new Column[size];
267         Set JavaDoc<Column> unbound = new HashSet JavaDoc<Column>();
268         for (int index = 0 ; index < size; index++) {
269             columns[index] = new Column( columnNames[index] );
270             unbound.add( columns[index] );
271             //column equals and hashcode is based on column name
272
}
273         for (Column column : columns) {
274             if ( table.containsColumn( column ) ) {
275                 uc = table.getOrCreateUniqueKey( keyName );
276                 uc.addColumn( table.getColumn( column ) );
277                 unbound.remove( column );
278             }
279         }
280         if (unbound.size() > 0) {
281             StringBuffer JavaDoc sb = new StringBuffer JavaDoc("Unable to create unique key constraint (");
282             for (String JavaDoc columnName : columnNames) {
283                 sb.append( columnName ).append( ", ");
284             }
285             sb.setLength( sb.length() - 2 );
286             sb.append(") on table ").append( table.getName() ).append(": ");
287             for (Column column : unbound) {
288                 sb.append( column.getName() ).append( ", ");
289             }
290             sb.setLength( sb.length() - 2 );
291             sb.append( " not found");
292             throw new AnnotationException( sb.toString() );
293         }
294     }
295
296     protected void parseMappingElement(Element subelement, String JavaDoc name) {
297         Attribute rsrc = subelement.attribute( "resource" );
298         Attribute file = subelement.attribute( "file" );
299         Attribute jar = subelement.attribute( "jar" );
300         Attribute pckg = subelement.attribute( "package" );
301         Attribute clazz = subelement.attribute( "class" );
302         if ( rsrc != null ) {
303             log.debug( name + "<-" + rsrc );
304             addResource( rsrc.getValue() );
305         }
306         else if ( jar != null ) {
307             log.debug( name + "<-" + jar );
308             addJar( new File JavaDoc( jar.getValue() ) );
309         }
310         else if ( file != null) {
311             log.debug( name + "<-" + file );
312             addFile( file.getValue() );
313         }
314         else if (pckg != null) {
315             log.debug( name + "<-" + pckg );
316             addPackage( pckg.getValue() );
317         }
318         else if (clazz != null) {
319             log.debug( name + "<-" + clazz );
320             Class JavaDoc loadedClass = null;
321             try {
322                 loadedClass = ReflectHelper.classForName( clazz.getValue() );
323             }
324             catch (ClassNotFoundException JavaDoc cnf) {
325                 throw new MappingException("Unable to load class declared as <mapping class=\"" + clazz.getValue() + "\"/> in the configuration:", cnf);
326             }
327             addAnnotatedClass(loadedClass);
328         }
329         else {
330             throw new MappingException( "<mapping> element in configuration specifies no attributes" );
331         }
332     }
333
334     private class CacheHolder {
335         public CacheHolder(String JavaDoc role, String JavaDoc usage, String JavaDoc region, boolean isClass) {
336             this.role = role;
337             this.usage = usage;
338             this.region = region;
339             this.isClass = isClass;
340         }
341         public String JavaDoc role;
342         public String JavaDoc usage;
343         public String JavaDoc region;
344         public boolean isClass;
345     }
346 }
347
Popular Tags