// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.messagebus.routing;
import java.util.ArrayList;
import java.util.List;
/**
* Along with the {@link RoutingSpec}, {@link RoutingTableSpec} and {@link HopSpec}, this holds the routing
* specifications for all protocols. The only way a client can configure or alter the settings of a message bus instance
* is through these classes.
*
* This class contains the spec for a single route.
*
* @author Simon Thoresen Hult
*/
public class RouteSpec {
private final String name;
private final List hops = new ArrayList();
private final boolean verify;
/**
* Creates a new named route specification.
*
* @param name A protocol-unique name for this route.
*/
public RouteSpec(String name) {
this(name, true);
}
/**
* Creates a new named route specification.
*
* @param name A protocol-unique name for this route.
* @param verify Whether or not this should be verified.
*/
public RouteSpec(String name, boolean verify) {
this.name = name;
this.verify = verify;
}
/**
* Implements the copy constructor.
*
* @param obj The object to copy.
*/
public RouteSpec(RouteSpec obj) {
this.name = obj.name;
this.verify = obj.verify;
for (String hop : obj.hops) {
hops.add(hop);
}
}
/**
* Returns the protocol-unique name of this route.
*
* @return The name.
*/
public String getName() {
return name;
}
/**
* Returns the hop name at the given index.
*
* @param i The index of the hop to return.
* @return The hop at the given index.
*/
public String getHop(int i) {
return hops.get(i);
}
/**
* Returns whether or not there are any hops in this route.
*
* @return True if there is at least one hop.
*/
public boolean hasHops() {
return !hops.isEmpty();
}
/**
* Returns the number of hops that make up this route.
*
* @return The number of hops.
*/
public int getNumHops() {
return hops.size();
}
/**
* Adds the given hop name to this.
*
* @param hop The hop to add.
* @return This, to allow chaining.
*/
public RouteSpec addHop(String hop) {
hops.add(hop);
return this;
}
/**
* Adds the given hop names to this.
*
* @param hops The hops to add.
* @return This, to allow chaining.
*/
public RouteSpec addHops(List hops) {
this.hops.addAll(hops);
return this;
}
/**
* Sets the hop name for a given index.
*
* @param i The index of the hop to set.
* @param hop The hop to set.
* @return This, to allow chaining.
*/
public RouteSpec setHop(int i, String hop) {
hops.set(i, hop);
return this;
}
/**
* Removes the hop name at the given index.
*
* @param i The index of the hop to remove.
* @return The removed hop.
*/
public String removeHop(int i) {
return hops.remove(i);
}
/**
* Clears the list of hops that make up this route.
*
* @return This, to allow chaining.
*/
public RouteSpec clearHops() {
hops.clear();
return this;
}
/**
* Verifies the content of this against the given application.
*
* @param app The application to verify against.
* @param table The routing table to verify against.
* @param errors The list of errors found.
* @return True if no errors where found.
*/
public boolean verify(ApplicationSpec app, RoutingTableSpec table, List errors) {
if (verify) {
String protocol = table.getProtocol();
int numHops = hops.size();
if (numHops == 0) {
errors.add("Route '" + name + "' in routing table '" + protocol + "' has no hops.");
} else {
for (int i = 0; i < numHops; ++i) {
HopSpec.verify(app, table, null, null, hops.get(i), errors,
"hop " + (i + 1) + " in route '" + name + "' in routing table '" + protocol + "'");
}
}
}
return errors.isEmpty();
}
/**
* Appends the content of this to the given config string builder.
*
* @param cfg The config to add to.
* @param prefix The prefix to use for each add.
*/
public void toConfig(StringBuilder cfg, String prefix) {
cfg.append(prefix).append("name ").append(RoutingSpec.toConfigString(name)).append("\n");
int numHops = hops.size();
if (numHops > 0) {
cfg.append(prefix).append("hop[").append(numHops).append("]\n");
for (int i = 0; i < numHops; ++i) {
cfg.append(prefix).append("hop[").append(i).append("] ");
cfg.append(RoutingSpec.toConfigString(hops.get(i))).append("\n");
}
}
}
// Overrides Object.
@Override
public String toString() {
StringBuilder ret = new StringBuilder();
toConfig(ret, "");
return ret.toString();
}
// Overrides Object.
@Override
public boolean equals(Object obj) {
if (!(obj instanceof RouteSpec)) {
return false;
}
RouteSpec rhs = (RouteSpec)obj;
if (!name.equals(rhs.name)) {
return false;
}
if (!hops.equals(rhs.hops)) {
return false;
}
return true;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + (hops != null ? hops.hashCode() : 0);
result = 31 * result + (verify ? 1 : 0);
return result;
}
}