KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hibernate > hql > ast > tree > AssignmentSpecification


1 // $Id: AssignmentSpecification.java,v 1.2 2005/07/15 21:43:53 steveebersole Exp $
2
package org.hibernate.hql.ast.tree;
3
4 import java.util.Iterator JavaDoc;
5 import java.util.List JavaDoc;
6
7 import org.hibernate.QueryException;
8 import org.hibernate.engine.SessionFactoryImplementor;
9 import org.hibernate.hql.antlr.HqlSqlTokenTypes;
10 import org.hibernate.hql.ast.SqlGenerator;
11 import org.hibernate.hql.ast.util.ASTUtil;
12 import org.hibernate.param.ParameterSpecification;
13 import org.hibernate.persister.entity.Queryable;
14
15 import antlr.collections.AST;
16
17 /**
18  * Encapsulates the information relating to an individual assignment within the
19  * set clause of an HQL update statement. This information is used during execution
20  * of the update statements when the updates occur against "multi-table" stuff.
21  *
22  * @author Steve Ebersole
23  */

24 public class AssignmentSpecification {
25
26     private final String JavaDoc tableName;
27     private final ParameterSpecification[] hqlParameters;
28     private final AST eq;
29     private final SessionFactoryImplementor factory;
30
31     private String JavaDoc sqlAssignmentString;
32
33     public AssignmentSpecification(AST eq, Queryable persister) {
34         if ( eq.getType() != HqlSqlTokenTypes.EQ ) {
35             throw new QueryException( "assignment in set-clause not associated with equals" );
36         }
37
38         this.eq = eq;
39         this.factory = persister.getFactory();
40
41         // Needed to bump this up to DotNode, because that is the only thing which currently
42
// knows about the property-ref path in the correct format; it is either this, or
43
// recurse over the DotNodes constructing the property path just like DotNode does
44
// internally
45
DotNode lhs = ( DotNode ) eq.getFirstChild();
46         SqlNode rhs = ( SqlNode ) lhs.getNextSibling();
47
48         validateLhs( lhs );
49
50         final String JavaDoc propertyPath = lhs.getPropertyPath();
51         this.tableName = persister.getSubclassTableName( persister.getSubclassPropertyTableNumber( propertyPath ) );
52
53         if (rhs==null) {
54             hqlParameters = new ParameterSpecification[0];
55         }
56         else if ( isParam( rhs ) ) {
57             hqlParameters = new ParameterSpecification[] { ( ( ParameterNode ) rhs ).getHqlParameterSpecification() };
58         }
59         else {
60             List JavaDoc parameterList = ASTUtil.collectChildren(
61                     rhs,
62                     new ASTUtil.IncludePredicate() {
63                         public boolean include(AST node) {
64                             return isParam( node );
65                         }
66                     }
67             );
68             hqlParameters = new ParameterSpecification[ parameterList.size() ];
69             Iterator JavaDoc itr = parameterList.iterator();
70             int i = 0;
71             while( itr.hasNext() ) {
72                 hqlParameters[i++] = ( ( ParameterNode ) itr.next() ).getHqlParameterSpecification();
73             }
74         }
75     }
76
77     public boolean affectsTable(String JavaDoc tableName) {
78         return this.tableName.equals( tableName );
79     }
80
81     public ParameterSpecification[] getParameters() {
82         return hqlParameters;
83     }
84
85     public String JavaDoc getSqlAssignmentFragment() {
86         if ( sqlAssignmentString == null ) {
87             try {
88                 SqlGenerator sqlGenerator = new SqlGenerator( factory );
89                 sqlGenerator.comparisonExpr( eq, false ); // false indicates to not generate parens around the assignment
90
sqlAssignmentString = sqlGenerator.getSQL();
91             }
92             catch( Throwable JavaDoc t ) {
93                 throw new QueryException( "cannot interpret set-clause assignment" );
94             }
95         }
96         return sqlAssignmentString;
97     }
98
99     private static boolean isParam(AST node) {
100         return node.getType() == HqlSqlTokenTypes.PARAM || node.getType() == HqlSqlTokenTypes.NAMED_PARAM;
101     }
102
103     private void validateLhs(FromReferenceNode lhs) {
104         // make sure the lhs is "assignable"...
105
if ( !lhs.isResolved() ) {
106             throw new UnsupportedOperationException JavaDoc( "cannot validate assignablity of unresolved node" );
107         }
108
109         if ( lhs.getDataType().isCollectionType() ) {
110             throw new QueryException( "collections not assignable in update statements" );
111         }
112         else if ( lhs.getDataType().isComponentType() ) {
113             throw new QueryException( "Components currently not assignable in update statements" );
114         }
115         else if ( lhs.getDataType().isEntityType() ) {
116             // currently allowed...
117
}
118
119         // TODO : why aren't these the same?
120
if ( lhs.getImpliedJoin() != null || lhs.getFromElement().isImplied() ) {
121             throw new QueryException( "Implied join paths are not assignable in update statements" );
122         }
123     }
124 }
125
Popular Tags