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.mapping;
26
27 import java.io.Serializable;
28 import java.util.HashSet;
29 import java.util.Iterator;
30 import java.util.Set;
31
32 import org.slf4j.LoggerFactory;
33 import org.hibernate.MappingException;
34 import org.hibernate.engine.Mapping;
35 import org.hibernate.util.ReflectHelper;
36 import org.hibernate.util.SingletonIterator;
37
38 /**
39 * The root class of an inheritance hierarchy
40 * @author Gavin King
41 */
42 public class RootClass extends PersistentClass implements TableOwner {
43
44 public static final String DEFAULT_IDENTIFIER_COLUMN_NAME = "id";
45 public static final String DEFAULT_DISCRIMINATOR_COLUMN_NAME = "class";
46
47 private Property identifierProperty; //may be final
48 private KeyValue identifier; //may be final
49 private Property version; //may be final
50 private boolean polymorphic;
51 private String cacheConcurrencyStrategy;
52 private String cacheRegionName;
53 private boolean lazyPropertiesCacheable = true;
54 private Value discriminator; //may be final
55 private boolean mutable = true;
56 private boolean embeddedIdentifier = false; // may be final
57 private boolean explicitPolymorphism;
58 private Class entityPersisterClass;
59 private boolean forceDiscriminator = false;
60 private String where;
61 private Table table;
62 private boolean discriminatorInsertable = true;
63 private int nextSubclassId = 0;
64
65 int nextSubclassId() {
66 return ++nextSubclassId;
67 }
68
69 public int getSubclassId() {
70 return 0;
71 }
72
73 public void setTable(Table table) {
74 this.table=table;
75 }
76 public Table getTable() {
77 return table;
78 }
79
80 public Property getIdentifierProperty() {
81 return identifierProperty;
82 }
83 public KeyValue getIdentifier() {
84 return identifier;
85 }
86 public boolean hasIdentifierProperty() {
87 return identifierProperty!=null;
88 }
89
90 public Value getDiscriminator() {
91 return discriminator;
92 }
93
94 public boolean isInherited() {
95 return false;
96 }
97 public boolean isPolymorphic() {
98 return polymorphic;
99 }
100
101 public void setPolymorphic(boolean polymorphic) {
102 this.polymorphic = polymorphic;
103 }
104
105 public RootClass getRootClass() {
106 return this;
107 }
108
109 public Iterator getPropertyClosureIterator() {
110 return getPropertyIterator();
111 }
112 public Iterator getTableClosureIterator() {
113 return new SingletonIterator( getTable() );
114 }
115 public Iterator getKeyClosureIterator() {
116 return new SingletonIterator( getKey() );
117 }
118
119 public void addSubclass(Subclass subclass) throws MappingException {
120 super.addSubclass(subclass);
121 setPolymorphic(true);
122 }
123
124 public boolean isExplicitPolymorphism() {
125 return explicitPolymorphism;
126 }
127
128 public Property getVersion() {
129 return version;
130 }
131 public void setVersion(Property version) {
132 this.version = version;
133 }
134 public boolean isVersioned() {
135 return version!=null;
136 }
137
138 public boolean isMutable() {
139 return mutable;
140 }
141 public boolean hasEmbeddedIdentifier() {
142 return embeddedIdentifier;
143 }
144
145 public Class getEntityPersisterClass() {
146 return entityPersisterClass;
147 }
148
149 public Table getRootTable() {
150 return getTable();
151 }
152
153 public void setEntityPersisterClass(Class persister) {
154 this.entityPersisterClass = persister;
155 }
156
157 public PersistentClass getSuperclass() {
158 return null;
159 }
160
161 public KeyValue getKey() {
162 return getIdentifier();
163 }
164
165 public void setDiscriminator(Value discriminator) {
166 this.discriminator = discriminator;
167 }
168
169 public void setEmbeddedIdentifier(boolean embeddedIdentifier) {
170 this.embeddedIdentifier = embeddedIdentifier;
171 }
172
173 public void setExplicitPolymorphism(boolean explicitPolymorphism) {
174 this.explicitPolymorphism = explicitPolymorphism;
175 }
176
177 public void setIdentifier(KeyValue identifier) {
178 this.identifier = identifier;
179 }
180
181 public void setIdentifierProperty(Property identifierProperty) {
182 this.identifierProperty = identifierProperty;
183 identifierProperty.setPersistentClass(this);
184 }
185
186 public void setMutable(boolean mutable) {
187 this.mutable = mutable;
188 }
189
190 public boolean isDiscriminatorInsertable() {
191 return discriminatorInsertable;
192 }
193
194 public void setDiscriminatorInsertable(boolean insertable) {
195 this.discriminatorInsertable = insertable;
196 }
197
198 public boolean isForceDiscriminator() {
199 return forceDiscriminator;
200 }
201
202 public void setForceDiscriminator(boolean forceDiscriminator) {
203 this.forceDiscriminator = forceDiscriminator;
204 }
205
206 public String getWhere() {
207 return where;
208 }
209
210 public void setWhere(String string) {
211 where = string;
212 }
213
214 public void validate(Mapping mapping) throws MappingException {
215 super.validate(mapping);
216 if ( !getIdentifier().isValid(mapping) ) {
217 throw new MappingException(
218 "identifier mapping has wrong number of columns: " +
219 getEntityName() +
220 " type: " +
221 getIdentifier().getType().getName()
222 );
223 }
224 checkCompositeIdentifier();
225 }
226
227 private void checkCompositeIdentifier() {
228 if ( getIdentifier() instanceof Component ) {
229 Component id = (Component) getIdentifier();
230 if ( !id.isDynamic() ) {
231 Class idClass = id.getComponentClass();
232 if ( idClass != null && !ReflectHelper.overridesEquals( idClass ) ) {
233 LoggerFactory.getLogger( RootClass.class )
234 .warn( "composite-id class does not override equals(): "
235 + id.getComponentClass().getName() );
236 }
237 if ( !ReflectHelper.overridesHashCode( idClass ) ) {
238 LoggerFactory.getLogger( RootClass.class )
239 .warn( "composite-id class does not override hashCode(): "
240 + id.getComponentClass().getName() );
241 }
242 if ( !Serializable.class.isAssignableFrom( idClass ) ) {
243 throw new MappingException( "composite-id class must implement Serializable: "
244 + id.getComponentClass().getName() );
245 }
246 }
247 }
248 }
249
250 public String getCacheConcurrencyStrategy() {
251 return cacheConcurrencyStrategy;
252 }
253
254 public void setCacheConcurrencyStrategy(String cacheConcurrencyStrategy) {
255 this.cacheConcurrencyStrategy = cacheConcurrencyStrategy;
256 }
257
258 public String getCacheRegionName() {
259 return cacheRegionName==null ? getEntityName() : cacheRegionName;
260 }
261 public void setCacheRegionName(String cacheRegionName) {
262 this.cacheRegionName = cacheRegionName;
263 }
264
265 public boolean isLazyPropertiesCacheable() {
266 return lazyPropertiesCacheable;
267 }
268
269 public void setLazyPropertiesCacheable(boolean lazyPropertiesCacheable) {
270 this.lazyPropertiesCacheable = lazyPropertiesCacheable;
271 }
272
273 public boolean isJoinedSubclass() {
274 return false;
275 }
276
277 public java.util.Set getSynchronizedTables() {
278 return synchronizedTables;
279 }
280
281 public Set getIdentityTables() {
282 Set tables = new HashSet();
283 Iterator iter = getSubclassClosureIterator();
284 while ( iter.hasNext() ) {
285 PersistentClass clazz = (PersistentClass) iter.next();
286 if ( clazz.isAbstract() == null || !clazz.isAbstract().booleanValue() ) tables.add( clazz.getIdentityTable() );
287 }
288 return tables;
289 }
290
291 public Object accept(PersistentClassVisitor mv) {
292 return mv.accept(this);
293 }
294
295 public int getOptimisticLockMode() {
296 return optimisticLockMode;
297 }
298
299 }