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.event.def;
26
27 import org.hibernate.HibernateException;
28 import org.hibernate.event.EventSource;
29 import org.hibernate.intercept.LazyPropertyInitializer;
30 import org.hibernate.persister.entity.EntityPersister;
31 import org.hibernate.type.AbstractComponentType;
32 import org.hibernate.type.CollectionType;
33 import org.hibernate.type.EntityType;
34 import org.hibernate.type.Type;
35
36
37 /**
38 * Abstract superclass of algorithms that walk
39 * a tree of property values of an entity, and
40 * perform specific functionality for collections,
41 * components and associated entities.
42 *
43 * @author Gavin King
44 */
45 public abstract class AbstractVisitor {
46
47 private final EventSource session;
48
49 AbstractVisitor(EventSource session) {
50 this.session = session;
51 }
52
53 /**
54 * Dispatch each property value to processValue().
55 *
56 * @param values
57 * @param types
58 * @throws HibernateException
59 */
60 void processValues(Object[] values, Type[] types) throws HibernateException {
61 for ( int i=0; i<types.length; i++ ) {
62 if ( includeProperty(values, i) ) {
63 processValue( i, values, types );
64 }
65 }
66 }
67
68 /**
69 * Dispatch each property value to processValue().
70 *
71 * @param values
72 * @param types
73 * @throws HibernateException
74 */
75 public void processEntityPropertyValues(Object[] values, Type[] types) throws HibernateException {
76 for ( int i=0; i<types.length; i++ ) {
77 if ( includeEntityProperty(values, i) ) {
78 processValue( i, values, types );
79 }
80 }
81 }
82
83 void processValue(int i, Object[] values, Type[] types) {
84 processValue( values[i], types[i] );
85 }
86
87 boolean includeEntityProperty(Object[] values, int i) {
88 return includeProperty(values, i);
89 }
90
91 boolean includeProperty(Object[] values, int i) {
92 return values[i]!=LazyPropertyInitializer.UNFETCHED_PROPERTY;
93 }
94
95 /**
96 * Visit a component. Dispatch each property
97 * to processValue().
98 * @param component
99 * @param componentType
100 * @throws HibernateException
101 */
102 Object processComponent(Object component, AbstractComponentType componentType)
103 throws HibernateException {
104 if (component!=null) {
105 processValues(
106 componentType.getPropertyValues(component, session),
107 componentType.getSubtypes()
108 );
109 }
110 return null;
111 }
112
113 /**
114 * Visit a property value. Dispatch to the
115 * correct handler for the property type.
116 * @param value
117 * @param type
118 * @throws HibernateException
119 */
120 final Object processValue(Object value, Type type) throws HibernateException {
121
122 if ( type.isCollectionType() ) {
123 //even process null collections
124 return processCollection( value, (CollectionType) type );
125 }
126 else if ( type.isEntityType() ) {
127 return processEntity( value, (EntityType) type );
128 }
129 else if ( type.isComponentType() ) {
130 return processComponent( value, (AbstractComponentType) type );
131 }
132 else {
133 return null;
134 }
135 }
136
137 /**
138 * Walk the tree starting from the given entity.
139 *
140 * @param object
141 * @param persister
142 * @throws HibernateException
143 */
144 void process(Object object, EntityPersister persister)
145 throws HibernateException {
146 processEntityPropertyValues(
147 persister.getPropertyValues( object, getSession().getEntityMode() ),
148 persister.getPropertyTypes()
149 );
150 }
151
152 /**
153 * Visit a collection. Default superclass
154 * implementation is a no-op.
155 * @param collection
156 * @param type
157 * @throws HibernateException
158 */
159 Object processCollection(Object collection, CollectionType type)
160 throws HibernateException {
161 return null;
162 }
163
164 /**
165 * Visit a many-to-one or one-to-one associated
166 * entity. Default superclass implementation is
167 * a no-op.
168 * @param value
169 * @param entityType
170 * @throws HibernateException
171 */
172 Object processEntity(Object value, EntityType entityType)
173 throws HibernateException {
174 return null;
175 }
176
177 final EventSource getSession() {
178 return session;
179 }
180 }