package dmg.cells.nucleus;
import com.google.common.base.MoreObjects;
import java.io.Serializable;
import java.util.Objects;
import org.dcache.util.Args;
import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Arrays.asList;
/*
* route add -default <cell>[@<domain>]
* route add -domain <domain> <cell>[@<domain>]
* WARNING : This Class is designed to be immutable.
* All other class rely on that fact and
* a lot of things may fail at runtime
* if this design item is changed.
*/
public class CellRoute implements Serializable
{
private static final long serialVersionUID = 4566260400288960984L;
private final String _destCell;
private final String _destDomain;
private final String _gateway;
private final int _type;
public static final int AUTO = 0;
public static final int EXACT = 1;
public static final int QUEUE = 2;
public static final int DOMAIN = 3;
public static final int DEFAULT = 4;
public static final int DUMPSTER = 5;
public static final int ALIAS = 6;
public static final int TOPIC = 7;
private static final String[] TYPE_NAMES =
{"Auto", "Exact", "Queue", "Domain",
"Default", "Dumpster", "Alias", "Topic"};
private static int getTypeOf(Args args)
{
if (args.argc() == 0) {
throw new IllegalArgumentException("Not enough arguments");
}
String opt = (args.optc() == 0) ? "-auto" : args.optv(0);
int type = AUTO;
switch (opt) {
case "auto":
type = AUTO;
break;
case "domain":
type = DOMAIN;
break;
case "wellknown":
case "queue":
type = QUEUE;
break;
case "exact":
type = EXACT;
break;
case "default":
type = DEFAULT;
break;
case "dumpster":
type = DUMPSTER;
break;
case "alias":
type = ALIAS;
break;
case "topic":
type = TOPIC;
break;
}
switch (args.argc()) {
case 1:
if (type != DEFAULT && type != DUMPSTER) {
throw new IllegalArgumentException("Not enough arguments");
}
break;
case 2:
if (type == DEFAULT || type == DUMPSTER) {
throw new IllegalArgumentException("Too many arguments");
}
break;
default:
throw new IllegalArgumentException("Too many arguments");
}
return type;
}
private static int getTypeOf(String type)
{
int i = asList(TYPE_NAMES).indexOf(type);
if (i == -1) {
throw new IllegalArgumentException("Illegal Route Type: " + type);
}
return i;
}
public CellRoute(Args args)
throws IllegalArgumentException
{
this((args.argc() != 2) ? null : args.argv(0),
(args.argc() != 2) ? args.argv(0) : args.argv(1),
getTypeOf(args));
}
public CellRoute(String dest, CellAddressCore gateway, int type)
throws IllegalArgumentException
{
this(dest, gateway.toString(), type);
}
public CellRoute(String dest, String gateway, String type)
throws IllegalArgumentException
{
this(dest, gateway, getTypeOf(type));
}
public CellRoute(String dest, String gateway, int type)
throws IllegalArgumentException
{
_gateway = gateway;
String cell, domain;
if (dest == null || dest.isEmpty()) {
cell = null;
domain = null;
} else {
int ind = dest.indexOf('@');
if (ind < 0) {
cell = dest;
domain = null;
} else {
cell = dest.substring(0, ind);
if (ind == (dest.length() - 1)) {
domain = null;
} else {
domain = dest.substring(ind + 1);
}
}
}
switch (type) {
case EXACT:
case ALIAS:
checkArgument(cell != null, "No destination cell spec.");
_destCell = cell;
_destDomain = (domain == null) ? "local" : domain;
_type = type;
break;
case QUEUE:
checkArgument(cell != null, "No destination cell spec.");
checkArgument(domain == null, "QUEUE doesn't accept domain");
_destCell = cell;
_destDomain = "*";
_type = type;
break;
case TOPIC:
checkArgument(cell != null, "No destination cell spec.");
checkArgument(domain == null, "TOPIC doesn't accept domain");
_destCell = cell;
_destDomain = "*";
_type = type;
break;
case DOMAIN:
checkArgument(domain == null, "DOMAIN doesn't accept cell");
checkArgument(cell != null, "No destination domain spec.");
_destDomain = cell;
_destCell = "*";
_type = type;
break;
case DUMPSTER:
checkArgument(cell == null, "DUMPSTER doesn't accept cell");
checkArgument(domain == null, "DUMPSTER doesn't accept domain");
_destDomain = "*";
_destCell = "*";
_type = type;
break;
case DEFAULT:
checkArgument(cell == null, "DEFAULT doesn't accept cell");
checkArgument(domain == null, "DEFAULT doesn't accept domain");
_destDomain = "*";
_destCell = "*";
_type = type;
break;
case AUTO:
if ((cell != null) && (domain != null)) {
if (cell.equals("*") && domain.equals("*")) {
_type = DEFAULT;
} else if (cell.equals("*")) {
_type = DOMAIN;
} else if (domain.equals("*")) {
_type = QUEUE;
} else {
_type = EXACT;
}
_destCell = cell;
_destDomain = domain;
} else if (domain != null) {
_destCell = "*";
_destDomain = domain;
_type = DOMAIN;
} else if (cell != null) {
_destCell = cell;
_destDomain = "*";
_type = QUEUE;
} else {
_destCell = "*";
_destDomain = "*";
_type = DEFAULT;
}
break;
default:
throw new IllegalArgumentException("Unknown Route type");
}
}
public String getCellName()
{
return _destCell;
}
public String getDomainName()
{
return _destDomain;
}
public String getTargetName()
{
return _gateway;
}
public int getRouteType()
{
return _type;
}
public CellAddressCore getTarget()
{
return new CellAddressCore(_gateway);
}
public String getRouteTypeName()
{
return TYPE_NAMES[_type];
}
public int hashCode()
{
return _type ^ Objects.hash(_destCell, _destDomain, _gateway);
}
public boolean equals(Object o)
{
if (o == this) {
return true;
}
if (!(o instanceof CellRoute)) {
return false;
}
CellRoute route = (CellRoute) o;
return route._destCell.equals(_destCell) &&
route._destDomain.equals(_destDomain) &&
route._gateway.equals(_gateway) &&
route._type == _type;
}
public String toString()
{
return MoreObjects.toStringHelper(this)
.add("cell", getCellName())
.add("domain", getDomainName())
.add("gateway", getTargetName())
.add("type", getRouteTypeName())
.toString();
}
}