View Javadoc

1   /*
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  
20  package org.apache.hadoop.hbase.rest.model;
21  
22  import java.io.IOException;
23  import java.io.Serializable;
24  import java.util.ArrayList;
25  import java.util.HashMap;
26  import java.util.Iterator;
27  import java.util.List;
28  import java.util.Map;
29  
30  import javax.xml.bind.annotation.XmlAnyAttribute;
31  import javax.xml.bind.annotation.XmlAttribute;
32  import javax.xml.bind.annotation.XmlElement;
33  import javax.xml.bind.annotation.XmlRootElement;
34  import javax.xml.namespace.QName;
35  
36  import org.apache.hadoop.classification.InterfaceAudience;
37  import org.apache.hadoop.hbase.HColumnDescriptor;
38  import org.apache.hadoop.hbase.HConstants;
39  import org.apache.hadoop.hbase.HTableDescriptor;
40  import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
41  import org.apache.hadoop.hbase.rest.ProtobufMessageHandler;
42  import org.apache.hadoop.hbase.rest.protobuf.generated.ColumnSchemaMessage.ColumnSchema;
43  import org.apache.hadoop.hbase.rest.protobuf.generated.TableSchemaMessage.TableSchema;
44  import org.apache.hadoop.hbase.util.Bytes;
45  
46  /**
47   * A representation of HBase table descriptors.
48   * 
49   * <pre>
50   * &lt;complexType name="TableSchema"&gt;
51   *   &lt;sequence&gt;
52   *     &lt;element name="column" type="tns:ColumnSchema" 
53   *       maxOccurs="unbounded" minOccurs="1"&gt;&lt;/element&gt;
54   *   &lt;/sequence&gt;
55   *   &lt;attribute name="name" type="string"&gt;&lt;/attribute&gt;
56   *   &lt;anyAttribute&gt;&lt;/anyAttribute&gt;
57   * &lt;/complexType&gt;
58   * </pre>
59   */
60  @XmlRootElement(name="TableSchema")
61  @InterfaceAudience.Private
62  public class TableSchemaModel implements Serializable, ProtobufMessageHandler {
63    private static final long serialVersionUID = 1L;
64    private static final QName IS_META = new QName(HTableDescriptor.IS_META);
65    private static final QName IS_ROOT = new QName(HTableDescriptor.IS_ROOT);
66    private static final QName READONLY = new QName(HTableDescriptor.READONLY);
67    private static final QName TTL = new QName(HColumnDescriptor.TTL);
68    private static final QName VERSIONS = new QName(HConstants.VERSIONS);
69    private static final QName COMPRESSION = 
70      new QName(HColumnDescriptor.COMPRESSION);
71  
72    private String name;
73    private Map<QName,Object> attrs = new HashMap<QName,Object>();
74    private List<ColumnSchemaModel> columns = new ArrayList<ColumnSchemaModel>();
75    
76    /**
77     * Default constructor.
78     */
79    public TableSchemaModel() {}
80  
81    /**
82     * Constructor
83     * @param htd the table descriptor
84     */
85    public TableSchemaModel(HTableDescriptor htd) {
86      setName(htd.getNameAsString());
87      for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> e:
88          htd.getValues().entrySet()) {
89        addAttribute(Bytes.toString(e.getKey().get()), 
90          Bytes.toString(e.getValue().get()));
91      }
92      for (HColumnDescriptor hcd: htd.getFamilies()) {
93        ColumnSchemaModel columnModel = new ColumnSchemaModel();
94        columnModel.setName(hcd.getNameAsString());
95        for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> e:
96            hcd.getValues().entrySet()) {
97          columnModel.addAttribute(Bytes.toString(e.getKey().get()), 
98              Bytes.toString(e.getValue().get()));
99        }
100       addColumnFamily(columnModel);
101     }
102   }
103 
104   /**
105    * Add an attribute to the table descriptor
106    * @param name attribute name
107    * @param value attribute value
108    */
109   public void addAttribute(String name, Object value) {
110     attrs.put(new QName(name), value);
111   }
112 
113   /**
114    * Return a table descriptor value as a string. Calls toString() on the
115    * object stored in the descriptor value map.
116    * @param name the attribute name
117    * @return the attribute value
118    */
119   public String getAttribute(String name) {
120     Object o = attrs.get(new QName(name));
121     return o != null ? o.toString() : null;
122   }
123 
124   /**
125    * Add a column family to the table descriptor
126    * @param family the column family model
127    */
128   public void addColumnFamily(ColumnSchemaModel family) {
129     columns.add(family);
130   }
131 
132   /**
133    * Retrieve the column family at the given index from the table descriptor
134    * @param index the index
135    * @return the column family model
136    */
137   public ColumnSchemaModel getColumnFamily(int index) {
138     return columns.get(index);
139   }
140 
141   /**
142    * @return the table name
143    */
144   @XmlAttribute
145   public String getName() {
146     return name;
147   }
148 
149   /**
150    * @return the map for holding unspecified (user) attributes
151    */
152   @XmlAnyAttribute
153   public Map<QName,Object> getAny() {
154     return attrs;
155   }
156 
157   /**
158    * @return the columns
159    */
160   @XmlElement(name="ColumnSchema")
161   public List<ColumnSchemaModel> getColumns() {
162     return columns;
163   }
164 
165   /**
166    * @param name the table name
167    */
168   public void setName(String name) {
169     this.name = name;
170   }
171 
172   /**
173    * @param columns the columns to set
174    */
175   public void setColumns(List<ColumnSchemaModel> columns) {
176     this.columns = columns;
177   }
178 
179   /* (non-Javadoc)
180    * @see java.lang.Object#toString()
181    */
182   @Override
183   public String toString() {
184     StringBuilder sb = new StringBuilder();
185     sb.append("{ NAME=> '");
186     sb.append(name);
187     sb.append('\'');
188     for (Map.Entry<QName,Object> e: attrs.entrySet()) {
189       sb.append(", ");
190       sb.append(e.getKey().getLocalPart());
191       sb.append(" => '");
192       sb.append(e.getValue().toString());
193       sb.append('\'');
194     }
195     sb.append(", COLUMNS => [ ");
196     Iterator<ColumnSchemaModel> i = columns.iterator();
197     while (i.hasNext()) {
198       ColumnSchemaModel family = i.next();
199       sb.append(family.toString());
200       if (i.hasNext()) {
201         sb.append(',');
202       }
203       sb.append(' ');
204     }
205     sb.append("] }");
206     return sb.toString();
207   }
208 
209   // getters and setters for common schema attributes
210 
211   // cannot be standard bean type getters and setters, otherwise this would
212   // confuse JAXB
213 
214   /**
215    * @return true if IS_META attribute exists and is truel
216    */
217   public boolean __getIsMeta() {
218     Object o = attrs.get(IS_META);
219     return o != null ? Boolean.valueOf(o.toString()) : false;
220   }
221 
222   /**
223    * @return true if IS_ROOT attribute exists and is truel
224    */
225   public boolean __getIsRoot() {
226     Object o = attrs.get(IS_ROOT);
227     return o != null ? Boolean.valueOf(o.toString()) : false;
228   }
229 
230   /**
231    * @return true if READONLY attribute exists and is truel
232    */
233   public boolean __getReadOnly() {
234     Object o = attrs.get(READONLY);
235     return o != null ? 
236       Boolean.valueOf(o.toString()) : HTableDescriptor.DEFAULT_READONLY;
237   }
238 
239   /**
240    * @param value desired value of IS_META attribute
241    */
242   public void __setIsMeta(boolean value) {
243     attrs.put(IS_META, Boolean.toString(value));
244   }
245 
246   /**
247    * @param value desired value of IS_ROOT attribute
248    */
249   public void __setIsRoot(boolean value) {
250     attrs.put(IS_ROOT, Boolean.toString(value));
251   }
252 
253   /**
254    * @param value desired value of READONLY attribute
255    */
256   public void __setReadOnly(boolean value) {
257     attrs.put(READONLY, Boolean.toString(value));
258   }
259 
260   @Override
261   public byte[] createProtobufOutput() {
262     TableSchema.Builder builder = TableSchema.newBuilder();
263     builder.setName(name);
264     for (Map.Entry<QName, Object> e: attrs.entrySet()) {
265       TableSchema.Attribute.Builder attrBuilder = 
266         TableSchema.Attribute.newBuilder();
267       attrBuilder.setName(e.getKey().getLocalPart());
268       attrBuilder.setValue(e.getValue().toString());
269       builder.addAttrs(attrBuilder);
270     }
271     for (ColumnSchemaModel family: columns) {
272       Map<QName, Object> familyAttrs = family.getAny();
273       ColumnSchema.Builder familyBuilder = ColumnSchema.newBuilder();
274       familyBuilder.setName(family.getName());
275       for (Map.Entry<QName, Object> e: familyAttrs.entrySet()) {
276         ColumnSchema.Attribute.Builder attrBuilder = 
277           ColumnSchema.Attribute.newBuilder();
278         attrBuilder.setName(e.getKey().getLocalPart());
279         attrBuilder.setValue(e.getValue().toString());
280         familyBuilder.addAttrs(attrBuilder);
281       }
282       if (familyAttrs.containsKey(TTL)) {
283         familyBuilder.setTtl(
284           Integer.valueOf(familyAttrs.get(TTL).toString()));
285       }
286       if (familyAttrs.containsKey(VERSIONS)) {
287         familyBuilder.setMaxVersions(
288           Integer.valueOf(familyAttrs.get(VERSIONS).toString()));
289       }
290       if (familyAttrs.containsKey(COMPRESSION)) {
291         familyBuilder.setCompression(familyAttrs.get(COMPRESSION).toString());
292       }
293       builder.addColumns(familyBuilder);
294     }
295     if (attrs.containsKey(READONLY)) {
296       builder.setReadOnly(
297         Boolean.valueOf(attrs.get(READONLY).toString()));
298     }
299     return builder.build().toByteArray();
300   }
301 
302   @Override
303   public ProtobufMessageHandler getObjectFromMessage(byte[] message) 
304       throws IOException {
305     TableSchema.Builder builder = TableSchema.newBuilder();
306     builder.mergeFrom(message);
307     this.setName(builder.getName());
308     for (TableSchema.Attribute attr: builder.getAttrsList()) {
309       this.addAttribute(attr.getName(), attr.getValue());
310     }
311     if (builder.hasReadOnly()) {
312       this.addAttribute(HTableDescriptor.READONLY, builder.getReadOnly());
313     }
314     for (ColumnSchema family: builder.getColumnsList()) {
315       ColumnSchemaModel familyModel = new ColumnSchemaModel();
316       familyModel.setName(family.getName());
317       for (ColumnSchema.Attribute attr: family.getAttrsList()) {
318         familyModel.addAttribute(attr.getName(), attr.getValue());
319       }
320       if (family.hasTtl()) {
321         familyModel.addAttribute(HColumnDescriptor.TTL, family.getTtl());
322       }
323       if (family.hasMaxVersions()) {
324         familyModel.addAttribute(HConstants.VERSIONS,
325           family.getMaxVersions());
326       }
327       if (family.hasCompression()) {
328         familyModel.addAttribute(HColumnDescriptor.COMPRESSION,
329           family.getCompression());
330       }
331       this.addColumnFamily(familyModel);
332     }
333     return this;
334   }
335 
336   /**
337    * @return a table descriptor
338    */
339   public HTableDescriptor getTableDescriptor() {
340     HTableDescriptor htd = new HTableDescriptor(getName());
341     for (Map.Entry<QName, Object> e: getAny().entrySet()) {
342       htd.setValue(e.getKey().getLocalPart(), e.getValue().toString());
343     }
344     for (ColumnSchemaModel column: getColumns()) {
345       HColumnDescriptor hcd = new HColumnDescriptor(column.getName());
346       for (Map.Entry<QName, Object> e: column.getAny().entrySet()) {
347         hcd.setValue(e.getKey().getLocalPart(), e.getValue().toString());
348       }
349       htd.addFamily(hcd);
350     }
351     return htd;
352   }
353 
354 }