/*
* Copyright 2003-2010 Tufts University Licensed under the
* Educational Community License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* http://www.osedu.org/licenses/ECL-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS"
* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/*
* RDFOpenAction.java
*
* Created on October 23, 2003, 12:40 PM
*/
package tufts.vue.action;
/**
*
* @author akumar03
*/
import java.io.*;
import java.util.zip.*;
import java.util.*;
import java.awt.event.*;
import javax.swing.*;
import tufts.vue.*;
import com.hp.hpl.jena.rdf.model.*;
public class RDFOpenAction extends VueAction {
private static final org.apache.log4j.Logger Log = org.apache.log4j.Logger.getLogger(RDFOpenAction.class);
//todo: add constants for row length, starting position, y gaps and x gaps
//also make these all be read from properties file for ease of modification
//after compilation
public static final int NODE_LABEL_TRUNCATE_LENGTH = 8;
public RDFOpenAction(String label) {
super(label, null, ":general/Open");
}
public RDFOpenAction() {
this(VueResources.getString("menu.file.importrdffile"));
}
// workaround for rapid-succession Ctrl-O's which pop multiple open dialogs
private static final Object LOCK = new Object();
private static boolean openUnderway = false;
public void actionPerformed(ActionEvent e) {
synchronized (LOCK) {
if (openUnderway)
return;
openUnderway = true;
}
try {
File file = ActionUtil.openFile("Open Map", "RDF");
displayMap(file);
System.out.println("Action["+e.getActionCommand()+"] completed.");
} finally {
openUnderway = false;
}
}
public static void displayMap(File file) {
if (file != null) {
VUE.activateWaitCursor();
try {
LWMap loadedMap = loadMap(file.getAbsolutePath());
VUE.displayMap(loadedMap);
} finally {
VUE.clearWaitCursor();
}
}
}
// todo: have only one root loadMap that hanldes files & urls -- actually, make it ALL url's
public static LWMap loadMap(String fileName) {
try {
//probably don't want to save over original rdf
//LWMap map = new LWMap(fileName);
//so construct a name based on file name instead:
String mapName = fileName.substring(fileName.lastIndexOf("/")+1,fileName.length());
if(mapName.lastIndexOf(".")>0)
mapName = mapName.substring(0,mapName.lastIndexOf("."));
if(mapName.length() == 0)
mapName = "RDF Import";
LWMap map = new LWMap(mapName);
// create an empty model
Model model = ModelFactory.createDefaultModel();
// use the FileManager to find the input file
InputStream in = new FileInputStream(fileName);
if (in == null) {
throw new IllegalArgumentException(
"File: " + fileName + " not found");
}
// read the RDF/XML file
model.read(in, "");
// write it to standard out -- fails for zotero rdf so comment out for now..
// model.write(System.out);
int totalResources = 0;
Map<String,LWNode> hashMap = new HashMap<String,LWNode>();
ResIterator resIterator = model.listSubjects();
while(resIterator.hasNext()) {
com.hp.hpl.jena.rdf.model.Resource res = resIterator.nextResource();
LWNode node = createNodeFromResource(res);
hashMap.put(res.getURI(),node);
map.add(node);
totalResources++;
}
com.hp.hpl.jena.rdf.model.NodeIterator nIterator = model.listObjects();
while(nIterator.hasNext()) {
RDFNode rdfNode = nIterator.nextNode();
if(rdfNode instanceof com.hp.hpl.jena.rdf.model.Resource ) {
com.hp.hpl.jena.rdf.model.Resource nodeResource = (com.hp.hpl.jena.rdf.model.Resource)rdfNode;
if(!hashMap.containsKey(nodeResource.getURI())) {
LWNode node = createNodeFromResource(nodeResource);
hashMap.put(nodeResource.getURI(),node);
map.add(node);
totalResources++;
}
}
}
//float y = 20;
//float x = 0;
//int count = 0;
resetLayoutParameters();
com.hp.hpl.jena.rdf.model.StmtIterator iter = model.listStatements();
while(iter.hasNext()){
com.hp.hpl.jena.rdf.model.Statement stmt = iter.nextStatement();
com.hp.hpl.jena.rdf.model.Resource stmtSubject = stmt.getSubject();
com.hp.hpl.jena.rdf.model.Property stmtProperty = stmt.getPredicate();
com.hp.hpl.jena.rdf.model.RDFNode stmtObject = stmt.getObject();
if(stmtObject instanceof com.hp.hpl.jena.rdf.model.Resource) {
LWNode node1 = hashMap.get(stmtSubject.getURI());
LWNode node2 = hashMap.get(((com.hp.hpl.jena.rdf.model.Resource)stmtObject).getURI());
LWLink link = new LWLink(node1,node2);
map.add(link);
}else if(stmtObject instanceof com.hp.hpl.jena.rdf.model.Literal) {
tufts.vue.Resource mapResource = hashMap.get(stmtSubject.getURI()).getResource();
if(mapResource != null)
mapResource.setProperty(stmtProperty.getLocalName(), stmtObject);
}
}
map.layoutAndValidateNewMap();
map.markAsSaved(); // all mods permanent
return map;
} catch (Exception e) {
// out of the Open File dialog box.
System.err.println("OpenAction.loadMap[" + fileName + "]: " + e);
VueUtil.alert(null, "\"" + fileName + "\"" +VueResources.getString("rfdopenaction.openfile.error"), VueResources.getString("rfdopenaction.openfile.title"));
e.printStackTrace();
}
return null;
}
private static LWNode createNodeFromResource(com.hp.hpl.jena.rdf.model.Resource r) {
tufts.vue.Resource resource = null;
String uri = null;
try
{
uri = r.getURI();
// Resource's aren't currently intended to support being created from arbitrary strings.
// Do we need them to? If so, we'd probably want to require that the abritraty string
// is at least a valid URI. We might want something like this:
// if (uri != null && uri.length() > 0) {
// if (uri.charAt(0) == '#')
// uri = "rdf:" + uri.substring(1);
// else if (uri.indexOf(':') < 0)
// uri = "rdf:" + uri;
// }
if (uri != null)
resource = tufts.vue.Resource.getFactory().get(uri);
else
Log.warn("null URI: " + tufts.Util.tags(r));
}
catch (Throwable t) {
Log.warn("failed to create Resource from " + tufts.Util.tags(uri), t);
}
LWNode node = new LWNode("Empty");
if(resource == null)
{
if (uri != null)
node = new LWNode("Resource Error; URI [" + uri + "]");
}
else
{
String labelDisplay = VueResources.getString("rdf.import.displayType");
String labelConstant = VueResources.getString("rdf.import.displayLabel");
if(labelDisplay.equals("LABEL"))
{
edu.tufts.vue.rdf.RDFIndex index = new edu.tufts.vue.rdf.RDFIndex();
com.hp.hpl.jena.rdf.model.Property labelOf = index.createProperty(edu.tufts.vue.rdf.RDFIndex.VUE_ONTOLOGY,edu.tufts.vue.metadata.Constants.LABEL);
node = new LWNode(r.getProperty(labelOf).getString());
}
else
{
node = new LWNode(r.getURI());
}
node.setResource(resource);
}
placeNode(node);
//double angle = Math.random()*Math.PI*4;
//node.setLocation(200+200*Math.cos(angle),200+200*Math.sin(angle));
return node;
}
private static void resetLayoutParameters()
{
if(nodeLayout == CIRCLE)
{
}
if(nodeLayout == STAGGERED_FLOW)
{
oldWidth = 0.0f;
y = 20;
x = 0;
count = 0;
}
}
static float oldWidth = 0.0f;
static float y = 20;
static float x = 0;
static int count = 0;
static int toggle = 0;
public final static int CIRCLE = 0;
public final static int STAGGERED_FLOW = 1;
public final static int nodeLayout = STAGGERED_FLOW;
private static void placeNode(LWNode node)
{
if(nodeLayout == CIRCLE)
{
double angle = Math.random()*Math.PI*4;
node.setLocation(200+200*Math.cos(angle),200+200*Math.sin(angle));
}
if(nodeLayout == STAGGERED_FLOW)
{
String uri = node.getLabel();
String name = node.getLabel();
int lastSlash = name.lastIndexOf("/");
if(lastSlash > 1 && (lastSlash == name.length()-1) )
{
name = name.substring(0,name.length()-1);
}
name = name.substring(name.lastIndexOf("/")+1,name.length());
if(name.length() == 0)
{
name = uri;
}
if(name.length() > NODE_LABEL_TRUNCATE_LENGTH)
name = name.substring(0,NODE_LABEL_TRUNCATE_LENGTH) + "...";
//node = new LWNode(name);
//System.out.println("Resource uri: "+r.getURI());
//com.hp.hpl.jena.rdf.model.StmtIterator stmtIterator = r.listProperties();
//java.util.Properties properties = new java.util.Properties();
// oldWidth can be used to seperate wide nodes from each other
// not perfectly reliable and not needed while node names are truncated
//if(oldWidth > 150)
// x += oldWidth + 50;
//else
x += 150;
if(toggle == 0)
{
toggle++;
y = y + 50;
}
else
if(toggle == 1)
{
toggle = 0;
y = y - 50;
}
if(count % 5 == 0)
{
y += 100;
x = 400;
toggle = 0;
}
count++;
oldWidth = node.getWidth();
node.setLocation(x,y);
node.setLabel(name);
}
}
public static void main(String args[]) throws Exception {
String file = args.length == 0 ? "test.xml" : args[0];
System.err.println("Attempting to read map from " + file);
DEBUG.Enabled = true;
VUE.parseArgs(args);
LWMap map;
if (file.indexOf(':') >= 0)
map = OpenAction.loadMap(new java.net.URL(file));
else
map = OpenAction.loadMap(file);
System.out.println("Loaded map: " + map);
}
}