View Javadoc

1   /*
2    * Copyright (c) 2010.  The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  
21  package org.apache.expreval.expr.var;
22  
23  import org.apache.expreval.client.InternalErrorException;
24  import org.apache.expreval.client.NullColumnValueException;
25  import org.apache.expreval.client.ResultMissingColumnException;
26  import org.apache.expreval.expr.MultipleExpressionContext;
27  import org.apache.expreval.expr.TypeSupport;
28  import org.apache.expreval.expr.literal.BooleanLiteral;
29  import org.apache.expreval.expr.literal.DateLiteral;
30  import org.apache.expreval.expr.literal.DoubleLiteral;
31  import org.apache.expreval.expr.literal.FloatLiteral;
32  import org.apache.expreval.expr.literal.IntegerLiteral;
33  import org.apache.expreval.expr.literal.LongLiteral;
34  import org.apache.expreval.expr.literal.NullLiteral;
35  import org.apache.expreval.expr.literal.ObjectLiteral;
36  import org.apache.expreval.expr.literal.ShortLiteral;
37  import org.apache.expreval.expr.literal.StringLiteral;
38  import org.apache.expreval.expr.node.GenericValue;
39  import org.apache.hadoop.hbase.client.Result;
40  import org.apache.hadoop.hbase.filter.Filter;
41  import org.apache.hadoop.hbase.hbql.client.HBqlException;
42  import org.apache.hadoop.hbase.hbql.impl.AggregateValue;
43  import org.apache.hadoop.hbase.hbql.impl.HConnectionImpl;
44  import org.apache.hadoop.hbase.hbql.impl.InvalidServerFilterException;
45  import org.apache.hadoop.hbase.hbql.impl.InvalidTypeException;
46  import org.apache.hadoop.hbase.hbql.util.Lists;
47  
48  import java.io.Serializable;
49  import java.util.Collection;
50  import java.util.Comparator;
51  import java.util.Date;
52  import java.util.List;
53  
54  public class NamedParameter implements GenericValue {
55  
56      private static long counter = Long.MIN_VALUE;
57  
58      private MultipleExpressionContext context = null;
59      private GenericValue typedExpr = null;
60      private List<GenericValue> typedExprList = null;
61  
62      private String paramName;
63      private long position;
64  
65      public NamedParameter() {
66      }
67  
68      public NamedParameter(final String paramName) {
69          if (paramName.equals("?"))
70              this.paramName = "unnamed";
71          else
72              this.paramName = paramName;
73  
74          this.position = getNextPosition();
75      }
76  
77      private static synchronized long getNextPosition() {
78          return counter++;
79      }
80  
81      public String toString() {
82          return this.getParamName();
83      }
84  
85      public String getParamName() {
86          return this.paramName;
87      }
88  
89      public long getPosition() {
90          return this.position;
91      }
92  
93      private boolean isScalarValueSet() {
94          return this.getTypedExpr() != null;
95      }
96  
97      private GenericValue getTypedExpr() {
98          return this.typedExpr;
99      }
100 
101     private List<GenericValue> getTypedExprList() {
102         return this.typedExprList;
103     }
104 
105     public GenericValue getOptimizedValue() throws HBqlException {
106         return this;
107     }
108 
109     public boolean isAConstant() {
110         return false;
111     }
112 
113     public boolean hasAColumnReference() {
114         return false;
115     }
116 
117     public boolean isAColumnReference() {
118         return false;
119     }
120 
121     public boolean isDefaultKeyword() {
122         return false;
123     }
124 
125     public boolean isAnAggregateValue() {
126         return false;
127     }
128 
129     public void setExpressionContext(final MultipleExpressionContext context) {
130         this.context = context;
131         this.getExpressionContext().addNamedParameter(this);
132     }
133 
134     private MultipleExpressionContext getExpressionContext() {
135         return this.context;
136     }
137 
138     public void initAggregateValue(final AggregateValue aggregateValue) throws HBqlException {
139         throw new InternalErrorException("Not applicable");
140     }
141 
142     public void applyResultToAggregateValue(final AggregateValue aggregateValue, final Result result) throws HBqlException {
143         throw new InternalErrorException("Not applicable");
144     }
145 
146     public void reset() {
147         this.typedExpr = null;
148         this.typedExprList = null;
149     }
150 
151     public Class<? extends GenericValue> validateTypes(final GenericValue parentExpr,
152                                                        final boolean allowCollections) throws HBqlException {
153 
154         if (this.getTypedExpr() == null && this.getTypedExprList() == null)
155             throw new InvalidTypeException("Parameter \"" + this.getParamName() + "\" not assigned a value");
156 
157         if (this.isScalarValueSet()) {
158             return this.getTypedExpr().getClass();
159         }
160         else {
161             // Make sure a list is legal in this expr
162             if (!allowCollections) {
163                 final String context = parentExpr == null ? "" : " in the context " + parentExpr.asString();
164                 throw new InvalidTypeException("Parameter " + this.getParamName()
165                                                + " is assigned a collection which is not allowed" + context);
166             }
167 
168             // if it is a list, then ensure that all the types in list are valid and consistent
169             if (this.getTypedExprList().size() == 0)
170                 throw new InvalidTypeException("Parameter " + this.getParamName() + " is assigned a collection with no values");
171 
172             // Look at the type of the first item and then make sure the rest match that one
173             final GenericValue firstval = this.getTypedExprList().get(0);
174             final Class<? extends GenericValue> clazzToMatch = TypeSupport.getGenericExprType(firstval);
175 
176             for (final GenericValue val : this.getTypedExprList()) {
177 
178                 final Class<? extends GenericValue> clazz = TypeSupport.getGenericExprType(val);
179 
180                 if (clazz == null)
181                     throw new InvalidTypeException("Parameter " + this.getParamName()
182                                                    + " assigned a collection value with invalid type "
183                                                    + firstval.getClass().getSimpleName());
184 
185                 if (!clazz.equals(clazzToMatch))
186                     throw new InvalidTypeException("Parameter " + this.getParamName()
187                                                    + " assigned a collection value with type "
188                                                    + firstval.getClass().getSimpleName()
189                                                    + " which is inconsistent with the type of the first element");
190             }
191 
192             return clazzToMatch;
193         }
194     }
195 
196     public Object getValue(final HConnectionImpl conn, final Object object) throws HBqlException,
197                                                                                    ResultMissingColumnException,
198                                                                                    NullColumnValueException {
199         if (this.isScalarValueSet()) {
200             final GenericValue genericValue = this.getTypedExpr();
201             return genericValue.getValue(conn, object);
202         }
203         else
204             return this.getTypedExprList();
205     }
206 
207     public void setParameter(final Object val) throws HBqlException {
208 
209         // Reset both values
210         this.reset();
211 
212         if (val != null && TypeSupport.isACollection(val)) {
213             this.typedExprList = Lists.newArrayList();
214             for (final Object elem : (Collection)val)
215                 this.getTypedExprList().add(this.getValueExpr((Serializable)elem));
216         }
217         else {
218             this.typedExpr = this.getValueExpr((Serializable)val);
219         }
220     }
221 
222     private GenericValue getValueExpr(final Serializable val) throws InvalidTypeException {
223 
224         if (val == null)
225             return new NullLiteral();
226 
227         if (val instanceof Boolean)
228             return new BooleanLiteral((Boolean)val);
229 
230         if (val instanceof Character)
231             return new ShortLiteral((short)((Character)val).charValue());
232 
233         if (val instanceof Short)
234             return new ShortLiteral((Short)val);
235 
236         if (val instanceof Integer)
237             return new IntegerLiteral((Integer)val);
238 
239         if (val instanceof Long)
240             return new LongLiteral((Long)val);
241 
242         if (val instanceof Float)
243             return new FloatLiteral((Float)val);
244 
245         if (val instanceof Double)
246             return new DoubleLiteral((Double)val);
247 
248         if (val instanceof String)
249             return new StringLiteral((String)val);
250 
251         if (val instanceof Date)
252             return new DateLiteral((Date)val);
253 
254         if (val instanceof Object)
255             return new ObjectLiteral(val);
256 
257         throw new InvalidTypeException("Parameter " + this.getParamName()
258                                        + " assigned an unsupported type " + val.getClass().getSimpleName());
259     }
260 
261     public String asString() {
262         return this.getParamName();
263     }
264 
265     public static Comparator<? super NamedParameter> getComparator() {
266         return new NamedParameterComparator();
267     }
268 
269     public static class NamedParameterComparator implements Comparator<NamedParameter>, Serializable {
270         public int compare(final NamedParameter param1, final NamedParameter param2) {
271             if (param1.getPosition() < param2.getPosition())
272                 return -1;
273             else if (param1.getPosition() > param2.getPosition())
274                 return +1;
275             else
276                 return 0;
277         }
278     }
279 
280     public Filter getFilter() throws HBqlException {
281         throw new InvalidServerFilterException();
282     }
283 }