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