package org.cloudname.service;
import org.cloudname.core.CloudnamePath;
import org.json.JSONObject;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* A coordinate representing a running service. The coordinate consists of four parts; instance id,
* service name, tag and region.
*
* <p>Note that the order of elements in the string representation is opposite of the CloudnamePath
* class; you can't create a canonical representation of the instance coordinate by calling join()
* on the CloudnamePath instance.
*
* @author stalehd@gmail.com
*/
public class InstanceCoordinate {
private static final Pattern COORDINATE_PATTERN = Pattern.compile("(.*)\\.(.*)\\.(.*)\\.(.*)");
private static final String REGION_NAME = "region";
private static final String TAG_NAME = "tag";
private static final String SERVICE_NAME = "service";
private static final String INSTANCE_NAME = "instance";
private final String region;
private final String tag;
private final String service;
private final String instance;
/**
* Create new instance based on CloudnamePath.
*
* @throws IllegalArgumentException if parameters are invalid
*/
/* package-private */ InstanceCoordinate(final CloudnamePath path) {
if (path == null) {
throw new IllegalArgumentException("Path can not be null");
}
if (path.length() != 4) {
throw new IllegalArgumentException("Path must contain 4 elements");
}
this.region = path.get(0);
this.tag = path.get(1);
this.service = path.get(2);
this.instance = path.get(3);
}
/**
* The region of the coordinate.
*/
public String getRegion() {
return region;
}
/**
* The tag of the coordinate.
*/
public String getTag() {
return tag;
}
/**
* The service name.
*/
public String getService() {
return service;
}
/**
* The instance identifier.
*/
public String getInstance() {
return instance;
}
/**
* A CloudnamePath instance representing this coordinate.
*/
/* package-private */ CloudnamePath toCloudnamePath() {
return new CloudnamePath(
new String[] {this.region, this.tag, this.service, this.instance});
}
/**
* Canonical string representation of coordinate.
*/
public String toCanonicalString() {
return new StringBuffer()
.append(instance).append(".")
.append(service).append(".")
.append(tag).append(".")
.append(region)
.toString();
}
/**
* Coordinate represented as a JSON-formatted string.
*/
/* package-private */ String toJsonString() {
return new JSONObject()
.put(REGION_NAME, this.region)
.put(TAG_NAME, this.tag)
.put(SERVICE_NAME, this.service)
.put(INSTANCE_NAME, this.instance)
.toString();
}
/**
* Create InstanceCoordinate instance from JSON string.
*/
/* package-private */ static InstanceCoordinate fromJson(final String jsonString) {
final JSONObject object = new JSONObject(jsonString);
final String[] pathElements = new String[4];
pathElements[0] = object.getString(REGION_NAME);
pathElements[1] = object.getString(TAG_NAME);
pathElements[2] = object.getString(SERVICE_NAME);
pathElements[3] = object.getString(INSTANCE_NAME);
return new InstanceCoordinate(new CloudnamePath(pathElements));
}
/**
* Parse a canonical string representation of a coordinate.
*/
public static InstanceCoordinate parse(final String string) {
if (string == null) {
return null;
}
final Matcher matcher = COORDINATE_PATTERN.matcher(string);
if (!matcher.matches()) {
return null;
}
final String[] path = new String[] {
matcher.group(4), matcher.group(3), matcher.group(2), matcher.group(1)
};
return new InstanceCoordinate(new CloudnamePath(path));
}
@Override
public String toString() {
return "[ Coordinate " + toCanonicalString() + "]";
}
}