1 /*
2 * Hibernate, Relational Persistence for Idiomatic Java
3 *
4 * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
5 * indicated by the @author tags or express copyright attribution
6 * statements applied by the authors. All third-party contributions are
7 * distributed under license by Red Hat Middleware LLC.
8 *
9 * This copyrighted material is made available to anyone wishing to use, modify,
10 * copy, or redistribute it subject to the terms and conditions of the GNU
11 * Lesser General Public License, as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
16 * for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this distribution; if not, write to:
20 * Free Software Foundation, Inc.
21 * 51 Franklin Street, Fifth Floor
22 * Boston, MA 02110-1301 USA
23 *
24 */
25 package org.hibernate.persister;
26
27 import java.lang.reflect.Constructor;
28 import java.lang.reflect.InvocationTargetException;
29
30 import org.hibernate.HibernateException;
31 import org.hibernate.MappingException;
32 import org.hibernate.cache.access.EntityRegionAccessStrategy;
33 import org.hibernate.cache.access.CollectionRegionAccessStrategy;
34 import org.hibernate.cfg.Configuration;
35 import org.hibernate.engine.Mapping;
36 import org.hibernate.engine.SessionFactoryImplementor;
37 import org.hibernate.mapping.Collection;
38 import org.hibernate.mapping.PersistentClass;
39 import org.hibernate.persister.collection.BasicCollectionPersister;
40 import org.hibernate.persister.collection.CollectionPersister;
41 import org.hibernate.persister.collection.OneToManyPersister;
42 import org.hibernate.persister.entity.EntityPersister;
43 import org.hibernate.persister.entity.JoinedSubclassEntityPersister;
44 import org.hibernate.persister.entity.SingleTableEntityPersister;
45 import org.hibernate.persister.entity.UnionSubclassEntityPersister;
46
47 /**
48 * Factory for <tt>EntityPersister</tt> and <tt>CollectionPersister</tt> instances
49 *
50 * @author Gavin King
51 */
52 public final class PersisterFactory {
53
54 //TODO: make EntityPersister *not* depend on SessionFactoryImplementor
55 //interface, if possible
56
57 // TODO : still need to make CollectionPersisters EntityMode-aware
58
59 private PersisterFactory() {}
60
61 private static final Class[] PERSISTER_CONSTRUCTOR_ARGS = new Class[] {
62 PersistentClass.class, EntityRegionAccessStrategy.class, SessionFactoryImplementor.class, Mapping.class
63 };
64
65 // TODO: is it really neceassry to provide Configuration to CollectionPersisters ? Should it not be enough with associated class ?
66 // or why does EntityPersister's not get access to configuration ?
67 //
68 // The only reason I could see that Configuration gets passed to collection persisters
69 // is so that they can look up the dom4j node name of the entity element in case
70 // no explicit node name was applied at the collection element level. Are you kidding me?
71 // Trivial to fix then. Just store and expose the node name on the entity persister
72 // (which the collection persister looks up anyway via other means...).
73 private static final Class[] COLLECTION_PERSISTER_CONSTRUCTOR_ARGS = new Class[] {
74 Collection.class, CollectionRegionAccessStrategy.class, Configuration.class, SessionFactoryImplementor.class
75 };
76
77 public static EntityPersister createClassPersister(
78 PersistentClass model,
79 EntityRegionAccessStrategy cacheAccessStrategy,
80 SessionFactoryImplementor factory,
81 Mapping cfg) throws HibernateException {
82 Class persisterClass = model.getEntityPersisterClass();
83 if ( persisterClass == null || persisterClass == SingleTableEntityPersister.class ) {
84 return new SingleTableEntityPersister( model, cacheAccessStrategy, factory, cfg );
85 }
86 else if ( persisterClass == JoinedSubclassEntityPersister.class ) {
87 return new JoinedSubclassEntityPersister( model, cacheAccessStrategy, factory, cfg );
88 }
89 else if ( persisterClass == UnionSubclassEntityPersister.class ) {
90 return new UnionSubclassEntityPersister( model, cacheAccessStrategy, factory, cfg );
91 }
92 else {
93 return create( persisterClass, model, cacheAccessStrategy, factory, cfg );
94 }
95 }
96
97 public static CollectionPersister createCollectionPersister(
98 Configuration cfg,
99 Collection model,
100 CollectionRegionAccessStrategy cacheAccessStrategy,
101 SessionFactoryImplementor factory) throws HibernateException {
102 Class persisterClass = model.getCollectionPersisterClass();
103 if ( persisterClass == null ) {
104 return model.isOneToMany()
105 ? ( CollectionPersister ) new OneToManyPersister( model, cacheAccessStrategy, cfg, factory )
106 : ( CollectionPersister ) new BasicCollectionPersister( model, cacheAccessStrategy, cfg, factory );
107 }
108 else {
109 return create( persisterClass, cfg, model, cacheAccessStrategy, factory );
110 }
111
112 }
113
114 private static EntityPersister create(
115 Class persisterClass,
116 PersistentClass model,
117 EntityRegionAccessStrategy cacheAccessStrategy,
118 SessionFactoryImplementor factory,
119 Mapping cfg) throws HibernateException {
120 Constructor pc;
121 try {
122 pc = persisterClass.getConstructor( PERSISTER_CONSTRUCTOR_ARGS );
123 }
124 catch ( Exception e ) {
125 throw new MappingException( "Could not get constructor for " + persisterClass.getName(), e );
126 }
127
128 try {
129 return (EntityPersister) pc.newInstance( new Object[] { model, cacheAccessStrategy, factory, cfg } );
130 }
131 catch (InvocationTargetException ite) {
132 Throwable e = ite.getTargetException();
133 if (e instanceof HibernateException) {
134 throw (HibernateException) e;
135 }
136 else {
137 throw new MappingException( "Could not instantiate persister " + persisterClass.getName(), e );
138 }
139 }
140 catch (Exception e) {
141 throw new MappingException( "Could not instantiate persister " + persisterClass.getName(), e );
142 }
143 }
144
145 private static CollectionPersister create(
146 Class persisterClass,
147 Configuration cfg,
148 Collection model,
149 CollectionRegionAccessStrategy cacheAccessStrategy,
150 SessionFactoryImplementor factory) throws HibernateException {
151 Constructor pc;
152 try {
153 pc = persisterClass.getConstructor( COLLECTION_PERSISTER_CONSTRUCTOR_ARGS );
154 }
155 catch (Exception e) {
156 throw new MappingException( "Could not get constructor for " + persisterClass.getName(), e );
157 }
158
159 try {
160 return (CollectionPersister) pc.newInstance( new Object[] { model, cacheAccessStrategy, cfg, factory } );
161 }
162 catch (InvocationTargetException ite) {
163 Throwable e = ite.getTargetException();
164 if (e instanceof HibernateException) {
165 throw (HibernateException) e;
166 }
167 else {
168 throw new MappingException( "Could not instantiate collection persister " + persisterClass.getName(), e );
169 }
170 }
171 catch (Exception e) {
172 throw new MappingException( "Could not instantiate collection persister " + persisterClass.getName(), e );
173 }
174 }
175
176
177 }