package com.cyc.tool.kbtaxonomy.viewer;
/*
* #%L
* KBTaxonomyViewer2015
* %%
* Copyright (C) 2015 Cycorp, Inc
* %%
* Licensed under the Apache 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.apache.org/licenses/LICENSE-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.
* #L%
*/
import com.cyc.tool.kbtaxonomy.builder.KBConcept;
import com.cyc.tool.kbtaxonomy.builder.NonCycConcept;
import com.cyc.tool.kbtaxonomy.builder.OpenCycConcept;
import static com.cyc.tool.kbtaxonomy.viewer.ResourceServer.RESOURCE_BASE;
import com.cyc.tool.owltools.OpenCycContent;
import fi.iki.elonen.NanoHTTPD;
import java.net.InetAddress;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import org.semanticweb.owlapi.model.OWLOntologyCreationException;
/**
*
* <p>
* Web Interface for searching for and (possibly) adding concepts to a KB Taxonomy search query.
* This version runs the Taxonomy Viewer with the Biology Word2Vec space.
*
*/
public class WebConceptFinderBio extends NanoHTTPD {
private static ConceptViewer bViewer;
private static final boolean debug = false;
private static ConceptViewer oViewer = new OpenCycViewer();
private static int port = 8081;
// private static int port = 8082;
private static final String version = "1.0";
private String graphShape;
private ResourceServer resourceServer = null;
/**
* WebConceptFinderNew constructor.
*/
public WebConceptFinderBio() {
super(port);
}
/**
*
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
processOptions(args);
bViewer = new BioOpenCycViewer();
// OpenCyc Taxonomy
oViewer.loadTaxonomy();
System.out.println("\n\nConnect on " + InetAddress.getLocalHost().getCanonicalHostName() + ":" + port);
LocalServerRunner
.run(WebConceptFinderBio.class
);
}
private static void processOptions(String[] args) {
try { // Processing the command line
Options op = new Options();
// op.addOption("h", true, "host name the server will run on");
op.addOption("p", true, "port the server will run on");
CommandLineParser clp = new PosixParser();
CommandLine cmd = clp.parse(op, args);
if (cmd.hasOption("p")) {
port = Integer.parseInt(cmd.getOptionValue("p"));
}
} catch (ParseException ex) {
//If CL parsing fails we use default options
Logger.getLogger(WebConceptFinderBio.class
.getName()).log(Level.SEVERE, null, ex);
}
}
@Override
public NanoHTTPD.Response serve(NanoHTTPD.IHTTPSession session) {
NanoHTTPD.Method method = session.getMethod();
String uri = session.getUri();
if (debug) {
System.out.println(method + " '" + uri + "' ");
}
if (session.getUri().startsWith(RESOURCE_BASE)) {
return serveFile(session.getUri().substring(RESOURCE_BASE.length() + 1));
}
Map<String, String> webParams = session.getParms();
final WebParams params = new WebParams(session.getParms());
/* Process form inputs */
if (webParams.get("childData") != null) {
String id = webParams.get("childData");
String heightStr = webParams.get("height");
int height = heightStr != null ? Integer.parseInt(heightStr) : 1;
KBConcept v = KBConcept.getExpandedConcept(id);
String json = (webParams.get("direction") != null && webParams.get("direction").equals("up"))
? v.toD3JSON(0, height, KBConcept.GraphDirection.up)
: v.toD3JSON(0, height, KBConcept.GraphDirection.down);
System.out.println("Returning data for " + id);
return new NanoHTTPD.Response(json);
}
if (webParams.get("getNodeData") != null) {
try {
OpenCycContent ocycc;
ocycc = new OpenCycContent(webParams.get("getNodeData"));
String ocycContent = ocycc.generateHtmlForConcept();
return new NanoHTTPD.Response(ocycContent);
} catch (OWLOntologyCreationException ex) {
Logger.getLogger(WebConceptFinderBio.class.getName()).log(Level.SEVERE, null, ex);
}
}
if (webParams.get("terms") != null) {
bViewer.getSelectedConceptsFromParameters(webParams.get("terms"));
}
if (webParams.get(
"searchterms") != null) {
clearLists();
oViewer.getSelectedOCycConceptsFromParameters(webParams.get("searchterms"));
}
if (webParams.get(
"nearestterms") != null) {
clearLists();
bViewer.setNearestOCycQuery(webParams.get("nearestterms"));
}
if (webParams.get(
"graphShape") != null) {
graphShape = webParams.get("graphShape");
setGraphShape(graphShape);
} else {
graphShape = "linear"; //default
}
/* Produce the page */
String scripts = "";
String page;
// Prologue and search boxes
page = bViewer.getPagePrologue(params, version);
page += "<div id='debug'> </div>\n\n\n";
page += "Search for: ";
page = oViewer.addNearestTermSearchForm(page);
page = oViewer.addConceptSearchForm(page);
Set<NonCycConcept> conceptsToGraph = new HashSet<>();
if (bViewer.getNearestOCycQuery() != null) {
bViewer.prepareNearOpenCycTerms();
} else if (oViewer.getNearestOCycQuery() != null) {
oViewer.prepareNearOpenCycTerms();
}
if ((!conceptsToGraph.isEmpty())
|| !oViewer.getSelectedOCycConcepts().isEmpty()
|| !oViewer.getNearestOCyc().isEmpty()) {
Collection<KBConcept> found = new HashSet<>();
if (!oViewer.getNearestOCyc().isEmpty()) {
found = oViewer.getNearestOCyc();
} else {
found.addAll(oViewer.getIndex().searchString(oViewer.getSelectedOCycConcepts()));
}
if (found == null) {
page += "No results.";
} else {
for (KBConcept v : found) {
int conceptNo = v.getIndex();
String ref = v.getRef();
page += "<div class=\"cgraph\" id=\"" + ref + "\" style=\"display:none;\"><hr>";
if (v instanceof OpenCycConcept) {
page += "\n\n" + v.toCloseButton();// + ": Concept: <i>" + v.getCycL() + "</i><br>" + v.getName();
if (OpenCycViewer.nonGraphingConcepts.contains(v.getCycL())) {
page += "<b>Skipping graph </b>";
} else {
page += // "<br>"+v.nLeaves()+
" \n<div id=\"area" + conceptNo + "\"></div>";
}
}
page += "<hr></div>\n";
}
page = addListsOfConcepts(page, found);
}
}
page = addDirectionsForm(page);
page += scripts + "</body>\n";
return new NanoHTTPD.Response(page);
}
private String addDirectionsForm(String page) {
page
+= "<br><h2>Directions:</h2>\n"
+ "<ul>\n"
+ "<li>Left click in the graph panel to pan around the graph.\n"
+ "<li>Right click on a purple node to see additional information from OpenCyc.\n"
+ "<li>Shift click on a purple node to redraw the graph with that node as the root.\n"
+ "</ul>";
return page;
}
private String addListsOfConcepts(String page, Collection<KBConcept> found) {
page = oViewer.getPageOpenCycList(page, found);
return page;
}
private void clearLists() {
oViewer.clearLists();
}
private void setGraphShape(String graphShape) throws RuntimeException {
if (graphShape != null) {
switch (graphShape) {
case "cluster":
JavascriptGraphs.readGraphJS("ClusterDendogram");
break;
case "linear":
JavascriptGraphs.setAllowCircles(false);
break;
case "radial":
JavascriptGraphs.setAllowCircles(true);
break;
default:
throw new RuntimeException("Bad value for radio button");
}
}
}
private NanoHTTPD.Response serveFile(String filename) {
if (resourceServer == null) {
resourceServer = new ResourceServer();
}
return resourceServer.serveFile(filename);
}
private static class LocalServerRunner {
public static void run(Class serverClass) {
try {
executeInstance((NanoHTTPD) serverClass.newInstance());
} catch (Exception e) {
e.printStackTrace();
}
}
private static void executeInstance(NanoHTTPD server) throws Exception {
try {
server.start();
System.out.println("Server started, CTRL-C to stop.\n");
// sleep forever
while (server.isAlive()) {
Thread.sleep(5000);
}
// try {
// System.in.read();
// } catch (Throwable ignored) {
// }
} catch (InterruptedException ignore) {
} finally {
server.stop();
System.out.println("Server stopped.\n");
}
}
}
}