001/*
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements.  See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership.  The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License.  You may obtain a copy of the License at
010 *
011 *     http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 */
019
020package org.apache.hadoop.hbase.rest.model;
021
022import java.io.IOException;
023import java.io.Serializable;
024import java.util.HashMap;
025import java.util.List;
026import java.util.Map;
027
028import javax.xml.bind.annotation.XmlAccessType;
029import javax.xml.bind.annotation.XmlAccessorType;
030import javax.xml.bind.annotation.XmlRootElement;
031import javax.xml.bind.annotation.XmlTransient;
032
033import org.apache.hadoop.hbase.NamespaceDescriptor;
034import org.apache.yetus.audience.InterfaceAudience;
035import org.apache.hadoop.hbase.client.Admin;
036import org.apache.hadoop.hbase.rest.ProtobufMessageHandler;
037import org.apache.hadoop.hbase.rest.protobuf
038  .generated.NamespacePropertiesMessage.NamespaceProperties;
039
040/**
041 * List a HBase namespace's key/value properties.
042 * <ul>
043 * <li>NamespaceProperties: outer element</li>
044 * <li>properties: sequence property elements</li>
045 * <li>entry</li>
046 * <li>key: property key</li>
047 * <li>value: property value</li>
048 * </ul>
049 */
050@XmlRootElement(name="NamespaceProperties")
051@XmlAccessorType(XmlAccessType.FIELD)
052@InterfaceAudience.Private
053public class NamespacesInstanceModel implements Serializable, ProtobufMessageHandler {
054
055  private static final long serialVersionUID = 1L;
056
057  // JAX-RS automatically converts Map to XMLAnyElement.
058  private Map<String,String> properties = null;
059
060  @XmlTransient
061  private String namespaceName;
062
063  /**
064   * Default constructor. Do not use.
065   */
066  public NamespacesInstanceModel() {}
067
068  /**
069   * Constructor to use if namespace does not exist in HBASE.
070   * @param namespaceName the namespace name.
071   * @throws IOException
072   */
073  public NamespacesInstanceModel(String namespaceName) throws IOException {
074    this(null, namespaceName);
075  }
076
077  /**
078   * Constructor
079   * @param admin the administrative API
080   * @param namespaceName the namespace name.
081   * @throws IOException
082   */
083  public NamespacesInstanceModel(Admin admin, String namespaceName) throws IOException {
084    this.namespaceName = namespaceName;
085    if(admin == null) { return; }
086
087    NamespaceDescriptor nd = admin.getNamespaceDescriptor(namespaceName);
088
089    // For properly formed JSON, if no properties, field has to be null (not just no elements).
090    if(nd.getConfiguration().isEmpty()){ return; }
091
092    properties = new HashMap<>();
093    properties.putAll(nd.getConfiguration());
094  }
095
096  /**
097   * Add property to the namespace.
098   * @param key attribute name
099   * @param value attribute value
100   */
101  public void addProperty(String key, String value) {
102    if(properties == null){
103      properties = new HashMap<>();
104    }
105    properties.put(key, value);
106  }
107
108  /**
109   * @return The map of uncategorized namespace properties.
110   */
111  public Map<String,String> getProperties() {
112    if(properties == null){
113      properties = new HashMap<>();
114    }
115    return properties;
116  }
117
118  public String getNamespaceName(){
119    return namespaceName;
120  }
121
122  /* (non-Javadoc)
123   * @see java.lang.Object#toString()
124   */
125  @Override
126  public String toString() {
127    StringBuilder sb = new StringBuilder();
128    sb.append("{NAME => \'");
129    sb.append(namespaceName);
130    sb.append("\'");
131    if(properties != null){
132      for (Map.Entry<String, String> entry : properties.entrySet()) {
133        sb.append(", ");
134        sb.append(entry.getKey());
135        sb.append(" => '");
136        sb.append(entry.getValue());
137        sb.append("\'");
138      }
139    }
140    sb.append("}");
141    return sb.toString();
142  }
143
144  @Override
145  public byte[] createProtobufOutput() {
146    NamespaceProperties.Builder builder = NamespaceProperties.newBuilder();
147    if(properties != null){
148      for (Map.Entry<String, String> entry : properties.entrySet()) {
149        String key = entry.getKey();
150        NamespaceProperties.Property.Builder property = NamespaceProperties.Property.newBuilder();
151        property.setKey(key);
152        property.setValue(entry.getValue());
153        builder.addProps(property);
154      }
155    }
156    return builder.build().toByteArray();
157  }
158
159  @Override
160  public ProtobufMessageHandler getObjectFromMessage(byte[] message) throws IOException {
161    NamespaceProperties.Builder builder = NamespaceProperties.newBuilder();
162    builder.mergeFrom(message);
163    List<NamespaceProperties.Property> properties = builder.getPropsList();
164    for(NamespaceProperties.Property property: properties){
165      addProperty(property.getKey(), property.getValue());
166    }
167    return this;
168  }
169}