/*
* PaperScopeSession.java - For managing the XML file, queried papers, etc
*
* Created on 29 May 2007, 11:23
*
*Author: Mark Holliman
*/
package paperscope;
import java.io.*;
import java.lang.reflect.*;
import java.util.Vector;
import java.util.Iterator;
import prefuse.data.Graph;
import prefuse.data.Node;
import prefuse.data.Edge;
import prefuse.data.Table;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.SwingConstants;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;
import javax.swing.JPanel;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JButton;
import javax.swing.JTextField;
import javax.swing.JSeparator;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.border.EtchedBorder;
import edu.stanford.ejalbert.BrowserLauncher;
public class PaperScopeSession
{
//==== Variables for storing and interacting with the XML file
String resultsFile;
String bibcode;
//==== Variables for manipulating the current graph and list of papers (main data structures)
RadialGraph currentGraph;
//==== Variables for interacting with the user interface
PaperScopeUI userInterface;
//=== Default Constructor initializes variables
public PaperScopeSession(String bibcode, PaperScopeUI ui)
{
this.bibcode = bibcode.replace("&", "%26");
this.userInterface = ui;
}
//=== Constructor for session started with a saved graph file
public PaperScopeSession(Graph g, PaperScopeUI ui)
{
this.userInterface = ui;
//==== Use the graph provided
this.currentGraph = new RadialGraph(g, this);
//==== Update the node visibility according to the saved value
currentGraph.setVisibility();
}
//#######################################################################################################
public void executeInitialQuery()
{
//==== Execute a List query on the given bibcode
ListQuery firstQuery = new ListQuery(this.bibcode, "all");
//==== Get the array of papers returned
Paper[] firstResults = firstQuery.getPaperList();
//==== Generate the Prefuse Graph
GraphAdapter graphMaker = new GraphAdapter(firstResults);
this.currentGraph = new RadialGraph(graphMaker.getGraph(), this);
} //end executeInitialQuery
//#######################################################################################################
public SecondaryResults executeSecondaryQuery(String bibcode, String whichNodes, int focusKey, Table nodesTable)
{
//==== Execute a List query on the given bibcode
ListQuery secondaryQuery = new ListQuery(bibcode, whichNodes);
//==== Get the array of papers returned
Paper[] secondaryList = secondaryQuery.getPaperList();
//==== create the graph object with the new nodes and edges, update the current list to include all new papers
SecondaryResults secondaryResults = compareGraphs(secondaryList, focusKey, nodesTable);
//==== return the graph
return secondaryResults;
} //end executeInitialQuery
//#######################################################################################################
public JScrollPane executeAuthorQuery(String author)
{
//==== Run the search for the author's name on ADS, retrieve an array of the results
AuthorSearchParser search = new AuthorSearchParser(author);
Paper[] results = search.getPaperList();
//==== create the JPanel to be returned, add the box with the papers to it
JPanel panel = new JPanel();
//==== Create the Gridbag layout for displaying the papers
GridLayout mainLayout = new GridLayout(Array.getLength(results)+1, 1);
panel.setLayout(mainLayout);
//==== Go through the results, creating a panel for each paper
for(int i=0; i<Array.getLength(results); i++)
{
PaperPanel paperPanel = new PaperPanel(this, i, results[i].getTitle(), results[i].getAuthorList(), results[i].getJournal(), results[i].getDate(), results[i].getCitCount(), results[i].getBibcode(), results[i].getAbstractURL());
panel.add(paperPanel);
} //end for, looped through results
JScrollPane scrollPanel = new JScrollPane(panel);
JScrollBar bar = new JScrollBar();
bar.setUnitIncrement(50);
scrollPanel.setVerticalScrollBar(bar);
return scrollPanel;
}
//#######################################################################################################
public String getResultsFilePath()
{
return resultsFile;
}
//#######################################################################################################
public RadialGraph getRadialGraph()
{
return currentGraph;
}
//#######################################################################################################
public void setGraph(RadialGraph newGraph)
{
currentGraph = newGraph;
}
//#######################################################################################################
public void setBibcode(String bibcode)
{
this.bibcode = bibcode;
}
//#######################################################################################################
public SecondaryResults compareGraphs(Paper[] secondaryResults, int focusKey, Table paperTable)
{
//==== Node key of last node in current list (for use in creating new nodes in the new graph)
int lastNodeKey = paperTable.getInt(paperTable.getMaximumRow(), "DEFAULT_NODE_KEY");
//==== Separately, note the lastNodeKey for adding nodeKey values to the papers in the for loops below
int nodeKey = lastNodeKey + 1;
//==== Counters for loops
int secondaryResultCount = Array.getLength(secondaryResults);
int currentPaperCount = paperTable.getRowCount();
//==== Vector for storing papers new papers foun
Vector papersToAdd = new Vector();
//==== Vector for storing node keys of duplicate papers
Vector dupePapers = new Vector();
//==== Vector for storing node keys for nodes that need to be updated
Vector nodes2Change = new Vector();
//==== Checker for new papers, initialized to true
boolean paperIsNew = true;
//==== Loop through the list of papers from the secondary query
for (int i=0; i<secondaryResultCount; i++)
{
//=== Loop through all the papers in the current graph
for(int j=0; j<currentPaperCount; j++)
{
//== If a duplicate paper is found
if(paperTable.getString(j,"bibcode").equals(secondaryResults[i].getBibcode()))
{
//= set the checker to false
paperIsNew = false;
//= if it is not the paper being queried then note it as a duplicate (to add an edge to it on the graph)
//= also make sure it is not a focus paper (hence already on the graph, with the necessary edge to the paper being queried)
if(!(j==focusKey) || !(paperTable.getString(j,"refType").equals("FOCUS")))
{
Paper paper = new Paper(paperTable.getInt(j,"DEFAULT_NODE_KEY"), paperTable.getString(j,"refType"));
dupePapers.add(paper);
//= Check to see if its 'refType' is different on each list
String curType = paperTable.getString(j,"refType");
String secType = secondaryResults[i].getRefType();
//= if it's a FOCUS paper, ignore it
if((!curType.equals("FOCUS"))&&(!secType.equals("FOCUS")))
{
//= If they are different, then note the node key of the paper
if(curType.equals("REFERENCES") && secType.equals("CITATIONS"))
{ nodes2Change.add(paperTable.getInt(j,"DEFAULT_NODE_KEY")); }
else if(curType.equals("CITATIONS") && secType.equals("REFERENCES"))
{ nodes2Change.add(paperTable.getInt(j,"DEFAULT_NODE_KEY")); }
}
}
}
} //end for, looped through list of current papers
//=== The paper wasn't in the current list, it is new
if(paperIsNew == true)
{
//==Update the nodeKey for this paper
secondaryResults[i].setDefaultNodeKey(nodeKey);
//== Add it to the vector of new papers
papersToAdd.add(secondaryResults[i]);
//== increment the nodeKey for the next new paper found
nodeKey = nodeKey + 1;
}
//=== reset the checker
paperIsNew = true;
} //end for, looped through list of papers from secondary query
//==== Convert the Vector of new papers into an array
Paper[] newList = new Paper[papersToAdd.size()];
papersToAdd.copyInto(newList);
//==== Convert the Vector of duplicate papers into an array
Paper[] duplicates = new Paper[dupePapers.size()];
dupePapers.copyInto(duplicates);
//==== Convert the Vector of nodes to be changed into an array
int[] rowChanges = new int[nodes2Change.size()];
for (int k=0; k<nodes2Change.size(); k++)
{
rowChanges[k] = (Integer)nodes2Change.get(k);
}
//==== Generate the results and return them
GraphAdapter newGraph = new GraphAdapter(newList, focusKey, duplicates);
SecondaryResults results = new SecondaryResults(newGraph.getGraph(), rowChanges);
//==== Update the paperList with the new papers (including their nodeKeys
return results;
}
//#######################################################################################################
public void graphPaperMouseClicked(String bibcode)
{
//==== Set this session's bibcode to the one from the paper
this.setBibcode(bibcode);
//==== Swing worker for executing the initial query
class InitialQueryExecuter extends SwingWorker<JPanel, Void> {
@Override
public JPanel doInBackground() {
executeInitialQuery();
RadialGraph graphme = getRadialGraph();
return graphme.getGraphDisplayPanel();
}
@Override
protected void done() {
try {
userInterface.stopQueryProgressBar();
userInterface.updateGraphFrame(get());
} catch (Exception ignore) {}
}
} //end class, InitialQueryExecuter
//==== Create the runnable
InitialQueryExecuter query = new InitialQueryExecuter();
//==== Turn on the progress bar (it is turned off when the done() method is called)
userInterface.startQueryProgressBar();
//==== Set the text in the bibcode text field to the bibcode of this paper, select the Graph tab
userInterface.setBibcodeTextField(bibcode);
userInterface.selectGraphTab();
//==== Execute the query
query.execute();
}
//#######################################################################################################
// Check all the focus papers for new citations, and if found add them to the graph
public void updateGraph()
{
//==== Iterate through all the nodes in this graph
Iterator items = this.getRadialGraph().getDataGraph().nodes();
while(items.hasNext())
{
Node node = (Node)items.next();
//=== If it is a focus node, check its citation list for new papers
if(node.getString("refType").equals("FOCUS"))
{
String bibcode = node.getString("bibcode");
int focusKey = node.getInt("DEFAULT_NODE_KEY");
SecondaryResults newNodes = executeSecondaryQuery(bibcode, "cit", focusKey, this.getRadialGraph().getDataGraph().getNodeTable());
//=== Take the new nodes, and their associated edges, and add them into the graph
for(int i=0; i<newNodes.getGraph().getNodeCount(); i++)
{
int key = newNodes.getGraph().getNodeTable().getInt(i, "DEFAULT_NODE_KEY");
Node addMe = newNodes.getGraph().getNodeFromKey(key);
this.getRadialGraph().getDataGraph().getNodes().addTuple(addMe);
Iterator edgeIt = newNodes.getGraph().edges();
while(edgeIt.hasNext())
{
Edge edge = (Edge)edgeIt.next();
if(edge.getInt("source") == addMe.getInt("DEFAULT_NODE_KEY"))
{
this.getRadialGraph().getDataGraph().addEdge(edge.getInt("source"), edge.getInt("target"));
}
}
}
}
} //end while, checked all nodes
//==== run the actions for painting and placing the new nodes
this.getRadialGraph().getVisualization().run("filter");
this.getRadialGraph().getVisualization().run("repaint");
}
}