View Javadoc

1   /*
2    * Copyright (c) 2011.  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.hadoop.hbase.hbql.mapping;
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.node.GenericValue;
27  import org.apache.hadoop.hbase.hbql.client.HBqlException;
28  import org.apache.hadoop.hbase.hbql.impl.HRecordImpl;
29  import org.apache.hadoop.hbase.hbql.impl.Utils;
30  import org.apache.hadoop.hbase.hbql.statement.args.DefaultArg;
31  import org.apache.hadoop.hbase.hbql.util.Lists;
32  
33  import java.lang.reflect.Method;
34  import java.util.List;
35  import java.util.Map;
36  import java.util.NavigableMap;
37  
38  public class HRecordAttrib extends ColumnAttrib {
39  
40      private final DefaultArg defaultArg;
41  
42      public HRecordAttrib(final ColumnDefinition columnDefinition) throws HBqlException {
43  
44          super(columnDefinition);
45  
46          this.defaultArg = this.evaluateDefaultValue(columnDefinition.getDefaultValue());
47  
48          if (this.isAKeyAttrib() && Utils.isValidString(this.getFamilyName()))
49              throw new HBqlException("Key value " + this.getNameToUseInExceptions() + " cannot have a family name");
50      }
51  
52      protected DefaultArg getDefaultArg() {
53          return this.defaultArg;
54      }
55  
56      public String asString() throws HBqlException {
57  
58          final StringBuilder sbuf = new StringBuilder();
59  
60          sbuf.append(this.getColumnName());
61  
62          sbuf.append(" " + this.getFieldType().getFirstSynonym());
63  
64          if (this.isAnArray())
65              sbuf.append("[]");
66  
67          if (this.hasAlias())
68              sbuf.append(" ALIAS " + this.getAliasName());
69  
70          if (this.hasDefaultArg())
71              sbuf.append(" DEFAULT " + this.getDefaultArg().asString());
72  
73          return sbuf.toString();
74      }
75  
76      public String toString() {
77          return this.getAliasName() + " - " + this.getFamilyQualifiedName();
78      }
79  
80      public boolean isAKeyAttrib() {
81          return this.getFieldType() == FieldType.KeyType;
82      }
83  
84      protected void defineAccessors() {
85          // TODO This needs to be implemented
86      }
87  
88      public Object getCurrentValue(final Object record) throws HBqlException, ResultMissingColumnException, NullColumnValueException {
89          Object retval = ((HRecordImpl)record).getCurrentValue(this.getAliasName());
90          if (retval == null) {
91              if (!((HRecordImpl)record).isColumnDefined(this.getAliasName()))
92                  throw new ResultMissingColumnException(this.getAliasName());
93              else
94                  throw new NullColumnValueException(this.getAliasName());
95          }
96          else {
97              return retval;
98          }
99      }
100 
101     public void setCurrentValue(final Object record, final long timestamp, final Object val) throws HBqlException {
102         ((HRecordImpl)record).setCurrentValue(this.getAliasName(), timestamp, val, true);
103     }
104 
105     public Map<Long, Object> getVersionMap(final Object record) throws HBqlException {
106         return ((HRecordImpl)record).getColumnValue(this.getAliasName(), true).getVersionMap();
107     }
108 
109     public void setUnMappedCurrentValue(final Object record,
110                                         final String name,
111                                         final byte[] value) throws HBqlException {
112         ((HRecordImpl)record).setUnMappedCurrentValue(this.getFamilyName(), name, 0, value);
113     }
114 
115     public void setUnMappedVersionMap(final Object record,
116                                       final String name,
117                                       final NavigableMap<Long, byte[]> timeStampMap) throws HBqlException {
118         ((HRecordImpl)record).setUnMappedVersionMap(this.getFamilyName(), name, timeStampMap);
119     }
120 
121     protected Method getMethod(final String methodName,
122                                final Class<?>... params) throws NoSuchMethodException, HBqlException {
123         throw new InternalErrorException();
124     }
125 
126     protected Class getComponentType() {
127         return this.getFieldType().getComponentType();
128     }
129 
130     public String getNameToUseInExceptions() {
131         return this.getFamilyQualifiedName();
132     }
133 
134     public String getEnclosingClassName() {
135         // TODO This will get resolved when getter/setter is added to TableMapping
136         return "";
137     }
138 
139     public boolean isAVersionValue() {
140         return true;
141     }
142 
143     public String[] getNamesForColumn() {
144         final List<String> nameList = Lists.newArrayList();
145         nameList.add(this.getFamilyQualifiedName());
146         if (!this.getAliasName().equals(this.getFamilyQualifiedName()))
147             nameList.add(this.getAliasName());
148         return nameList.toArray(new String[nameList.size()]);
149     }
150 
151     private DefaultArg evaluateDefaultValue(final GenericValue defaultValueExpr) throws HBqlException {
152 
153         if (defaultValueExpr == null)
154             return null;
155 
156         if (this.isAKeyAttrib())
157             throw new HBqlException("Default values are not valid for key values: "
158                                     + this.getNameToUseInExceptions());
159 
160         if (!defaultValueExpr.isAConstant())
161             throw new HBqlException("Default values must be constants: "
162                                     + this.getNameToUseInExceptions());
163 
164         if (this.isAnArray())
165             throw new HBqlException("Default values are not valid for array values: "
166                                     + this.getNameToUseInExceptions());
167 
168         // This will apply only to Annotations
169         if (this.isAVersionValue() && !this.isACurrentValue())
170             throw new HBqlException("Default values are not valid for version values: "
171                                     + this.getNameToUseInExceptions());
172 
173         final Class<? extends GenericValue> type = this.getFieldType().getExprType();
174 
175         if (type == null)
176             throw new HBqlException("Default values are not valid for: " + this.getNameToUseInExceptions());
177 
178         // Type checking will happen in this call
179         return new DefaultArg(type, defaultValueExpr);
180     }
181 }