/* * Copyright 2010 The Apache Software Foundation * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.hadoop.hbase.rest.model; import java.io.IOException; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.xml.bind.annotation.XmlAnyAttribute; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.namespace.QName; import org.apache.hadoop.hbase.HColumnDescriptor; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.io.ImmutableBytesWritable; import org.apache.hadoop.hbase.rest.ProtobufMessageHandler; import org.apache.hadoop.hbase.rest.protobuf.generated.ColumnSchemaMessage.ColumnSchema; import org.apache.hadoop.hbase.rest.protobuf.generated.TableSchemaMessage.TableSchema; import org.apache.hadoop.hbase.util.Bytes; /** * A representation of HBase table descriptors. * * <pre> * <complexType name="TableSchema"> * <sequence> * <element name="column" type="tns:ColumnSchema" * maxOccurs="unbounded" minOccurs="1"></element> * </sequence> * <attribute name="name" type="string"></attribute> * <anyAttribute></anyAttribute> * </complexType> * </pre> */ @XmlRootElement(name="TableSchema") public class TableSchemaModel implements Serializable, ProtobufMessageHandler { private static final long serialVersionUID = 1L; private static final QName IS_META = new QName(HTableDescriptor.IS_META); private static final QName IS_ROOT = new QName(HTableDescriptor.IS_ROOT); private static final QName READONLY = new QName(HTableDescriptor.READONLY); private static final QName TTL = new QName(HColumnDescriptor.TTL); private static final QName VERSIONS = new QName(HConstants.VERSIONS); private static final QName COMPRESSION = new QName(HColumnDescriptor.COMPRESSION); private String name; private Map<QName,Object> attrs = new HashMap<QName,Object>(); private List<ColumnSchemaModel> columns = new ArrayList<ColumnSchemaModel>(); /** * Default constructor. */ public TableSchemaModel() {} /** * Constructor * @param htd the table descriptor */ public TableSchemaModel(HTableDescriptor htd) { setName(htd.getNameAsString()); for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> e: htd.getValues().entrySet()) { addAttribute(Bytes.toString(e.getKey().get()), Bytes.toString(e.getValue().get())); } for (HColumnDescriptor hcd: htd.getFamilies()) { ColumnSchemaModel columnModel = new ColumnSchemaModel(); columnModel.setName(hcd.getNameAsString()); for (Map.Entry<ImmutableBytesWritable, ImmutableBytesWritable> e: hcd.getValues().entrySet()) { columnModel.addAttribute(Bytes.toString(e.getKey().get()), Bytes.toString(e.getValue().get())); } addColumnFamily(columnModel); } } /** * Add an attribute to the table descriptor * @param name attribute name * @param value attribute value */ public void addAttribute(String name, Object value) { attrs.put(new QName(name), value); } /** * Return a table descriptor value as a string. Calls toString() on the * object stored in the descriptor value map. * @param name the attribute name * @return the attribute value */ public String getAttribute(String name) { Object o = attrs.get(new QName(name)); return o != null ? o.toString() : null; } /** * Add a column family to the table descriptor * @param family the column family model */ public void addColumnFamily(ColumnSchemaModel family) { columns.add(family); } /** * Retrieve the column family at the given index from the table descriptor * @param index the index * @return the column family model */ public ColumnSchemaModel getColumnFamily(int index) { return columns.get(index); } /** * @return the table name */ @XmlAttribute public String getName() { return name; } /** * @return the map for holding unspecified (user) attributes */ @XmlAnyAttribute public Map<QName,Object> getAny() { return attrs; } /** * @return the columns */ @XmlElement(name="ColumnSchema") public List<ColumnSchemaModel> getColumns() { return columns; } /** * @param name the table name */ public void setName(String name) { this.name = name; } /** * @param columns the columns to set */ public void setColumns(List<ColumnSchemaModel> columns) { this.columns = columns; } /* (non-Javadoc) * @see java.lang.Object#toString() */ @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("{ NAME=> '"); sb.append(name); sb.append('\''); for (Map.Entry<QName,Object> e: attrs.entrySet()) { sb.append(", "); sb.append(e.getKey().getLocalPart()); sb.append(" => '"); sb.append(e.getValue().toString()); sb.append('\''); } sb.append(", COLUMNS => [ "); Iterator<ColumnSchemaModel> i = columns.iterator(); while (i.hasNext()) { ColumnSchemaModel family = i.next(); sb.append(family.toString()); if (i.hasNext()) { sb.append(','); } sb.append(' '); } sb.append("] }"); return sb.toString(); } // getters and setters for common schema attributes // cannot be standard bean type getters and setters, otherwise this would // confuse JAXB /** * @return true if IS_META attribute exists and is truel */ public boolean __getIsMeta() { Object o = attrs.get(IS_META); return o != null ? Boolean.valueOf(o.toString()) : false; } /** * @return true if IS_ROOT attribute exists and is truel */ public boolean __getIsRoot() { Object o = attrs.get(IS_ROOT); return o != null ? Boolean.valueOf(o.toString()) : false; } /** * @return true if READONLY attribute exists and is truel */ public boolean __getReadOnly() { Object o = attrs.get(READONLY); return o != null ? Boolean.valueOf(o.toString()) : HTableDescriptor.DEFAULT_READONLY; } /** * @param value desired value of IS_META attribute */ public void __setIsMeta(boolean value) { attrs.put(IS_META, Boolean.toString(value)); } /** * @param value desired value of IS_ROOT attribute */ public void __setIsRoot(boolean value) { attrs.put(IS_ROOT, Boolean.toString(value)); } /** * @param value desired value of READONLY attribute */ public void __setReadOnly(boolean value) { attrs.put(READONLY, Boolean.toString(value)); } @Override public byte[] createProtobufOutput() { TableSchema.Builder builder = TableSchema.newBuilder(); builder.setName(name); for (Map.Entry<QName, Object> e: attrs.entrySet()) { TableSchema.Attribute.Builder attrBuilder = TableSchema.Attribute.newBuilder(); attrBuilder.setName(e.getKey().getLocalPart()); attrBuilder.setValue(e.getValue().toString()); builder.addAttrs(attrBuilder); } for (ColumnSchemaModel family: columns) { Map<QName, Object> familyAttrs = family.getAny(); ColumnSchema.Builder familyBuilder = ColumnSchema.newBuilder(); familyBuilder.setName(family.getName()); for (Map.Entry<QName, Object> e: familyAttrs.entrySet()) { ColumnSchema.Attribute.Builder attrBuilder = ColumnSchema.Attribute.newBuilder(); attrBuilder.setName(e.getKey().getLocalPart()); attrBuilder.setValue(e.getValue().toString()); familyBuilder.addAttrs(attrBuilder); } if (familyAttrs.containsKey(TTL)) { familyBuilder.setTtl( Integer.valueOf(familyAttrs.get(TTL).toString())); } if (familyAttrs.containsKey(VERSIONS)) { familyBuilder.setMaxVersions( Integer.valueOf(familyAttrs.get(VERSIONS).toString())); } if (familyAttrs.containsKey(COMPRESSION)) { familyBuilder.setCompression(familyAttrs.get(COMPRESSION).toString()); } builder.addColumns(familyBuilder); } if (attrs.containsKey(READONLY)) { builder.setReadOnly( Boolean.valueOf(attrs.get(READONLY).toString())); } return builder.build().toByteArray(); } @Override public ProtobufMessageHandler getObjectFromMessage(byte[] message) throws IOException { TableSchema.Builder builder = TableSchema.newBuilder(); builder.mergeFrom(message); this.setName(builder.getName()); for (TableSchema.Attribute attr: builder.getAttrsList()) { this.addAttribute(attr.getName(), attr.getValue()); } if (builder.hasReadOnly()) { this.addAttribute(HTableDescriptor.READONLY, builder.getReadOnly()); } for (ColumnSchema family: builder.getColumnsList()) { ColumnSchemaModel familyModel = new ColumnSchemaModel(); familyModel.setName(family.getName()); for (ColumnSchema.Attribute attr: family.getAttrsList()) { familyModel.addAttribute(attr.getName(), attr.getValue()); } if (family.hasTtl()) { familyModel.addAttribute(HColumnDescriptor.TTL, family.getTtl()); } if (family.hasMaxVersions()) { familyModel.addAttribute(HConstants.VERSIONS, family.getMaxVersions()); } if (family.hasCompression()) { familyModel.addAttribute(HColumnDescriptor.COMPRESSION, family.getCompression()); } this.addColumnFamily(familyModel); } return this; } /** * @return a table descriptor */ public HTableDescriptor getTableDescriptor() { HTableDescriptor htd = new HTableDescriptor(getName()); for (Map.Entry<QName, Object> e: getAny().entrySet()) { htd.setValue(e.getKey().getLocalPart(), e.getValue().toString()); } for (ColumnSchemaModel column: getColumns()) { HColumnDescriptor hcd = new HColumnDescriptor(column.getName()); for (Map.Entry<QName, Object> e: column.getAny().entrySet()) { hcd.setValue(e.getKey().getLocalPart(), e.getValue().toString()); } htd.addFamily(hcd); } return htd; } }