001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.rest.model;
019
020import java.io.IOException;
021import java.io.Serializable;
022import java.util.HashMap;
023import java.util.List;
024import java.util.Map;
025import javax.xml.bind.annotation.XmlAccessType;
026import javax.xml.bind.annotation.XmlAccessorType;
027import javax.xml.bind.annotation.XmlRootElement;
028import javax.xml.bind.annotation.XmlTransient;
029import org.apache.hadoop.hbase.NamespaceDescriptor;
030import org.apache.hadoop.hbase.client.Admin;
031import org.apache.hadoop.hbase.rest.ProtobufMessageHandler;
032import org.apache.hadoop.hbase.rest.RestUtil;
033import org.apache.yetus.audience.InterfaceAudience;
034
035import org.apache.hbase.thirdparty.com.google.protobuf.CodedInputStream;
036import org.apache.hbase.thirdparty.com.google.protobuf.Message;
037
038import org.apache.hadoop.hbase.shaded.rest.protobuf.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  /**
070   * Constructor to use if namespace does not exist in HBASE.
071   * @param namespaceName the namespace name.
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   */
082  public NamespacesInstanceModel(Admin admin, String namespaceName) throws IOException {
083    this.namespaceName = namespaceName;
084    if (admin == null) {
085      return;
086    }
087
088    NamespaceDescriptor nd = admin.getNamespaceDescriptor(namespaceName);
089
090    // For properly formed JSON, if no properties, field has to be null (not just no elements).
091    if (nd.getConfiguration().isEmpty()) {
092      return;
093    }
094
095    properties = new HashMap<>();
096    properties.putAll(nd.getConfiguration());
097  }
098
099  /**
100   * Add property to the namespace.
101   * @param key   attribute name
102   * @param value attribute value
103   */
104  public void addProperty(String key, String value) {
105    if (properties == null) {
106      properties = new HashMap<>();
107    }
108    properties.put(key, value);
109  }
110
111  /** Returns The map of uncategorized namespace properties. */
112  public Map<String, String> getProperties() {
113    if (properties == null) {
114      properties = new HashMap<>();
115    }
116    return properties;
117  }
118
119  public String getNamespaceName() {
120    return namespaceName;
121  }
122
123  /*
124   * (non-Javadoc)
125   * @see java.lang.Object#toString()
126   */
127  @Override
128  public String toString() {
129    StringBuilder sb = new StringBuilder();
130    sb.append("{NAME => \'");
131    sb.append(namespaceName);
132    sb.append("\'");
133    if (properties != null) {
134      for (Map.Entry<String, String> entry : properties.entrySet()) {
135        sb.append(", ");
136        sb.append(entry.getKey());
137        sb.append(" => '");
138        sb.append(entry.getValue());
139        sb.append("\'");
140      }
141    }
142    sb.append("}");
143    return sb.toString();
144  }
145
146  @Override
147  public Message messageFromObject() {
148    NamespaceProperties.Builder builder = NamespaceProperties.newBuilder();
149    if (properties != null) {
150      for (Map.Entry<String, String> entry : properties.entrySet()) {
151        String key = entry.getKey();
152        NamespaceProperties.Property.Builder property = NamespaceProperties.Property.newBuilder();
153        property.setKey(key);
154        property.setValue(entry.getValue());
155        builder.addProps(property);
156      }
157    }
158    return builder.build();
159  }
160
161  @Override
162  public ProtobufMessageHandler getObjectFromMessage(CodedInputStream cis) throws IOException {
163    NamespaceProperties.Builder builder = NamespaceProperties.newBuilder();
164    RestUtil.mergeFrom(builder, cis);
165    List<NamespaceProperties.Property> properties = builder.getPropsList();
166    for (NamespaceProperties.Property property : properties) {
167      addProperty(property.getKey(), property.getValue());
168    }
169    return this;
170  }
171
172}