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 */
018
019package org.apache.hadoop.hbase;
020
021import java.util.Collections;
022import java.util.Comparator;
023import java.util.HashSet;
024import java.util.Map;
025import java.util.Set;
026import java.util.TreeMap;
027import java.util.TreeSet;
028
029import org.apache.hadoop.hbase.util.Bytes;
030import org.apache.yetus.audience.InterfaceAudience;
031
032/**
033 * Namespace POJO class. Used to represent and define namespaces.
034 *
035 * Descriptors will be persisted in an hbase table.
036 * This works since namespaces are essentially metadata of a group of tables
037 * as opposed to a more tangible container.
038 */
039@InterfaceAudience.Public
040public class NamespaceDescriptor {
041
042  /** System namespace name. */
043  public static final byte [] SYSTEM_NAMESPACE_NAME = Bytes.toBytes("hbase");
044  public static final String SYSTEM_NAMESPACE_NAME_STR =
045      Bytes.toString(SYSTEM_NAMESPACE_NAME);
046  /** Default namespace name. */
047  public static final byte [] DEFAULT_NAMESPACE_NAME = Bytes.toBytes("default");
048  public static final String DEFAULT_NAMESPACE_NAME_STR =
049      Bytes.toString(DEFAULT_NAMESPACE_NAME);
050
051  public static final NamespaceDescriptor DEFAULT_NAMESPACE = NamespaceDescriptor.create(
052    DEFAULT_NAMESPACE_NAME_STR).build();
053  public static final NamespaceDescriptor SYSTEM_NAMESPACE = NamespaceDescriptor.create(
054    SYSTEM_NAMESPACE_NAME_STR).build();
055
056  public final static Set<String> RESERVED_NAMESPACES;
057  static {
058    Set<String> set = new HashSet<>();
059    set.add(NamespaceDescriptor.DEFAULT_NAMESPACE_NAME_STR);
060    set.add(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR);
061    RESERVED_NAMESPACES = Collections.unmodifiableSet(set);
062  }
063  public final static Set<byte[]> RESERVED_NAMESPACES_BYTES;
064  static {
065    Set<byte[]> set = new TreeSet<>(Bytes.BYTES_RAWCOMPARATOR);
066    for(String name: RESERVED_NAMESPACES) {
067      set.add(Bytes.toBytes(name));
068    }
069    RESERVED_NAMESPACES_BYTES = Collections.unmodifiableSet(set);
070  }
071
072  private String name;
073  private Map<String, String> configuration;
074
075  public static final Comparator<NamespaceDescriptor> NAMESPACE_DESCRIPTOR_COMPARATOR =
076      new Comparator<NamespaceDescriptor>() {
077    @Override
078    public int compare(NamespaceDescriptor namespaceDescriptor,
079        NamespaceDescriptor namespaceDescriptor2) {
080      return namespaceDescriptor.getName().compareTo(namespaceDescriptor2.getName());
081    }
082  };
083
084  private NamespaceDescriptor() {
085  }
086
087  private NamespaceDescriptor(String name) {
088    this.name = name;
089  }
090
091  public String getName() {
092    return name;
093  }
094
095  /**
096   * Getter for accessing the configuration value by key
097   */
098  public String getConfigurationValue(String key) {
099    return configuration.get(key);
100  }
101
102  /**
103   * Getter for fetching an unmodifiable {@link #configuration} map.
104   */
105  public Map<String, String> getConfiguration() {
106    // shallow pointer copy
107    return Collections.unmodifiableMap(configuration);
108  }
109
110  /**
111   * Setter for storing a configuration setting in {@link #configuration} map.
112   * @param key Config key. Same as XML config key e.g. hbase.something.or.other.
113   * @param value String value. If null, removes the setting.
114   */
115  public void setConfiguration(String key, String value) {
116    if (value == null) {
117      removeConfiguration(key);
118    } else {
119      configuration.put(key, value);
120    }
121  }
122
123  /**
124   * Remove a config setting represented by the key from the {@link #configuration} map
125   */
126  public void removeConfiguration(final String key) {
127    configuration.remove(key);
128  }
129
130  @Override
131  public String toString() {
132    StringBuilder s = new StringBuilder();
133    s.append('{');
134    s.append(HConstants.NAME);
135    s.append(" => '");
136    s.append(name);
137    s.append("'");
138    for (Map.Entry<String, String> e : configuration.entrySet()) {
139      String key = e.getKey();
140      String value = e.getValue();
141      if (key == null) {
142        continue;
143      }
144      s.append(", ");
145      s.append(key);
146      s.append(" => '");
147      s.append(value);
148      s.append("'");
149    }
150    s.append('}');
151    return s.toString();
152  }
153
154  public static Builder create(String name) {
155    return new Builder(name);
156  }
157
158  public static Builder create(NamespaceDescriptor ns) {
159    return new Builder(ns);
160  }
161
162  @InterfaceAudience.Public
163  public static class Builder {
164    private String bName;
165    private Map<String, String> bConfiguration = new TreeMap<>();
166
167    private Builder(NamespaceDescriptor ns) {
168      this.bName = ns.name;
169      this.bConfiguration = ns.configuration;
170    }
171
172    private Builder(String name) {
173      this.bName = name;
174    }
175
176    public Builder addConfiguration(Map<String, String> configuration) {
177      this.bConfiguration.putAll(configuration);
178      return this;
179    }
180
181    public Builder addConfiguration(String key, String value) {
182      this.bConfiguration.put(key, value);
183      return this;
184    }
185
186    public Builder removeConfiguration(String key) {
187      this.bConfiguration.remove(key);
188      return this;
189    }
190
191    public NamespaceDescriptor build() {
192      if (this.bName == null){
193         throw new IllegalArgumentException("A name has to be specified in a namespace.");
194      }
195
196      NamespaceDescriptor desc = new NamespaceDescriptor(this.bName);
197      desc.configuration = this.bConfiguration;
198      return desc;
199    }
200  }
201}