package org.cloudname.service;
import org.cloudname.core.CloudnamePath;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* A coordinate pointing to a set of services or a single permanent service.
*
* @author stalehd@gmail.com
*/
public class ServiceCoordinate {
public static class Builder {
private String region;
private String tag;
private String service;
public Builder() {
}
public Builder setRegion(final String region) {
this.region = region;
return this;
}
public Builder setTag(final String tag) {
this.tag = tag;
return this;
}
public Builder setService(final String service) {
this.service = service;
return this;
}
/**
* Initialise builder with existing @link}ServiceCoordinate} instance.
*/
public Builder fromCoordinate(final ServiceCoordinate coordinate) {
service = coordinate.getService();
tag = coordinate.getTag();
region = coordinate.getRegion();
return this;
}
/**
* Construct a ServiceCoordinate instance.
*
* @throws IllegalStateException if a valid instance can't be built
*/
public ServiceCoordinate build() {
if (region == null) {
throw new IllegalStateException("Region can't be null");
}
if (tag == null) {
throw new IllegalStateException("Tag can't be null");
}
if (service == null) {
throw new IllegalStateException("Service can't be null");
}
return new ServiceCoordinate(new CloudnamePath(new String[] {region, tag, service}));
}
}
private final String region;
private final String tag;
private final String service;
// Pattern for string parsing
private static final Pattern COORDINATE_PATTERN = Pattern.compile("(.*)\\.(.*)\\.(.*)");
/**
* Create instance from a @link{CloudnamePath} instance.
*
* @throws IllegalArgumentException if parameter is invalid
*/
/* package-private */ ServiceCoordinate(final CloudnamePath path) {
if (path == null) {
throw new IllegalArgumentException("Path can not be null");
}
if (path.length() != 3) {
throw new IllegalArgumentException("Path must have three elements");
}
region = path.get(0);
tag = path.get(1);
service = path.get(2);
}
/**
* The coordinate's region.
*/
public String getRegion() {
return region;
}
/**
* The coordinate's tag.
*/
public String getTag() {
return tag;
}
/**
* The coordinate's service name.
*/
public String getService() {
return service;
}
/**
* Parse a canonical string representation of a ServiceCoordinate.
*
* @return coordinate or null if the coordinate can't be parsed
*/
public static ServiceCoordinate parse(final String serviceCoordinateString) {
final Matcher matcher = COORDINATE_PATTERN.matcher(serviceCoordinateString);
if (!matcher.matches()) {
return null;
}
final String[] path = new String[] {matcher.group(3), matcher.group(2), matcher.group(1)};
return new ServiceCoordinate(new CloudnamePath(path));
}
/**
* CloudnamePath representing this coordinate.
*/
/* package-private */ CloudnamePath toCloudnamePath() {
return new CloudnamePath(new String[] {this.region, this.tag, this.service});
}
@Override
public boolean equals(final Object otherInstance) {
if (this == otherInstance) {
return true;
}
if (otherInstance == null || getClass() != otherInstance.getClass()) {
return false;
}
final ServiceCoordinate other = (ServiceCoordinate) otherInstance;
if (!this.region.equals(other.region)
|| !this.tag.equals(other.tag)
|| !this.service.equals(other.service)) {
return false;
}
return true;
}
@Override
public int hashCode() {
int result = region.hashCode();
result = 31 * result + tag.hashCode();
result = 31 * result + service.hashCode();
return result;
}
}