/*
* (C) Copyright IBM Corp. 2009
*
* LICENSE: Eclipse Public License v1.0
* http://www.eclipse.org/legal/epl-v10.html
*/
package com.ibm.gaiandb.tools;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;
public class ExplainLinksAnalyser {
// Use PROPRIETARY notice if class contains a main() method, otherwise use COPYRIGHT notice.
public static final String COPYRIGHT_NOTICE = "(c) Copyright IBM Corp. 2009";
// private static final String delimiter =" ";
private static Vector<Vector<String>> longestRoutes = new Vector<Vector<String>>();
public static void main( String[] args) throws Exception {
// String filename = args.length > 0 ? args[0] : "C:\\temp\\GDB52-emj.txt";
// String filename = args.length > 0 ? args[0] : "C:\\temp\\GDB120-propnewalgo.txt"; //GDB120-propnolimit.txt"; //GDB120-prop.txt";
String filename = args.length > 0 ? args[0] : "C:\\temp\\gdb520.txt";
// String filename = args.length > 0 ? args[0] : "C:\\temp\\gdb120fix.txt";
// int INIT_NODES = 100;
// int MAX_STEPS = 20;
// Hashtable of node names
Hashtable<String, Set<String>> links = new Hashtable<String, Set<String>>(); //NUM_NODES);
// Hashtables of ArrayLists
Hashtable<String, ArrayList<Integer>> stepCardinalities = new Hashtable<String, ArrayList<Integer>>(); //NUM_NODES); //[MAX_STEPS+1];
Hashtable<String, ArrayList<Integer>> runningTotalCardinalities = new Hashtable<String, ArrayList<Integer>>(); //NUM_NODES); //[MAX_STEPS+1];
String queryStartNode = "";
FileReader fr = new FileReader( filename );
BufferedReader br = new BufferedReader( fr );
String line;
while( null != ( line = br.readLine() ) ) {
int cidx = line.indexOf( " -> " );
if ( -1 == cidx ) continue;
// before cidx is a query source in quotes, i.e. "hipods095.hursley.ibm.com:6415"
String sourceNode = line.substring (1,cidx-1);
// after cidx is a query destination in quotes, i.e. "hipods095.hursley.ibm.com:6415"
int tokenEnd=line.indexOf( "\"", cidx+5);
String destinationNode = line.substring (cidx+5,tokenEnd);
// after the destination is square bracketed style marker - showing whether the query was executed, or a duplicate
// such as [style=dotted] or [label=0];
// connected nodes n1 and n2
int tokenStart=line.indexOf("[");
tokenEnd=line.indexOf("=",tokenStart);
//String labelType=line.substring(tokenStart+1,tokenEnd);
// Get second half of the label
tokenStart=tokenEnd+1;
tokenEnd=line.indexOf("]",tokenStart);
//String labelData = line.substring(tokenStart,tokenEnd);
//String n1 = line.substring(0, cidx);
//String n2 = line.substring(cidx+delimiter.length());
String sub = sourceNode.substring(0,13);
if (sub.equals("SQL Query on ")) {
queryStartNode=destinationNode;
continue;
}
Set<String> s = links.get(sourceNode);
if ( null == s ) {
s = new HashSet<String>();
links.put(sourceNode, s);
stepCardinalities.put(sourceNode, new ArrayList<Integer>());
runningTotalCardinalities.put(sourceNode, new ArrayList<Integer>());
}
s.add(destinationNode);
s = links.get(destinationNode);
if ( null == s ) {
s = new HashSet<String>();
links.put(destinationNode, s);
stepCardinalities.put(destinationNode, new ArrayList<Integer>());
runningTotalCardinalities.put(destinationNode, new ArrayList<Integer>());
}
s.add(sourceNode);
}
Set<String> visited = new HashSet<String>();
// find the querysource node
String node = queryStartNode;
// Go through nodes one at a time to calculate their distance to all other nodes.
//Iterator nodes = links.keySet().iterator();
//while(nodes.hasNext()) {
// String node = (String) nodes.next();
visited.clear();
Set<String> previouslyVisited = null;
// At each step out, keep the list on newly visited nodes.
Hashtable<Integer, Set<String>> newlyvisitedPerStep = new Hashtable<Integer, Set<String>>();
// for every step out
for ( int s=0; /*s<MAX_STEPS*/; s++ ) {
Set<String> newlyVisited = new HashSet<String>();
if ( visited.isEmpty() ) {
// Just add ourself at depth step 0
newlyVisited.add( node );
} else {
// Compute cardinality at next step by getting all links m of the newly visited nodes
Iterator<String> iter = previouslyVisited.iterator();
while( iter.hasNext() ) {
String m = iter.next();
newlyVisited.addAll( links.get(m) );
}
newlyVisited.removeAll( visited );
}
// Early end condition: No new nodes visited
if ( 0 == newlyVisited.size() ) break;
visited.addAll( newlyVisited );
stepCardinalities.get(node).add( newlyVisited.size() );
runningTotalCardinalities.get(node).add( visited.size() );
newlyvisitedPerStep.put(new Integer(s), newlyVisited);
// Early end condition: All nodes visited
// if ( NUM_NODES == visited.size() ) break;
previouslyVisited = newlyVisited;
}
// use a recursive algorithm to step back and find the proutes to the longest points.
Iterator<String> visitIter = previouslyVisited.iterator();
int numberOfSteps = newlyvisitedPerStep.size();
while( visitIter.hasNext() ) {
String m = visitIter.next();
Vector<String> nodeRoute = new Vector<String>();
nodeRoute.add(m);
WorkOutRoute(numberOfSteps, nodeRoute, newlyvisitedPerStep, links);
}
for (Vector<String> longestRoute : longestRoutes) {
System.out.print ("Longest Route: ");
for (Object routeStep : longestRoute) {
Set<String> linkSet = links.get((String)routeStep);
int numberOfLinks = linkSet.size();
System.out.print((String)routeStep + ", connections: " + numberOfLinks + ", ");
}
System.out.println("");
}
//for ( int s=0; /*s<MAX_STEPS*/; s++ ) {
//int numberOfSteps = newlyvisitedPerStep.size();
//for ( int step=step; s==0; s-- ) {
// At the point when we exit, previouslyVisited holds the set of the furthest out nodes.
// Iterate through these and work backwards to find the shortest route to them.
//numberOfSteps = newlyvisitedPerStep.get(key)
//for
}
// Recursively work back through the newlyvisitedPerStep data and the links to find instances of the route within the
// number of steps given, Accrete the routes by inserting into the nodeRoute.
private static void WorkOutRoute(int numberOfSteps, Vector<String> nodeRoute,
Hashtable<Integer, Set<String>> newlyvisitedPerStep, Hashtable<String, Set<String>> links) {
String node = (String) nodeRoute.get(0);
Set<String> nodeConnections = links.get(node);
//reduce the links to just those the right number of steps form the source
Set<String> nodesAtCorrectStep = newlyvisitedPerStep.get(new Integer(numberOfSteps-2));
nodesAtCorrectStep.retainAll(nodeConnections);
for (String previousNode : nodesAtCorrectStep) {
@SuppressWarnings("unchecked")
Vector<String> extendedNodeRoute=(Vector<String>)nodeRoute.clone();
extendedNodeRoute.add(0, previousNode);
if (numberOfSteps>2)
WorkOutRoute(numberOfSteps-1,extendedNodeRoute,newlyvisitedPerStep,links);
else
//We have got back to the beginning with a full valid maximum length route.
longestRoutes.add(extendedNodeRoute);
}
}
// public static String intArrayAsString(int[] a) {
// if ( null==a ) return null; int len = a.length;
// String pcs = new String( 0<len ? "[" + a[0] : "[" );
//// for (int i=1; i<len; i++) pcs += ", " + a[i]; pcs += "]";
// for (int i=1; i<len; i++) pcs += ", " + a[i]; pcs += "]";
// return pcs;
// }
}