Navigator
package com.tegl.commercial.trade.marketagent.navigation;
import com.tegl.commercial.trade.marketagent.InputException;
import com.tegl.commercial.trade.marketagent.MASettings;
import com.tegl.commercial.trade.marketagent.entities.SS;
import com.tegl.commercial.trade.marketagent.io.EveGameDataReader;
import com.tegl.commercial.trade.marketagent.util.MAC;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.util.*;
/**
* The Navigation engine wraps the internal model of the Eve universe. It handles all requests
* for information related to finding paths, distances, or relationships of entities in space.
*/
public class Navigator {
private static Log log = LogFactory.getLog(Navigator.class);
private static Map pathCache = new HashMap();
private static Map overMaxDistancePathCache = new HashMap();
private static final OriginSSVisitor originVisitor = new OriginSSVisitor();
private static final TerminusSSVisitor terminusVisitor = new TerminusSSVisitor();
private static boolean pathDirty = true;// Indicates that some sss may have their pathParents set
public static final int NO_DISTANCE_LIMIT = -1;
public static final int ZERO_JUMPS = 0;
// This is placed into a path object that has no valid route. No need to recreate it.
private static final LinkedList EMPTY_SSLIST = new LinkedList();
private static final String dlm = "=";
// ======================================================================
// Client access
// ======================================================================
public static int getDistance(SS origin, SS terminus) {
return findPath(origin, terminus, NO_DISTANCE_LIMIT, 0.0f, 1.0f).getJumps();
}
/**
* This method first checks to see if origin and dest are the same.
* If so, the distance is 0, and the Path contains an empty LinkedList,
* and we save some work.<br>
* So don't do your own 0-jump checking. This will do it for you.
*
* @param originId The starting system id
* @param terminusId The destination system id
* @param maxDistance The maximum allowable distance, inclusive. If 0, no limit is enforced
* @param minSecurityLimit The lowest allowable system sec rating for the route
* @param maxSecurityLimit The highest allowable system sec rating for the route
* @return The Path object, or null if no path exists within the search parameters.<br>
* The Path object contains:
* <ul>
* <li>A List of ss's which are the path.</li>
* <li>The # of jumps in the path</li>
* <li>The lowest security rating in the path</li>
* <li>The highest security rating in the path</li>
* </ul>
* @throws InputException if either the origin or terminus system was invalid
*/
public static Path findPath(int originId,
int terminusId,
int maxDistance,
float minSecurityLimit,
float maxSecurityLimit) {
SS origin = SS.ss(originId);
if (origin == null) {
throw new InputException("" + originId, "Origin system was not found");
}
SS terminus = SS.ss(terminusId);
if (terminus == null) {
throw new InputException("" + terminusId, "Terminus system was not found");
}
return findPath(origin, terminus, maxDistance, minSecurityLimit, maxSecurityLimit);
}
/**
* This method first checks to see if origin and dest are the same.
* If so, the distance is 0, and the Path contains an empty LinkedList,
* and we save some work.<br>
* So don't do your own 0-jump checking. This will do it for you.
*
* @param originName The starting system name
* @param terminusName The destination system name
* @param maxDistance The maximum allowable distance, inclusive. If 0, no limit is enforced
* @param minSecurityLimit The lowest allowable system sec rating for the route
* @param maxSecurityLimit The highest allowable system sec rating for the route
* @return The Path object, or null if no path exists within the search parameters.<br>
* The Path object contains:
* <ul>
* <li>A List of ss's which are the path.</li>
* <li>The # of jumps in the path</li>
* <li>The lowest security rating in the path</li>
* <li>The highest security rating in the path</li>
* </ul>
* @throws InputException if either the origin or terminus system was invalid
*/
public static Path findPath(String originName,
String terminusName,
int maxDistance,
float minSecurityLimit,
float maxSecurityLimit) {
SS origin = SS.ss(originName);
if (origin == null) {
throw new InputException(originName, "Origin system was not found");
}
SS terminus = SS.ss(terminusName);
if (terminus == null) {
throw new InputException(terminusName, "Terminus system was not found");
}
return findPath(origin, terminus, maxDistance, minSecurityLimit, maxSecurityLimit);
}
/**
* This method first checks to see if origin and dest are the same.
* If so, the distance is 0, and the Path contains an empty LinkedList,
* and we save some work.<br>
* So don't do your own 0-jump checking. This will do it for you.
*
* @param origin The starting system
* @param terminus The destination system
* @param maxDistance The maximum allowable distance, inclusive. If 0, no limit is enforced
* @param minSecurityLimit The lowest allowable system sec rating for the route
* @param maxSecurityLimit The highest allowable system sec rating for the route
* @return The Path object, or null if no path exists within the search parameters.<br>
* The Path object contains:
* <ul>
* <li>A List of ss's which are the path.</li>
* <li>The # of jumps in the path</li>
* <li>The lowest security rating in the path</li>
* <li>The highest security rating in the path</li>
* </ul>
*/
public static Path findPath(SS origin,
SS terminus,
int maxDistance,
float minSecurityLimit,
float maxSecurityLimit) {
log.trace("findPath()");
if (log.isDebugEnabled()) pl("===========Search: "+ origin.getName() + " -> " + terminus.getName() + "=============================");
// ==================================================
// First, check the cache holding paths that failed
// due to exceeding distance limits...
// ==================================================
String key = keyForOverMaxJumps(origin, terminus, maxDistance, minSecurityLimit, maxSecurityLimit);
if (overMaxDistancePathCache.get(key) != null) {
if (log.isDebugEnabled()) pl(key);
if (log.isDebugEnabled()) pl("FailCache hit: [Over distance limit] " + showKey(key));
return null;
}
// ==================================================
// Next, check the success cache...
// ==================================================
Path cached;
key = keyFor(origin, terminus, minSecurityLimit, maxSecurityLimit);
if ( (cached = (Path) pathCache.get(key) ) != null) {
pl(key);
p("Cache hit: ");
// There's one in the cache for the current secRating limits.
// But is it inside the distance limits?
// If so, return it. If not, return null. There IS no route.
if (maxDistance == NO_DISTANCE_LIMIT || cached.getJumps() <= maxDistance) {
if (log.isDebugEnabled()) pl("[VALID] " + cached);
if (log.isDebugEnabled()) pl(" " + showKey(key));
return cached;
} else {
if (log.isDebugEnabled()) pl("[Over jump limit] " + cached);
return null;
}
}
// ==================================================
// Quit early if origin == terminus
// ==================================================
if (origin == terminus) {
Path path = new Path(EMPTY_SSLIST, ZERO_JUMPS, origin.getSecurity(), terminus.getSecurity());
if (log.isDebugEnabled()) pl("Zero-jump route: " + origin.getName());
return path;
}
// ==================================================
// Quit early if the terminus has an out-of-bounds secRating:
// ==================================================
if (!isWithinSecRatingLimits(terminus, minSecurityLimit, maxSecurityLimit)) {
if (log.isDebugEnabled()) pl(terminus.getName() + " is out of sec-limits: " + terminus.getSecurity());
return null;
}
// ==================================================
// Otherwise, do the hard work
// ==================================================
SS[] originConnections = new SS[]{origin};
SS[] terminusConnections = new SS[]{terminus};
originVisitor.setSearchParams(origin, terminus, minSecurityLimit, maxSecurityLimit);
terminusVisitor.setSearchParams(origin, terminus, minSecurityLimit, maxSecurityLimit);
// Set Dirty, cuz we could have visitors setting pathParent fields now
pathDirty = true;
// Monitor the number of jumps we're making. If it goes over the max, might as well quit.
int pathDistance = 0;
// As long as we keep getting back 2 sets of connections to traverse and haven't broken
// the loop, traverse and keep going.
while (originConnections.length > 0 && terminusConnections.length > 0) {
try {
pl("-------------------------------------------------");
// Traverse one set of connections from origin and increment/check pathDistance
originConnections = traverseBfOneLevel(originConnections, originVisitor);
if (isOverDistanceLimit(++pathDistance, maxDistance, origin, terminus, "[O]", minSecurityLimit, maxSecurityLimit)) {
return null;
}
pl("-------------------------------------------------");
// Traverse one set of connections from dest and increment/check pathDistance
terminusConnections = traverseBfOneLevel(terminusConnections, terminusVisitor);
if (isOverDistanceLimit(++pathDistance, maxDistance, origin, terminus, "[T]", minSecurityLimit, maxSecurityLimit)) {
return null;
}
} catch (AbortTraversalException e) {
if (log.isDebugEnabled()) pl("Done: " + e.getMessage());
// ==========================================================================
// If we get an exception, it's because we're DONE traversing, but we could
// still have a pathDistance greater than maxJumps because the exception would
// get thrown before pathDistance would get incremented.
// ==========================================================================
if (isOverDistanceLimit(++pathDistance, maxDistance, origin, terminus, "[E]", minSecurityLimit, maxSecurityLimit)) {
return null;
}
// ==================================================
// SUCCESS!!
// Retrace the path and store it in the cache
// ==================================================
Path path = retracePath(e.getSS());
pathCache.put(keyFor(origin, terminus, minSecurityLimit, maxSecurityLimit), path);
clearPath(AbstractSSVisitor.getPathedSSs(), pathDirty);// Clean up all the references to pathParents
return path;
}
}
pl("No valid paths");
clearPath(AbstractSSVisitor.getPathedSSs(), pathDirty);// Clean up all the references to pathParents
return null;
}
/**
* Use this method when the origin system is your current system.
* <p>
* This method first checks to see if origin and dest are the same.
* If so, the distance is 0, and the Path contains an empty LinkedList,
* and we save some work.<br>
* So don't do your own 0-jump checking. This will do it for you.
*
* @param terminusId The destination system id
* @param minSecurityLimit The lowest allowable system sec rating for the route
* @param maxSecurityLimit The highest allowable system sec rating for the route
* @return The Path object, or null if no path exists within the search parameters.<br>
* The Path object contains:
* <ul>
* <li>A List of ss's which are the path.</li>
* <li>The # of jumps in the path</li>
* <li>The lowest security rating in the path</li>
* <li>The highest security rating in the path</li>
* </ul>
*/
public static Path findPathTo(int terminusId, float minSecurityLimit, float maxSecurityLimit) {
return findPath(SS.ss(MASettings.getCurrentSystemSsid()), SS.ss(terminusId), NO_DISTANCE_LIMIT, minSecurityLimit, maxSecurityLimit);
}
/**
* Performs a breadth-first node-traversal search from the "center" system outward until maxDistance is
* reached.
* @param center You want to find systems near this one
* @param maxDistance The max distance (inclusive) of the search.
* @return An array of SS objects which are within the maxDistance of the center system.
*/
public static SS[] findSystemsNear(SS center, int maxDistance) {
TrueVisitor trueVisitor = new TrueVisitor(center);
int distance = 1;
SS[] connections = new SS[]{center};
while (distance <= maxDistance) {
try {
connections = traverseBfOneLevel(connections, trueVisitor);
} catch (AbortTraversalException e) {
// won't happen for the trueVisitor
}
if (connections.length == 0) {
break;
}
else {
distance++;
}
}
ArrayList pathedSSs = trueVisitor.getPathedSSs();
SS[] systemsNear = (SS[]) pathedSSs.toArray(new SS[0]);
clearPath(pathedSSs, true);
return systemsNear;
}
static boolean isWithinSecRatingLimits(SS ss, float minSecurityLimit, float maxSecurityLimit) {
return ss.getSecurity() >= minSecurityLimit && ss.getSecurity() <= maxSecurityLimit;
}
// ======================================================================
// Private methods
// ======================================================================
private static boolean isOverDistanceLimit(int pathDistance,
int maxDistance,
SS origin,
SS terminus,
String prefix,
float lowSecLimit,
float highSecLimit) {
// If limit enforced, and over limit
boolean overLimit = maxDistance != NO_DISTANCE_LIMIT && pathDistance > maxDistance;
if (overLimit) {
overMaxDistancePathCache.put(keyForOverMaxJumps(origin, terminus, maxDistance, lowSecLimit, highSecLimit), "");
if (log.isDebugEnabled()) pl(prefix + "Over distance limit: " + pathDistance);
clearPath(AbstractSSVisitor.getPathedSSs(), pathDirty);// Clean up all the references to pathParents
}
return overLimit;
}
private static SS[] traverseBfOneLevel(SS[] systems, SSVisitor visitor) throws AbortTraversalException {
// Keep a list of the next level of connections
ArrayList connectionList = new ArrayList();
for (int i = 0; i < systems.length; i++) {
SS parentSS = systems[i];
SS[] connections = parentSS.getConnections();
// Visit the ss's connections. If the return value is false,
// then this path is no good; don't add the connections
for (int j = 0; j < connections.length; j++) {
SS connection = connections[j];
// If we approve of this ss, add it to the next connection
// list to be traversed. Otherwise, leave it out.
if (visitor.visit(connection, parentSS)) {
// Save off a list of all connections of these sss
connectionList.add(connection);
}
}
}
return (SS[]) connectionList.toArray(new SS[0]);
}
/**
* Nullify all references to pathParents
*/
private static void clearPath(List SSsToClear, boolean pathDirty) {
p("Clearing paths: ");
// Check to make sure we need to do this. Only if dirty
if (pathDirty) {
for (int i = 0; i < SSsToClear.size(); /*don't increment*/) {
SS ss = (SS) SSsToClear.remove(i);
if (log.isDebugEnabled()) logClear(ss, "" + SSsToClear.size()); // Don't even process parameters unless we're in debug mode.
ss.setOriginPathParent(null);
ss.setTerminusPathParent(null);
}
pl("");
pathDirty = false;
}
}
/**
* @param ss the center ss of the path - the one where the two expanding spheres meet. This
* ss is thrown with the AbortTraversalException
* @return A list of ss' which are the path. null if ss == null.
*/
private static Path retracePath(SS ss) {
// Sanity check
if (ss == null) {
return null;
}
// Keep track of the number of jumps
int distance = 0; // Don't add one for the origin system
// Keep track of lowest and highest security ratings
float lowSec = Float.MAX_VALUE; // Start high and reduce
float highSec = Float.MIN_VALUE; // Start low and increase
LinkedList ssList = new LinkedList();
// Start from the middle system:
SS termP = ss;
SS orgnP = ss;
ssList.add(ss);
lowSec = Math.min(lowSec, ss.getSecurity());
highSec = Math.max(highSec, ss.getSecurity());
// Traverse the terminus path (the back leg) first, adding systems on top of each other
while ((termP = termP.getTerminusPathParent()) != null) {
ssList.add(termP);
distance++; // increment distance
lowSec = Math.min(lowSec, termP.getSecurity());
highSec = Math.max(highSec, termP.getSecurity());
}
// Traverse the origin path (the front leg) first, adding systems to the front
while ((orgnP = orgnP.getOriginPathParent()) != null) {
ssList.addFirst(orgnP);
distance++; // increment distance
lowSec = Math.min(lowSec, orgnP.getSecurity());
highSec = Math.max(highSec, orgnP.getSecurity());
}
Path path = new Path(ssList, distance, lowSec, highSec);
return path;
}
/**
* Creates a key for the caching of this path.<br>
* The path can be different based on security limits. But the path will not be different
* for distance limits - it just may be filtered out. Therefore the key is made like this
* (with a delim between each element):<br>
* <pre>
* [originId][terminusId][lowSecLimit][highSecLimit]
* </pre>
* @param origin
* @param terminus
* @param lowSecLimit
* @param highSecLimit
* @return
*/
private static String keyFor(SS origin, SS terminus, float lowSecLimit, float highSecLimit) {
StringBuffer buf = new StringBuffer();
buf.append(origin.getSsid()).append(dlm);
buf.append(terminus.getSsid()).append(dlm);
buf.append(lowSecLimit).append(dlm);
buf.append(highSecLimit);
return buf.toString();
}
/**
* Creates a key for caching the info that the attempt to find this path with these max jump
* settings and secRating settings fails.
* @param origin
* @param terminus
* @param lowSecLimit
* @param highSecLimit
* @return a key for a failed-by-maxdistance path cache
*/
private static String keyForOverMaxJumps(SS origin,
SS terminus,
int maxDistance,
float lowSecLimit,
float highSecLimit) {
// start with the basic key. Add a delim, and the maxDistance
return keyFor(origin, terminus, lowSecLimit, highSecLimit) + dlm + maxDistance;
}
private static String showKey(String key) {
String s = null;
if (log.isDebugEnabled()) {
String[] tokens = key.split(dlm);
s = SS.nameFor(Integer.parseInt(tokens[0])) + " -> " + SS.nameFor(Integer.parseInt(tokens[1])) + " " + tokens[2] + "-" + tokens[3];
if (tokens.length == 5) {
s = s + " " + tokens[4];
}
}
return s;
}
// ======================================================================
// Visitor Classes
// ======================================================================
static abstract class AbstractSSVisitor implements SSVisitor {
protected static ArrayList pathedSSs = new ArrayList();
protected SS originSS;
protected SS terminusSS;
protected float minSecurityLimit = 0.0f;
protected float maxSecurityLimit = 1.0f;
public static ArrayList getPathedSSs() {
return pathedSSs;
}
public void setSearchParams(SS originSS, SS terminusSS, float minSecurityLimit, float maxSecurityLimit) {
this.originSS = originSS;
this.terminusSS = terminusSS;
this.minSecurityLimit = minSecurityLimit;
this.maxSecurityLimit = maxSecurityLimit;
}
}
static class OriginSSVisitor extends AbstractSSVisitor implements SSVisitor {
public boolean visit(SS ss, SS parentSS) throws AbortTraversalException {
if (log.isDebugEnabled()) p("[O->] (" + parentSS.getName() + ")->" + ss.getName() + ":");
// We bumped back into the originating ss or one we've visited already
if (ss == originSS || ss.getOriginPathParent() != null) {
pl(" -| loop");
return false;
}
if (!isWithinSecRatingLimits(ss, minSecurityLimit, maxSecurityLimit)) {
pl(" -| sec");
return false;
}
ss.setOriginPathParent(parentSS);
pathedSSs.add(ss); // Keep track so we can reset it later
// If this ss was visited by the other path...
if (ss.getTerminusPathParent() != null) {
pl(" !One!");
throw new AbortTraversalException("Found a terminus ss: " + ss, ss);
}
// If we have found the terminus ss
if (ss == terminusSS) {
pl(" !!It!!");
throw new AbortTraversalException("Found THE terminus ss: " + ss, ss);
}
pl(" ->");
return true;
}
}
static class TerminusSSVisitor extends AbstractSSVisitor implements SSVisitor {
public boolean visit(SS ss, SS parentSS) throws AbortTraversalException {
if (log.isDebugEnabled()) p("[<-T] (" + parentSS.getName() + ")->" + ss.getName() + ":");
// We bumped back into the originating ss or one we've visited already
if (ss == terminusSS || ss.getTerminusPathParent() != null) {
pl(" -| loop");
return false;
}
if (!isWithinSecRatingLimits(ss, minSecurityLimit, maxSecurityLimit)) {
pl(" -| sec");
return false;
}
ss.setTerminusPathParent(parentSS);
pathedSSs.add(ss); // Keep track so we can reset it later
// If this ss was visited by the other path...
if (ss.getOriginPathParent() != null) {
pl(" !One!");
throw new AbortTraversalException("Found an origin ss: " + ss, ss);
}
// If we have found the originination ss
if (ss == originSS) {
pl(" !!It!!");
throw new AbortTraversalException("Found THE origin ss: " + ss, ss);
}
pl(" ->");
return true;
}
}
// ======================================================================
// Command-line access
// ======================================================================
private static final String HSL = "+";
private static final String LSL = "-";
/**
* <pre>
* StartSysName|StartSysId DestSysName|DestSysId [-minSecRating] [+maxSecRating]
* </pre>
* <p>- or -
* <pre>
* StartSysName|StartSysId maxDistance
* </pre>
*
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
if (args.length < 2) {
usage("Not enough arguments.");
return;
}
EveGameDataReader.init();
MASettings.init();
// If there are 2 args, and the second is 1 or 2 chars, treat it as a distance
if (args.length == 2 && args[1].length() < 3) {
SS center = SS.ssFor(args[0]);
if (center == null) {
usage("You must specify a \"center\" system.");
return;
}
int maxDistance = 0;
try {
maxDistance = Integer.parseInt(args[1]);
} catch (NumberFormatException e) {
usage("The max distance value you specified [" + args[1] + "] is not a number.");
return;
}
SS[] systemsNear = findSystemsNear(center, maxDistance);
for (int i = 0; i < systemsNear.length; i++) {
SS ss = systemsNear[i];
int distance = findPath(center, ss, NO_DISTANCE_LIMIT, 0.0f, 1.0f).getJumps();
System.out.println("(" + distance + ") " + ss);
}
return;
}
showPaths(args);
}
private static void showPaths(String[] args) {
try {
SS origin = SS.ssFor(args[0]);
SS terminus = SS.ssFor(args[1]);
if (origin == null || terminus == null) {
usage("You must specify an origin and a terminus system.");
return;
}
float minSecLimit = 0.0f;
float maxSecLimit = 1.0f;
Float[] minMaxSecs = getMinMaxArgs(args);
if (minMaxSecs != null) {
if (minMaxSecs[0] != null) {
minSecLimit = minMaxSecs[0].floatValue();
}
if (minMaxSecs[1] != null) {
maxSecLimit = minMaxSecs[1].floatValue();
}
}
System.out.println("Search: " + origin.getName() + " -> " + terminus.getName() + MAC.I + " " + LSL + (minSecLimit) + " " + HSL + (maxSecLimit));
Path path = findPath(origin, terminus, NO_DISTANCE_LIMIT, minSecLimit, maxSecLimit);
fullPrintPath(path);
} catch (Exception e) {
System.err.println("There was an error" + MAC.CR);
System.err.println(e.getMessage() + MAC.CR + "See below for details." + MAC.CR);
usage(null);
e.printStackTrace();
}
}
private static Float[] getMinMaxArgs(String[] args) {
Float[] minMax = new Float[2];
for (int i = 2; i < 4; i++) {
String arg;
try {
arg = args[i];
} catch (Exception e) {
continue;
}
if (arg.startsWith(LSL)) {
minMax[0] = new Float(arg.substring(1));
}
else if (arg.startsWith(HSL)) {
minMax[1] = new Float(arg.substring(1));
}
}
return minMax;
}
private static void usage(String errMsg) {
StringBuffer usage = new StringBuffer();
errMsg = errMsg == null ? "" : errMsg;
usage.append(errMsg).append(MAC.CR).append(MAC.CR);
usage.append(MAC.CR).append("USAGE: ").append(MAC.CR);
usage.append("Get path:").append(MAC.CR);
usage.append("nav startSystem destSystem [" + LSL + "minSecRating] [" + HSL + "maxSecRating]").append(MAC.CR);
usage.append(MAC.CR);
usage.append("OR" + MAC.CR);
usage.append("Get list of systems within n jumps:").append(MAC.CR);
usage.append("nav startSystem maxDistance").append(MAC.CR);
usage.append(MAC.CR);
usage.append("Where:").append(MAC.CR);
usage.append("startSystem").append(" = Exact name OR ID of start system").append(MAC.CR);
usage.append("destSystem").append(" = Exact name OR ID of destination system").append(MAC.CR);
usage.append(LSL + "minSecRating").append(" = Only Systems with this secrating or higher will be included in the route.").append(" (OPTIONAL) (Default: 0.0)").append(MAC.CR);
usage.append(HSL + "maxSecRating").append(" = Only Systems with this secrating or lower will be included in the route.").append(" (OPTIONAL) (Default: 1.0)").append(MAC.CR);
usage.append("maxDistance").append(" = max distance from startSystem").append(MAC.CR);
usage.append(MAC.CR);
usage.append("Example:*").append(MAC.CR);
usage.append("---------------------------").append(MAC.CR);
usage.append("nav Bar Asghatil " + LSL + "0.8").append(MAC.CR);
usage.append("---------------------------").append(MAC.CR);
usage.append("The resulting route will go thru Jarizza (0.8), because Sucha is 0.7").append(MAC.CR);
usage.append("*Note that you must include the '" + LSL + "' and '" + HSL + "' signs").append(MAC.CR);
usage.append(MAC.CR);
usage.append("Example:").append(MAC.CR);
usage.append("---------------------------").append(MAC.CR);
usage.append("nav Sasta 2 ").append(MAC.CR);
usage.append("---------------------------").append(MAC.CR);
usage.append("You will get a list of all systems within 2 jumps of Sasta").append(MAC.CR);
usage.append(MAC.CR);
System.out.println(usage.toString());
}
private static void fullPrintPath(Path path) {
if (path != null) {
List ssList = path.getSsList();
System.out.println("===================================================================");
System.out.println("Jumps = " + path.getJumps());
System.out.println("LowSec = " + path.getLowSec());
System.out.println("HighSec = " + path.getHighSec());
for (int i = 0; i < ssList.size(); i++) {
SS ss = (SS) ssList.get(i);
System.out.println(i + " " + ss);
}
} else {
System.out.println("No path");
}
}
// ======================================================================
// Debug methods and junk
// ======================================================================
private static void logClear(SS ss, String s) {
// Don't even do this if we're not in debug mode.
if (log.isDebugEnabled()) {
SS oParent = ss.getOriginPathParent();
SS tParent = ss.getTerminusPathParent();
if (oParent == null && tParent == null) {
log.error("No parents set!");
}
if (oParent != null) {
String oParentName = (oParent == null) ? "oParentNull" : oParent.getName();
String oName = (ss == null) ? "oNameNull" : ss.getName();
p("([O]" + oParentName + " -> " + oName + ") " + s + " ");
}
if (tParent != null) {
String tParentName = (tParent == null) ? "tParentNull" : tParent.getName();
String tName = (ss == null) ? "tNameNull" : ss.getName();
p("([T]" + tParentName + " -> " + tName + ") " + s + " ");
}
}
}
private static StringBuffer mem = new StringBuffer();
private static void p(String s) {
if (log.isDebugEnabled()) {
mem.append(s);
}
}
private static void pl(String s) {
if (log.isDebugEnabled()) {
log.debug(mem + s);
mem.delete(0, mem.length()); // clear it
}
}
private static String listConnections(SS[] terminusConnections) {
StringBuffer buf = new StringBuffer("connections of: ");
for (int i = 0; i < terminusConnections.length; i++) {
SS ss = terminusConnections[i];
buf.append(ss.getName());
if (i != terminusConnections.length - 1) {
buf.append(", ");
}
}
return buf.toString();
}
}