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;
22  
23  import org.apache.expreval.client.InternalErrorException;
24  import org.apache.expreval.expr.literal.BooleanLiteral;
25  import org.apache.expreval.expr.literal.ByteLiteral;
26  import org.apache.expreval.expr.literal.DateLiteral;
27  import org.apache.expreval.expr.literal.DoubleLiteral;
28  import org.apache.expreval.expr.literal.FloatLiteral;
29  import org.apache.expreval.expr.literal.IntegerLiteral;
30  import org.apache.expreval.expr.literal.LongLiteral;
31  import org.apache.expreval.expr.literal.ShortLiteral;
32  import org.apache.expreval.expr.literal.StringLiteral;
33  import org.apache.expreval.expr.node.BooleanValue;
34  import org.apache.expreval.expr.node.ByteValue;
35  import org.apache.expreval.expr.node.DateValue;
36  import org.apache.expreval.expr.node.DoubleValue;
37  import org.apache.expreval.expr.node.FloatValue;
38  import org.apache.expreval.expr.node.GenericValue;
39  import org.apache.expreval.expr.node.IntegerValue;
40  import org.apache.expreval.expr.node.LongValue;
41  import org.apache.expreval.expr.node.NumberValue;
42  import org.apache.expreval.expr.node.ShortValue;
43  import org.apache.expreval.expr.node.StringValue;
44  import org.apache.hadoop.hbase.hbql.client.HBqlException;
45  import org.apache.hadoop.hbase.hbql.util.Lists;
46  
47  import java.io.Serializable;
48  import java.lang.reflect.Constructor;
49  import java.lang.reflect.InvocationTargetException;
50  import java.util.Arrays;
51  import java.util.Date;
52  import java.util.List;
53  
54  public abstract class TypeSignature implements Serializable {
55  
56      private static final long serialVersionUID = 1L;
57  
58      private Class<? extends GenericValue> returnType;
59      private List<Class<? extends GenericValue>> argsTypeSignature = Lists.newArrayList();
60  
61      private Class literalCastClass;
62      private transient Constructor literalConstructor;
63  
64      public TypeSignature() {
65      }
66  
67      public TypeSignature(final Class<? extends GenericValue> returnType,
68                           final Class<? extends GenericValue>... argsTypeSignature) {
69          this.returnType = returnType;
70          this.argsTypeSignature.addAll(Arrays.asList(argsTypeSignature));
71  
72          this.literalCastClass = this.getLiteralCastClass(this.getReturnType());
73          this.literalConstructor = this.getLiteralConstructor(this.getReturnType(), this.getLiteralCastClass());
74      }
75  
76      public Class<? extends GenericValue> getReturnType() {
77          return this.returnType;
78      }
79  
80      public List<Class<? extends GenericValue>> getArgTypeList() {
81          return this.argsTypeSignature;
82      }
83  
84      private Constructor getLiteralConstructor() {
85          return this.literalConstructor;
86      }
87  
88      private Class getLiteralCastClass() {
89          return this.literalCastClass;
90      }
91  
92      public Class<? extends GenericValue> getArg(final int i) {
93          return this.getArgTypeList().get(i);
94      }
95  
96      public int getArgCount() {
97          return this.getArgTypeList().size();
98      }
99  
100     private Class getLiteralCastClass(final Class<? extends GenericValue> clazz) {
101 
102         if (clazz == null)
103             return null;
104         else if (clazz == BooleanValue.class)
105             return Boolean.class;
106         else if (clazz == ByteValue.class)
107             return Byte.class;
108         else if (clazz == ShortValue.class)
109             return Short.class;
110         else if (clazz == IntegerValue.class)
111             return Integer.class;
112         else if (clazz == LongValue.class)
113             return Long.class;
114         else if (clazz == FloatValue.class)
115             return Float.class;
116         else if (clazz == DoubleValue.class)
117             return Double.class;
118         else if (clazz == NumberValue.class)
119             return Number.class;
120         else if (clazz == StringValue.class)
121             return String.class;
122         else if (clazz == DateValue.class)
123             return Long.class;    // Note this is Long and not Date
124         else {
125             throw new RuntimeException("Invalid return type in signature: " + clazz.getName());
126         }
127     }
128 
129     private Constructor getLiteralConstructor(final Class clazz, final Class aLiteralCastClass) {
130 
131         final Class retval;
132 
133         try {
134             if (clazz == null)
135                 return null;
136             else if (clazz == BooleanValue.class || clazz == Boolean.class)
137                 retval = BooleanLiteral.class;
138             else if (NumericType.isAByte(clazz))
139                 retval = ByteLiteral.class;
140             else if (NumericType.isAShort(clazz))
141                 retval = ShortLiteral.class;
142             else if (NumericType.isAnInteger(clazz))
143                 retval = IntegerLiteral.class;
144             else if (NumericType.isALong(clazz))
145                 retval = LongLiteral.class;
146             else if (NumericType.isAFloat(clazz))
147                 retval = FloatLiteral.class;
148             else if (NumericType.isADouble(clazz))
149                 retval = DoubleLiteral.class;
150             else if (clazz == NumberValue.class || clazz == Number.class)
151                 return null;
152             else if (clazz == StringValue.class || clazz == String.class)
153                 retval = StringLiteral.class;
154             else if (clazz == DateValue.class || clazz == Date.class)
155                 retval = DateLiteral.class;
156             else
157                 throw new RuntimeException("Invalid return type in signature: " + clazz.getName());
158 
159             return retval.getConstructor(aLiteralCastClass);
160         }
161         catch (NoSuchMethodException e) {
162             throw new RuntimeException("Invalid literal constructor in signature: " + clazz.getName());
163         }
164     }
165 
166     public GenericValue newLiteral(final Object val) throws HBqlException {
167         try {
168 
169             final Constructor constructor;
170             final Object castedObject;
171 
172             if (this.getReturnType() == NumberValue.class) {
173                 constructor = this.getLiteralConstructor(val.getClass(), val.getClass());
174                 castedObject = val;
175             }
176             else {
177                 constructor = this.getLiteralConstructor();
178                 castedObject = this.getLiteralCastClass().cast(val);
179             }
180 
181             return (GenericValue)constructor.newInstance(castedObject);
182         }
183         catch (InstantiationException e) {
184             throw new InternalErrorException(e.getMessage());
185         }
186         catch (IllegalAccessException e) {
187             throw new InternalErrorException(e.getMessage());
188         }
189         catch (InvocationTargetException e) {
190             throw new InternalErrorException(e.getMessage());
191         }
192     }
193 }