View Javadoc

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