1 package org.hibernate.cfg; 3 4 import java.io.File ; 5 import java.util.ArrayList ; 6 import java.util.Collections ; 7 import java.util.HashMap ; 8 import java.util.Iterator ; 9 import java.util.List ; 10 import java.util.Map ; 11 import java.util.Properties ; 12 import java.util.Set ; 13 import java.util.HashSet ; 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 34 public class AnnotationConfiguration extends Configuration { 35 private static Log log = LogFactory.getLog(AnnotationConfiguration.class); 36 37 private Map namedGenerators; 38 private Map <String , Map <String , Join>> joins; 39 private Map <Class , AnnotatedClassType> classTypes; 40 private Map <String ,Properties > generatorTables; 41 private Map <Table, List <String []>> tableUniqueConstraints; 42 private Map <String , String > mappedByResolver; 43 private Map <String , String > propertyRefResolver; 44 private List <Class > annotatedClasses; 45 private List <CacheHolder> caches; 46 47 public AnnotationConfiguration() { 48 super(); 49 } 50 51 public AnnotationConfiguration(SettingsFactory sf) { 52 super(sf); 53 } 54 55 63 public AnnotationConfiguration addAnnotatedClasses(List <Class > classes) { 64 List <Class > newList; 65 newList = orderHierarchy(classes); 66 for (Class clazz : newList) { 67 addAnnotatedClass(clazz); 68 } 69 return this; 70 } 71 72 protected List <Class > orderHierarchy(List <Class > original) { 73 List <Class > copy = new ArrayList <Class >(original); 74 List <Class > newList = new ArrayList <Class >(); 75 while (copy.size() > 0) { 76 Class clazz = copy.get(0); 77 orderHierarchy(copy, newList, original, clazz); 78 } 79 return newList; 80 } 81 82 private static void orderHierarchy(List <Class > copy, List <Class > newList, List <Class > original, Class clazz) { 83 if ( Object .class.equals(clazz) ) return; 84 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 101 public AnnotationConfiguration addAnnotatedClass(Class 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 118 public AnnotationConfiguration addPackage(String 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 156 public void setCacheConcurrencyStrategy(String clazz, String concurrencyStrategy, String region) throws MappingException { 157 caches.add( new CacheHolder(clazz, concurrencyStrategy, region, true) ); 158 } 159 160 @Override 161 public void setCollectionCacheConcurrencyStrategy(String collectionRole, String concurrencyStrategy, String 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 (); 169 joins = new HashMap <String , Map <String , Join>>(); 170 classTypes = new HashMap <Class , AnnotatedClassType>(); 171 generatorTables = new HashMap <String , Properties >(); 172 tableUniqueConstraints = new HashMap <Table, List <String []>>(); 173 mappedByResolver = new HashMap <String , String >(); 174 propertyRefResolver = new HashMap <String , String >(); 175 annotatedClasses = new ArrayList <Class >(); 176 caches = new ArrayList <CacheHolder>(); 177 } 178 179 protected void secondPassCompile() throws MappingException { 180 log.debug("Executing first pass of annotated classes"); 181 List <Class > orderedClasses = orderHierarchy(annotatedClasses); 183 orderedClasses = addImplicitEmbeddedSuperClasses(orderedClasses); 184 Map <Class , InheritanceState> inheritanceStatePerClass = AnnotationBinder.buildInheritanceStates(orderedClasses); 185 for (Class clazz : orderedClasses) { 186 InheritanceState state = inheritanceStatePerClass.get( clazz); 187 if (state.hasParents == false && state.hasEmbeddedSuperclass == false && state.isEmbeddableSuperclass ==false) { 188 190 } 191 } 192 for (Class clazz : orderedClasses) { 193 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 iter = secondPasses.iterator(); 211 while ( iter.hasNext() ) { 212 HbmBinder.SecondPass sp = (HbmBinder.SecondPass) iter.next(); 213 if (sp instanceof FkSecondPass) { 215 sp.doSecondPass(classes, Collections.EMPTY_MAP); iter.remove(); 217 } 218 } 219 super.secondPassCompile(); 220 Iterator tables = (Iterator <Map.Entry <Table, List <String []>>>) tableUniqueConstraints.entrySet().iterator(); 221 Table table; 222 Map.Entry entry; 223 String keyName; 224 int uniqueIndexPerTable; 225 while ( tables.hasNext() ) { 226 entry = (Map.Entry ) tables.next(); 227 table = (Table) entry.getKey(); 228 List <String []> uniqueConstraints = (List <String []>) entry.getValue(); 229 uniqueIndexPerTable = 0; 230 for (String [] columnNames : uniqueConstraints) { 231 keyName = "key" + uniqueIndexPerTable++; 232 buildUniqueKeyFromColumnNames(columnNames, table, keyName); 233 } 234 } 235 } 236 237 private List <Class > addImplicitEmbeddedSuperClasses(List <Class > orderedClasses) { 238 List <Class > newOrderedClasses = new ArrayList <Class >(orderedClasses); 239 for (Class clazz : orderedClasses) { 240 Class superClazz = clazz.getSuperclass(); 241 if ( ! newOrderedClasses.contains( superClazz ) ) { 242 addEmbeddedSuperclasses(clazz, newOrderedClasses); 244 } 245 } 246 return newOrderedClasses; 247 } 248 249 private void addEmbeddedSuperclasses(Class clazz, List <Class > newOrderedClasses) { 250 Class 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 [] columnNames, Table table, String keyName) { 264 UniqueKey uc; 265 int size = columnNames.length; 266 Column[] columns = new Column[size]; 267 Set <Column> unbound = new HashSet <Column>(); 268 for (int index = 0 ; index < size; index++) { 269 columns[index] = new Column( columnNames[index] ); 270 unbound.add( columns[index] ); 271 } 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 sb = new StringBuffer ("Unable to create unique key constraint ("); 282 for (String 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 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 ( 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 loadedClass = null; 321 try { 322 loadedClass = ReflectHelper.classForName( clazz.getValue() ); 323 } 324 catch (ClassNotFoundException 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 role, String usage, String region, boolean isClass) { 336 this.role = role; 337 this.usage = usage; 338 this.region = region; 339 this.isClass = isClass; 340 } 341 public String role; 342 public String usage; 343 public String region; 344 public boolean isClass; 345 } 346 } 347 | Popular Tags |