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