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.impl;
22  
23  import org.apache.expreval.client.InternalErrorException;
24  import org.apache.hadoop.hbase.hbql.client.HBqlException;
25  import org.apache.hadoop.hbase.hbql.client.HRecord;
26  import org.apache.hadoop.hbase.hbql.client.UnMappedValueMap;
27  import org.apache.hadoop.hbase.hbql.mapping.ColumnAttrib;
28  import org.apache.hadoop.hbase.hbql.mapping.FieldType;
29  import org.apache.hadoop.hbase.hbql.mapping.MappingContext;
30  import org.apache.hadoop.hbase.hbql.mapping.ResultAccessor;
31  import org.apache.hadoop.hbase.hbql.mapping.TableMapping;
32  import org.apache.hadoop.hbase.hbql.util.AtomicReferences;
33  import org.apache.hadoop.hbase.hbql.util.Lists;
34  import org.apache.hadoop.hbase.hbql.util.Maps;
35  
36  import java.util.Date;
37  import java.util.List;
38  import java.util.Map;
39  import java.util.NavigableMap;
40  import java.util.Set;
41  import java.util.concurrent.atomic.AtomicReference;
42  
43  public class HRecordImpl implements HRecord {
44  
45      private MappingContext mappingContext;
46      private long timestamp = System.currentTimeMillis();
47  
48      private List<String> namePositionList = Lists.newArrayList();
49  
50      private AtomicReference<ElementMap<ColumnValue>>      atomicColumnValuesMap   = AtomicReferences.newAtomicReference();
51      private AtomicReference<ElementMap<UnMappedValueMap>> atomicUnMappedValuesMap = AtomicReferences.newAtomicReference();
52  
53      public HRecordImpl() {
54      }
55  
56      public HRecordImpl(final MappingContext mappingContext) {
57          this.setMappingContext(mappingContext);
58      }
59  
60      public MappingContext getMappingContext() {
61          return mappingContext;
62      }
63  
64      public void setMappingContext(final MappingContext mappingContext) {
65          this.mappingContext = mappingContext;
66      }
67  
68      public long getTimestamp() {
69          return this.timestamp;
70      }
71  
72      private AtomicReference<ElementMap<UnMappedValueMap>> getAtomicUnMappedValuesMap() {
73          return this.atomicUnMappedValuesMap;
74      }
75  
76      private AtomicReference<ElementMap<ColumnValue>> getAtomicColumnValuesMap() {
77          return this.atomicColumnValuesMap;
78      }
79  
80      private List<String> getNamePositionList() {
81          return this.namePositionList;
82      }
83  
84      public String getAttribName(final int i) throws HBqlException {
85          try {
86              return this.getNamePositionList().get(i - 1);
87          }
88          catch (ArrayIndexOutOfBoundsException e) {
89              throw new HBqlException("Invalid column number " + i);
90          }
91      }
92  
93      public void addNameToPositionList(final String name) {
94          this.getNamePositionList().add(name);
95      }
96  
97      public TableMapping getTableMapping() throws HBqlException {
98          return this.getMappingContext().getTableMapping();
99      }
100 
101     public ResultAccessor getResultAccessor() throws HBqlException {
102         return this.getMappingContext().getResultAccessor();
103     }
104 
105     protected ElementMap<ColumnValue> getColumnValuesMap() {
106         if (this.getAtomicColumnValuesMap().get() == null)
107             synchronized (this) {
108                 if (this.getAtomicColumnValuesMap().get() == null)
109                     this.getAtomicColumnValuesMap().set(new ElementMap<ColumnValue>(this));
110             }
111         return this.getAtomicColumnValuesMap().get();
112     }
113 
114     private ElementMap<UnMappedValueMap> getUnMappedValuesMap() {
115         if (this.getAtomicUnMappedValuesMap().get() == null)
116             synchronized (this) {
117                 if (this.getAtomicUnMappedValuesMap().get() == null)
118                     this.getAtomicUnMappedValuesMap().set(new ElementMap<UnMappedValueMap>(this));
119             }
120         return this.getAtomicUnMappedValuesMap().get();
121     }
122 
123     public void addElement(final Value value) throws HBqlException {
124 
125         if (value instanceof ColumnValue)
126             this.getColumnValuesMap().addElement((ColumnValue)value);
127         else if (value instanceof UnMappedValueMap)
128             this.getUnMappedValuesMap().addElement((UnMappedValueMap)value);
129         else
130             throw new InternalErrorException(value.getClass().getName());
131     }
132 
133     public void clearValues() {
134         this.getColumnValuesMap().clear();
135         this.getUnMappedValuesMap().clear();
136     }
137 
138     // Simple get routines
139     public ColumnValue getColumnValue(final String name, final boolean inMapping) throws HBqlException {
140         final ColumnValue value = this.getColumnValuesMap().findElement(name);
141         if (value != null) {
142             return value;
143         }
144         else {
145             if (inMapping && !this.getTableMapping().containsVariableName(name))
146                 throw new HBqlException("Invalid variable name "
147                                         + this.getTableMapping().getMappingName() + "." + name);
148             final ColumnValue columnValue = new ColumnValue(name);
149             this.addElement(columnValue);
150             return columnValue;
151         }
152     }
153 
154     private UnMappedValueMap getUnMappedValueMap(final String name,
155                                                  final boolean createNewIfMissing) throws HBqlException {
156         final UnMappedValueMap value = this.getUnMappedValuesMap().findElement(name);
157         if (value != null) {
158             return value;
159         }
160         else {
161             if (createNewIfMissing) {
162                 final UnMappedValueMap val = new UnMappedValueMap(name);
163                 this.addElement(val);
164                 return val;
165             }
166             else {
167                 return null;
168             }
169         }
170     }
171 
172     // Current Object values
173     public void setCurrentValue(final String family,
174                                 final String column,
175                                 final long timestamp,
176                                 final Object val) throws HBqlException {
177         final ColumnAttrib attrib = this.getTableMapping().getAttribFromFamilyQualifiedName(family, column);
178         if (attrib == null)
179             throw new HBqlException("Invalid column name " + family + ":" + column);
180         this.setCurrentValue(attrib.getAliasName(), timestamp, val, true);
181     }
182 
183     public boolean isCurrentValueSet(final ColumnAttrib attrib) throws HBqlException {
184         final ColumnValue columnValue = this.getColumnValuesMap().findElement(attrib.getAliasName());
185         return columnValue != null && columnValue.isValueSet();
186     }
187 
188     public void setCurrentValue(final String name,
189                                 final long timestamp,
190                                 final Object val,
191                                 final boolean inMapping) throws HBqlException {
192         this.getColumnValue(name, inMapping).setCurrentValue(timestamp, val);
193     }
194 
195     public void setVersionValue(final String familyName,
196                                 final String columnName,
197                                 final long timestamp,
198                                 final Object val,
199                                 final boolean inMapping) throws HBqlException {
200         final ColumnAttrib attrib = this.getTableMapping().getAttribFromFamilyQualifiedName(familyName, columnName);
201         if (attrib == null)
202             throw new HBqlException("Invalid column name " + familyName + ":" + columnName);
203 
204         this.getColumnValue(attrib.getColumnName(), inMapping).getVersionMap().put(timestamp, val);
205     }
206 
207     public void setUnMappedCurrentValue(final String familyName,
208                                         final String columnName,
209                                         final long timestamp,
210                                         final byte[] val) throws HBqlException {
211         this.getUnMappedValueMap(familyName, true).setCurrentValueMap(timestamp, columnName, val);
212     }
213 
214     public void setUnMappedVersionMap(final String familyName,
215                                       final String columnName,
216                                       final NavigableMap<Long, byte[]> val) throws HBqlException {
217         this.getUnMappedValueMap(familyName, true).setVersionMap(columnName, val);
218     }
219 
220     public void reset() {
221         this.atomicColumnValuesMap = null;
222         this.atomicUnMappedValuesMap = null;
223     }
224 
225     public void setTimestamp(final long timestamp) {
226         this.timestamp = timestamp;
227     }
228 
229     public void setCurrentValue(final String name, final Object val) throws HBqlException {
230         this.setCurrentValue(name, this.getTimestamp(), val, true);
231     }
232 
233     public boolean isColumnDefined(final String name) throws HBqlException {
234         return this.getColumnValuesMap().findElement(name) != null;
235     }
236 
237     public Object getCurrentValue(final String name) throws HBqlException {
238 
239         final ColumnValue columnValue = this.getColumnValuesMap().findElement(name);
240         if (columnValue != null) {
241             final Object retval = columnValue.getCurrentValue();
242             if (retval != null) {
243                 // Check if Date value
244                 if (retval instanceof Long) {
245                     final ColumnAttrib att = this.getMappingContext().getResultAccessor().getColumnAttribByName(name);
246                     if (att != null && att.getFieldType() == FieldType.DateType)
247                         return new Date((Long)retval);
248                 }
249                 return retval;
250             }
251         }
252 
253         // Return default value if it exists
254         final ColumnAttrib attrib = this.getMappingContext().getResultAccessor().getColumnAttribByName(name);
255         return (attrib != null) ? attrib.getDefaultValue() : null;
256     }
257 
258     public Set<String> getColumnNameList() throws HBqlException {
259         return this.getColumnValuesMap().keySet();
260     }
261 
262     public Map<Long, Object> getVersionMap(final String name) throws HBqlException {
263         final ColumnValue value = this.getColumnValuesMap().findElement(name);
264         return (value != null) ? value.getVersionMap() : null;
265     }
266 
267     public Map<String, byte[]> getUnMappedValueMap(final String name) throws HBqlException {
268 
269         final UnMappedValueMap value = this.getUnMappedValueMap(name, false);
270         if (value == null)
271             return null;
272 
273         final Map<String, byte[]> retval = Maps.newHashMap();
274         for (final String key : value.getCurrentAndVersionMap().keySet())
275             retval.put(key, value.getCurrentAndVersionMap().get(key).getCurrentValue());
276         return retval;
277     }
278 
279     public Map<String, NavigableMap<Long, byte[]>> getUnMappedVersionMap(final String name) throws HBqlException {
280 
281         final UnMappedValueMap value = this.getUnMappedValueMap(name, false);
282         if (value == null)
283             return null;
284 
285         final Map<String, NavigableMap<Long, byte[]>> retval = Maps.newHashMap();
286         for (final String key : value.getCurrentAndVersionMap().keySet())
287             retval.put(key, value.getCurrentAndVersionMap().get(key).getVersionMap());
288         return retval;
289     }
290 }