KickJava   Java API By Example, From Geeks To Geeks.

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


1 //$Id: BinderHelper.java,v 1.3 2005/07/22 22:36:07 epbernard Exp $
2
package org.hibernate.cfg;
3
4 import java.util.ArrayList JavaDoc;
5 import java.util.HashMap JavaDoc;
6 import java.util.HashSet JavaDoc;
7 import java.util.Iterator JavaDoc;
8 import java.util.List JavaDoc;
9 import java.util.Map JavaDoc;
10 import java.util.Set JavaDoc;
11 import java.util.StringTokenizer JavaDoc;
12
13 import org.hibernate.AnnotationException;
14 import org.hibernate.AssertionFailure;
15 import org.hibernate.MappingException;
16 import org.hibernate.cfg.annotations.TableBinder;
17 import org.hibernate.mapping.Collection;
18 import org.hibernate.mapping.Column;
19 import org.hibernate.mapping.Component;
20 import org.hibernate.mapping.PersistentClass;
21 import org.hibernate.mapping.Property;
22 import org.hibernate.mapping.ToOne;
23 import org.hibernate.mapping.Value;
24 import org.hibernate.util.StringHelper;
25
26 /**
27  * @author Emmanuel Bernard
28  */

29 public class BinderHelper {
30     private BinderHelper() {}
31
32     /**
33      * create a property copy reusing the same value
34      */

35     public static Property shallowCopy(Property property) {
36         Property clone = new Property();
37         clone.setCascade( property.getCascade() );
38         clone.setInsertable( property.isInsertable() );
39         clone.setLazy( property.isLazy() );
40         clone.setName( property.getName() );
41         clone.setNaturalIdentifier( property.isNaturalIdentifier() );
42         clone.setOptimisticLocked( property.isOptimisticLocked() );
43         clone.setOptional( property.isOptional() );
44         clone.setPersistentClass( property.getPersistentClass() );
45         clone.setPropertyAccessorName( property.getPropertyAccessorName() );
46         clone.setSelectable( property.isSelectable() );
47         clone.setUpdateable( property.isUpdateable() );
48         clone.setValue( property.getValue() );
49         return clone;
50     }
51
52     public static void createSyntheticPropertyReference(
53             Ejb3JoinColumn[] columns,
54             PersistentClass referencedEntity,
55             Value value,
56             ExtendedMappings mappings) {
57         if ( columns[0].isImplicit() || StringHelper.isNotEmpty( columns[0].getMappedBy() ) ) return;
58         int fkEnum = Ejb3JoinColumn.checkReferencedColumnsType(columns, referencedEntity);
59         PersistentClass associatedClass = columns[0].getPropertyHolder() == null ? null : columns[0].getPropertyHolder().getPersistentClass();
60         if ( Ejb3JoinColumn.NON_PK_REFERENCE == fkEnum ) {
61             /**
62              * Create a synthetic property to refer to including an
63              * embedded component value containing all the properties
64              * mapped to the referenced columns
65              * We need to shallow copy those properties to mark them
66              * as non insertable / non updatable
67              */

68
69             String JavaDoc syntheticPropertyName = new StringBuffer JavaDoc("_")
70                     .append( referencedEntity.getEntityName().replace( '.', '_') )
71                     .append("_")
72                     .append( columns[0].getPropertyName() ).toString();
73             //find properties associated to a certain column
74
List JavaDoc<Property> properties = findPropertiesByColumns(referencedEntity, columns);
75             //create an embeddable component
76
Property synthProp = null;
77             if (properties != null) {
78                 Component embeddedComp = new Component( referencedEntity );
79                 embeddedComp.setEmbedded( true );
80                 embeddedComp.setComponentClassName( embeddedComp.getOwner().getClassName() );
81                 for (Property property : properties) {
82                     Property clone = BinderHelper.shallowCopy(property);
83                     clone.setInsertable( false );
84                     clone.setUpdateable( false );
85                     clone.setNaturalIdentifier( false );
86                     embeddedComp.addProperty( clone );
87                 }
88                 synthProp = new Property();
89                 synthProp.setName(syntheticPropertyName);
90                 //synthProp.setNodeName(syntheticPropertyName);
91
synthProp.setPersistentClass( referencedEntity );
92                 synthProp.setUpdateable(false);
93                 synthProp.setInsertable(false);
94                 synthProp.setValue(embeddedComp);
95                 synthProp.setPropertyAccessorName( "embedded" );
96                 referencedEntity.addProperty(synthProp);
97                 //make it unique
98
TableBinder.createUniqueConstraint( embeddedComp );
99             }
100             else {
101                 //TODO use a ToOne type doing a second select
102
StringBuffer JavaDoc columnsList = new StringBuffer JavaDoc();
103                 for(Ejb3JoinColumn column : columns) {
104                     columnsList.append( column.getReferencedColumn() ).append(", ");
105                 }
106                 throw new AnnotationException("referencedColumnName not mapped to a property is not supported: "
107                     + columnsList.toString() );
108             }
109
110                 /**
111                  * creating the property ref to the new synthetic property
112                  */

113             if (value instanceof ToOne) {
114                 ( (ToOne) value).setReferencedPropertyName(syntheticPropertyName);
115                 mappings.addUniquePropertyReference(referencedEntity.getEntityName(), syntheticPropertyName);
116             }
117             else if (value instanceof Collection) {
118                 //Collection collection = (Collection) referencedEntity.getProperty( columns[0].getPropertyName() ).getValue();
119
( (Collection) value).setReferencedPropertyName( syntheticPropertyName );
120                 //not unique because we could create a mtm wo association table
121
mappings.addPropertyReference(referencedEntity.getEntityName(), syntheticPropertyName);
122             }
123             else {
124                 throw new AssertionFailure("Do a property ref on an unexpected Value type: "
125                         + value.getClass().getName() );
126             }
127             mappings.addPropertyReferencedAssociation(
128                     associatedClass.getEntityName(),
129                     columns[0].getPropertyName(),
130                     syntheticPropertyName
131             );
132         }
133     }
134
135
136     private static List JavaDoc<Property> findPropertiesByColumns(PersistentClass referencedEntity, Ejb3JoinColumn[] columns) {
137         Map JavaDoc<Column,Set JavaDoc<Property>> columnsToProperty = new HashMap JavaDoc<Column,Set JavaDoc<Property>>();
138         List JavaDoc<Column> orderedColumns = new ArrayList JavaDoc<Column>();
139         for(int index = 0 ; index < columns.length ; index++) {
140             Column column = new Column( columns[index].getReferencedColumn() );
141             orderedColumns.add( column );
142             columnsToProperty.put( column, new HashSet JavaDoc<Property>() );
143         }
144         Iterator JavaDoc it = referencedEntity.getPropertyIterator();
145         while ( it.hasNext() ) {
146             Property property = (Property) it.next();
147             Iterator JavaDoc columnIt = property.getColumnIterator();
148             while ( columnIt.hasNext() ) {
149                 Column column = (Column) columnIt.next();
150                 if ( columnsToProperty.containsKey( column ) ) {
151                     columnsToProperty.get( column ).add( property );
152                 }
153             }
154         }
155         //first naive implementation
156
//only check 1 columns properties
157
//TODO make it smarter by checking correctly ordered multi column properties
158
List JavaDoc<Property> orderedProperties = new ArrayList JavaDoc<Property>();
159         for (Column column : orderedColumns) {
160             boolean found = false;
161             for (Property property : columnsToProperty.get( column ) ) {
162                 if (property.getColumnSpan() == 1) {
163                     orderedProperties.add(property);
164                     found = true;
165                     break;
166                 }
167             }
168             if (!found) return null; //have to find it the hard way
169
}
170         return orderedProperties;
171     }
172
173     public static Property findPropertyByName(PersistentClass associatedClass, String JavaDoc propertyName) {
174         Property property = null;
175         Property idProperty = associatedClass.getIdentifierProperty();
176         String JavaDoc idName = idProperty != null ? idProperty.getName() : null;
177         try {
178             if ( propertyName == null
179                     || propertyName.equals( "" )
180                     || propertyName.equals( idName ) ) {
181                 //default to id
182
property = idProperty;
183             }
184             else {
185                 if ( propertyName.indexOf( idName + "." ) == 0 ) {
186                     property = idProperty;
187                     propertyName = propertyName.substring( idName.length() + 1 );
188                 }
189                 StringTokenizer JavaDoc st = new StringTokenizer JavaDoc( propertyName, ".", false);
190                 while ( st.hasMoreElements() ) {
191                     String JavaDoc element = (String JavaDoc) st.nextElement();
192                     if (property == null) {
193                         property = associatedClass.getProperty( element );
194                     }
195                     else {
196                         if ( ! property.isComposite() ) return null;
197                         property = ( (Component) property.getValue() ).getProperty(element);
198                     }
199                 }
200             }
201         }
202         catch (MappingException e) {
203             return null;
204         }
205         return property;
206     }
207 }
208
Popular Tags