/**
* Copyright 2016 Yahoo Inc.
*
* Licensed 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 com.yahoo.pulsar.common.naming;
import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI;
import java.net.URISyntaxException;
import com.google.common.base.Objects;
public class NamespaceName implements ServiceUnitId {
private final String namespace;
private String property;
private String cluster;
private String localName;
public NamespaceName(String namespace) {
try {
checkNotNull(namespace);
} catch (NullPointerException e) {
throw new IllegalArgumentException("Invalid null namespace: " + namespace);
}
// Verify it's a proper namespace
validateNamespaceName(namespace);
this.namespace = namespace;
}
public NamespaceName(String property, String cluster, String namespace) {
validateNamespaceName(property, cluster, namespace);
this.namespace = property + '/' + cluster + '/' + namespace;
this.property = property;
this.cluster = cluster;
this.localName = namespace;
}
public String getProperty() {
return property;
}
public String getCluster() {
return cluster;
}
public String getLocalName() {
return localName;
}
public boolean isGlobal() {
return "global".equals(cluster);
}
public String getPersistentTopicName(String localTopic) {
return getDestinationName(DestinationDomain.persistent, localTopic);
}
/**
* Compose the destination name from namespace + destination
*
* @param domain
* @param destination
* @return
*/
String getDestinationName(DestinationDomain domain, String destination) {
try {
checkNotNull(domain);
NamedEntity.checkName(destination);
return String.format("%s://%s/%s", domain.toString(), namespace, destination);
} catch (NullPointerException e) {
throw new IllegalArgumentException("Null pointer is invalid as domain for destination.", e);
}
}
@Override
public String toString() {
return namespace;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof NamespaceName) {
NamespaceName other = (NamespaceName) obj;
return Objects.equal(namespace, other.namespace);
}
return false;
}
@Override
public int hashCode() {
return namespace.hashCode();
}
public static void validateNamespaceName(String property, String cluster, String namespace) {
try {
checkNotNull(property);
checkNotNull(cluster);
checkNotNull(namespace);
if (property.isEmpty() || cluster.isEmpty() || namespace.isEmpty()) {
throw new IllegalArgumentException(
String.format("Invalid namespace format. namespace: %s/%s/%s", property, cluster, namespace));
}
NamedEntity.checkName(property);
NamedEntity.checkName(cluster);
NamedEntity.checkName(namespace);
} catch (NullPointerException e) {
throw new IllegalArgumentException(
String.format("Invalid namespace format. namespace: %s/%s/%s", property, cluster, namespace), e);
}
}
private void validateNamespaceName(String namespace) {
// assume the namespace is in the form of <property>/<cluster>/<namespace>
try {
checkNotNull(namespace);
String testUrl = String.format("http://%s", namespace);
URI uri = new URI(testUrl);
checkNotNull(uri.getPath());
NamedEntity.checkURI(uri, testUrl);
String[] parts = uri.getPath().split("/");
if (parts.length != 3) {
throw new IllegalArgumentException("Invalid namespace format. namespace: " + namespace);
}
validateNamespaceName(uri.getHost(), parts[1], parts[2]);
property = uri.getHost();
cluster = parts[1];
localName = parts[2];
} catch (URISyntaxException e) {
throw new IllegalArgumentException("Invalid namespace format. namespace: " + namespace, e);
} catch (NullPointerException e) {
throw new IllegalArgumentException("Invalid namespace format. namespace: " + namespace, e);
}
}
@Override
public NamespaceName getNamespaceObject() {
return this;
}
@Override
public boolean includes(DestinationName dn) {
return this.equals(dn.getNamespaceObject());
}
}