diff --git a/src/main/java/pt/ua/bioinformatics/coeus/actions/ConfigActionBean.java b/src/main/java/pt/ua/bioinformatics/coeus/actions/ConfigActionBean.java new file mode 100644 index 0000000..04ace8e --- /dev/null +++ b/src/main/java/pt/ua/bioinformatics/coeus/actions/ConfigActionBean.java @@ -0,0 +1,991 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package pt.ua.bioinformatics.coeus.actions; + +import com.hp.hpl.jena.ontology.OntModel; +import com.hp.hpl.jena.ontology.OntProperty; +import com.hp.hpl.jena.rdf.model.ModelFactory; +import com.hp.hpl.jena.rdf.model.Property; +import com.hp.hpl.jena.util.iterator.ExtendedIterator; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.StringWriter; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.ExecutorService; +import java.util.logging.Level; +import java.util.logging.Logger; +import net.sourceforge.stripes.action.ActionBean; +import net.sourceforge.stripes.action.ActionBeanContext; +import net.sourceforge.stripes.action.DefaultHandler; +import net.sourceforge.stripes.action.ForwardResolution; +import net.sourceforge.stripes.action.Resolution; +import net.sourceforge.stripes.action.StreamingResolution; +import net.sourceforge.stripes.action.UrlBinding; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import pt.ua.bioinformatics.coeus.api.DB; +import pt.ua.bioinformatics.coeus.common.Boot; +import pt.ua.bioinformatics.coeus.common.Config; +import pt.ua.bioinformatics.coeus.common.Worker; +import pt.ua.bioinformatics.coeus.data.Predicate; + +/** + * + * @author sernadela + */ +@UrlBinding("/config/{$model}/{method}") +public class ConfigActionBean implements ActionBean { + + private static final String NOTFOUND_VIEW = "/setup/404.jsp"; + private String method; + private String model; + private ActionBeanContext context; + + public String getModel() { + return model; + } + + public void setModel(String model) { + this.model = model; + } + + public String getMethod() { + return method; + } + + public void setMethod(String method) { + this.method = method; + } + + @Override + public void setContext(ActionBeanContext actionBeanContext) { + this.context = actionBeanContext; + } + + @Override + public ActionBeanContext getContext() { + return context; + } + + @DefaultHandler + public Resolution handle() { + return new ForwardResolution(NOTFOUND_VIEW); + } + + /** + * return the config.js file + * + * @return + */ + public Resolution getconfig() { + Boot.start(); + return new StreamingResolution("application/json", Config.getFile().toJSONString()); + } + + /** + * return existent properties that matches with $method + * + * @return + */ + public Resolution properties() { + JSONArray array = new JSONArray(); + String matchingStr = method; + //HashMap map= PrefixFactory.getPrefixes(); + HashMap map = Predicate.getPredicates(); + + for (Entry e : map.entrySet()) { + String key = e.getKey(); + if (matchingStr != null) { + if (key.contains(matchingStr)) { + array.add(key); + } + } else { + array.add(key); + } + } + //System.out.println(matchingStr); + //System.out.println(array.toJSONString()); + return new StreamingResolution("application/json", array.toJSONString()); + } + + /** + * Export the database content + * + * @return + * @throws FileNotFoundException + */ + public Resolution export() throws FileNotFoundException { + StringWriter outs = new StringWriter(); + Boot.start(); + if (method.endsWith(".ttl")) { + Boot.getAPI().getModel().write(outs, "TURTLE"); + } else { + Boot.getAPI().getModel().write(outs, "RDF/XML"); + } + return new StreamingResolution("application/rdf+xml", outs.toString()); + } + + /** + * Build (Boot.build() call in a different thread) + * + * @return + */ + public Resolution build() { + JSONObject result = new JSONObject(); + String value = method; + try { + + ExecutorService executor = (ExecutorService) context.getServletContext().getAttribute("INTEGRATION_EXECUTOR"); + Runnable worker = new Worker("worker" + System.currentTimeMillis()); + executor.execute(worker); + + result.put("status", 100); + result.put("message", "[COEUS][API][ConfigActionBean] Build done."); + } catch (Exception e) { + result.put("status", 201); + result.put("message", "[COEUS][API][ConfigActionBean] Build fail. Exception: " + e); + } + return new StreamingResolution("application/json", result.toJSONString()); + } + + /** + * Change built property in config.js file. The method value only can be + * true or false. + * + * @return + */ + public Resolution changebuilt() { + JSONObject result = new JSONObject(); + try { + JSONObject f = Config.getFile(); + JSONObject config = (JSONObject) f.get("config"); + + config.put("built", Boolean.parseBoolean(method)); + f.put("config", config); + + updateFile(f.toJSONString(), Config.getPath() + "config.js"); + //apply values + Boot.resetConfig(); + + result.put("status", 100); + result.put("message", "[COEUS][API][ConfigActionBean] Built property changed."); + } catch (Exception e) { + result.put("status", 201); + result.put("message", "[COEUS][API][ConfigActionBean] Built not property changed. Exception: " + e); + } + return new StreamingResolution("application/json", result.toJSONString()); + } + +// public Resolution executor(){ +// JSONObject result = new JSONObject(); +// ExecutorService executor = (ExecutorService )context.getServletContext().getAttribute("INTEGRATION_EXECUTOR"); +// +// result.put("executor.isShutdown()", executor.isShutdown()); +// result.put("executor.isTerminated()", executor.isTerminated()); +// return new StreamingResolution("application/json", result.toJSONString()); +// } + /** + * Cleans the DB of one environment (method) + * + * @return + */ + public Resolution cleandb() { + JSONObject result = new JSONObject(); + try { + //get map.js file + String environment = "env_" + method; + String path = Config.getPath() + environment + "/"; + String map = path + "map.js"; + JSONParser parser = new JSONParser(); + String json = readToString(map); + result = (JSONObject) parser.parse(json); + int index = result.get("$sdb:jdbcURL").toString().lastIndexOf("/"); + String dbName = result.get("$sdb:jdbcURL").toString().substring(index); + DB db = new DB(dbName, result.get("$sdb:jdbcURL") + "&user=" + result.get("$sdb:sdbUser").toString() + "&password=" + result.get("$sdb:sdbPassword").toString()); + // test db connection + boolean success = db.connectX(); + + if (success) { + db.update("Truncate table Node", "TRUNCATE TABLE Nodes;"); + db.update("Truncate table Prefixes", "TRUNCATE TABLE Prefixes;"); + db.update("Truncate table Quads", "TRUNCATE TABLE Quads;"); + db.update("Truncate table Triples", "TRUNCATE TABLE Triples;"); + System.out.println("[COEUS][API][ConfigActionBean] Sdb clean OK\n"); + result.put("status", 100); + result.put("message", "[COEUS][API][ConfigActionBean] DB Cleaned in environment: " + method); + } else { + result.put("status", 200); + result.put("message", "[COEUS][API][ConfigActionBean] ERROR: Clean DB, check exception."); + } + + } catch (IOException ex) { + result.put("status", 200); + result.put("message", "[COEUS][API][ConfigActionBean] ERROR: Clean DB, check exception."); + Logger.getLogger(ConfigActionBean.class.getName()).log(Level.SEVERE, null, ex); + } catch (ParseException ex) { + result.put("status", 200); + result.put("message", "[COEUS][API][ConfigActionBean] ERROR: Clean DB, check parse exception."); + Logger.getLogger(ConfigActionBean.class.getName()).log(Level.SEVERE, null, ex); + } + return new StreamingResolution("application/json", result.toJSONString()); + } + + /** + * List all environments (i.e., all folders started by 'env_' string) + * + * @return + */ + public Resolution listenv() { + JSONObject result = new JSONObject(); + File src = new File(ConfigActionBean.class.getResource("/").getPath()); + String env[] = src.list(new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + if (dir.isDirectory() && name.startsWith("env_")) { + return true; + } else { + return false; + } + } + }); + Map> m = new HashMap>(); + List l = new ArrayList(); + l.addAll(Arrays.asList(env)); + m.put("environments", l); + result.putAll(m); + + return new StreamingResolution("application/json", result.toJSONString()); + } + + /** + * Do the mapping from map.js to the configuration files. + * + * @param path + * @throws ParseException + */ + public void updateFilesFromMap(String path) throws ParseException, IOException { + JSONParser parser = new JSONParser(); + JSONObject map = (JSONObject) parser.parse(readToString(path + "map.js")); + + //ensures that files (pubby, sdb and joseki) are clean + copyFolder(new File(Config.getPath() + "init"), new File(path), new File(path + "map.js")); + + File src = new File(path); + //list all the directory contents + String files[] = src.list(); + for (String file : files) { + if (!file.endsWith("map.js")) { + String readString = readToString(path + file); + for (Iterator it = map.entrySet().iterator(); it.hasNext();) { + Map.Entry e = (Map.Entry) it.next(); + //System.out.println(e.getKey().toString() + " " + e.getValue().toString()); + readString = readString.replace(e.getKey().toString(), e.getValue().toString()); + } + System.out.println(file); + updateFile(readString, path + file); + } + } + } + + /** + * Update a Environment: + *

Copy all values from map.js to do the mapping in the configuration + * files.

+ *

Copy files to the root dir and change the environment key in + * config.js

+ * + * @return + */ + public Resolution upenv() { + JSONObject result = new JSONObject(); + try { + Boot.start(); + String path = Config.getPath() + "env_" + method + "/"; + + updateFilesFromMap(path); + applyEnvironment(path, Config.getPath(), "env_" + method, true); + + //Load new settings + Boot.resetConfig(); + Boot.resetStorage(); + //TODO: FIX THAT - NEEDS SERVERS RESTART TO APPLY NEW CONFIGS + + result.put("status", 100); + result.put("message", "[COEUS][API][ConfigActionBean] Environment updated: " + method); + + } catch (Exception ex) { + result.put("status", 200); + result.put("message", "[COEUS][API][ConfigActionBean] ERROR: Evironment " + method + " not updated, check exception."); + Logger.getLogger(ConfigActionBean.class.getName()).log(Level.SEVERE, null, ex); + } + + //Boot.start(); + return new StreamingResolution("application/json", result.toJSONString()); + } + + /** + * Change the environment: Copy files to the root dir and update the + * environment key in config.js + * + * @param src + * @param dest + * @param environment + * @throws IOException + */ + public void applyEnvironment(String src, String dest, String environment, Boolean copyFiles) throws IOException { + //copy all files from enviroment to root dir + if (copyFiles) { + copyFolder(new File(src), new File(dest), null); + } + JSONObject f = changeConfigValue("config", "environment", environment.split("env_", 2)[1]); + //System.err.println(f.toJSONString()); + updateFile(f.toJSONString(), Config.getPath() + "config.js"); + } + + /** + * Create a new environment according to the init directory (i.e., copy all + * files to the new directory) + * + * @return + */ + public Resolution newenv() { + JSONObject result = new JSONObject(); + try { + Boot.start(); + String name = "env_" + method; + String envStr = Config.getPath() + name; + String initStr = Config.getPath() + "init"; + File env = new File(envStr); + if (env.exists()) { + result.put("status", 200); + result.put("message", "[COEUS][API][ConfigActionBean] ERROR: " + method + " already exists."); + return new StreamingResolution("application/json", result.toJSONString()); + } + File init = new File(initStr); + + copyFolder(init, env, null); + //change to this env + applyEnvironment(envStr, Config.getPath(), name, true); + //apply values + Boot.resetConfig(); + result.put("status", 100); + result.put("message", "[COEUS][API][ConfigActionBean] Environment created: " + method); + } catch (IOException ex) { + result.put("status", 200); + result.put("message", "[COEUS][API][ConfigActionBean] ERROR: " + method + " not created, check exception."); + Logger.getLogger(ConfigActionBean.class.getName()).log(Level.SEVERE, null, ex); + } + + //Boot.start(); + return new StreamingResolution("application/json", result.toJSONString()); + } + + /** + * Returns a map.js file in the environment (method) + * + * @return + */ + public Resolution getmap() { + JSONObject result = new JSONObject(); + try { + Boot.start(); + String environment = "env_" + method; + String path = Config.getPath() + environment + "/"; + String map = path + "map.js"; + JSONParser parser = new JSONParser(); + String json = readToString(map); + result = (JSONObject) parser.parse(json); + } catch (Exception ex) { + Logger.getLogger(ConfigActionBean.class.getName()).log(Level.SEVERE, null, ex); + } + return new StreamingResolution("application/json", result.toJSONString()); + } + + /** + * Receives a map.js file with only db information to update the DB configuration + * + * @return + */ + public Resolution changedb() { + JSONObject result = new JSONObject(); + try { + Boot.start(); + + JSONParser parser = new JSONParser(); + System.out.println(method); + JSONObject db = (JSONObject) parser.parse(method); + //create the DB if not exists + DB creator = new DB(); + creator.createDB(db.get("$sdb:jdbcURL").toString(), db.get("$sdb:sdbUser").toString(), db.get("$sdb:sdbPassword").toString()); + + String environment = "env_" + Config.getEnvironment(); + String path = Config.getPath() + environment + "/"; + String map = path + "map.js"; + String oldMap = readToString(map); + + JSONObject oldMapJS = (JSONObject) parser.parse(oldMap); + + for (Iterator it = db.entrySet().iterator(); it.hasNext();) { + Entry e = (Entry) it.next(); + oldMapJS.put(e.getKey(), e.getValue()); + } + +// //update map.js file + result = updateFile(oldMapJS.toJSONString(), map); +// //update files on the environment + updateFilesFromMap(path); +// //change it to use + applyEnvironment(path, Config.getPath(), environment, true); + //apply values + Boot.resetConfig(); + Boot.resetStorage(); + result.put("status", 100); + result.put("message", "[COEUS][API][ConfigActionBean] DB created."); + + } catch (ParseException ex) { + result.put("status", 200); + result.put("message", "[COEUS][API][ConfigActionBean] ERROR: On parse map.js, check exception."); + Logger.getLogger(ConfigActionBean.class.getName()).log(Level.SEVERE, null, ex); + } catch (SQLException ex) { + result.put("status", 200); + result.put("message", "[COEUS][API][ConfigActionBean] ERROR: On creating database, check exception: " + ex); + Logger.getLogger(ConfigActionBean.class.getName()).log(Level.SEVERE, null, ex); + } catch (Exception ex) { + result.put("status", 200); + result.put("message", "[COEUS][API][ConfigActionBean] ERROR: Please, check exception."); + Logger.getLogger(ConfigActionBean.class.getName()).log(Level.SEVERE, null, ex); + } + return new StreamingResolution("application/json", result.toJSONString()); + } + + /** + * Receives a map.js file with only db information to update the DB configuration + * + * @return + */ + public Resolution changepubby() { + JSONObject result = new JSONObject(); + try { + Boot.start(); + + JSONParser parser = new JSONParser(); + System.out.println(method); + JSONObject pubby = (JSONObject) parser.parse(method); + + String environment = "env_" + Config.getEnvironment(); + String path = Config.getPath() + environment + "/"; + String map = path + "map.js"; + String oldMap = readToString(map); + + JSONObject oldMapJS = (JSONObject) parser.parse(oldMap); + + for (Iterator it = pubby.entrySet().iterator(); it.hasNext();) { + Entry e = (Entry) it.next(); + oldMapJS.put(e.getKey(), e.getValue()); + } + +// //update map.js file + result = updateFile(oldMapJS.toJSONString(), map); +// //update files on the environment + updateFilesFromMap(path); +// //change it to use + applyEnvironment(path, Config.getPath(), environment, true); + //apply values + Boot.resetConfig(); + Boot.resetStorage(); + result.put("status", 100); + result.put("message", "[COEUS][API][ConfigActionBean] DB updated."); + + } catch (ParseException ex) { + result.put("status", 200); + result.put("message", "[COEUS][API][ConfigActionBean] ERROR: On parse map.js, check exception."); + Logger.getLogger(ConfigActionBean.class.getName()).log(Level.SEVERE, null, ex); + } catch (Exception ex) { + result.put("status", 200); + result.put("message", "[COEUS][API][ConfigActionBean] ERROR: Please, check exception."); + Logger.getLogger(ConfigActionBean.class.getName()).log(Level.SEVERE, null, ex); + } + return new StreamingResolution("application/json", result.toJSONString()); + } + + /** + * Receives a map.js file with only db information to create the DB + * structure. + * + * @return + */ + public Resolution db() { + JSONObject result = new JSONObject(); + try { + Boot.start(); + + JSONParser parser = new JSONParser(); + System.out.println(method); + JSONObject db = (JSONObject) parser.parse(method); + //create the DB if not exists + DB creator = new DB(); + creator.createDB(db.get("$sdb:jdbcURL").toString(), db.get("$sdb:sdbUser").toString(), db.get("$sdb:sdbPassword").toString()); + + result.put("status", 100); + result.put("message", "[COEUS][API][ConfigActionBean] DB created."); + + } catch (ParseException ex) { + result.put("status", 200); + result.put("message", "[COEUS][API][ConfigActionBean] ERROR: On parse map.js, check exception."); + Logger.getLogger(ConfigActionBean.class.getName()).log(Level.SEVERE, null, ex); + } catch (SQLException ex) { + result.put("status", 200); + result.put("message", "[COEUS][API][ConfigActionBean] ERROR: On creating database, check exception: " + ex); + Logger.getLogger(ConfigActionBean.class.getName()).log(Level.SEVERE, null, ex); + } catch (Exception ex) { + result.put("status", 200); + result.put("message", "[COEUS][API][ConfigActionBean] ERROR: Please, check exception."); + Logger.getLogger(ConfigActionBean.class.getName()).log(Level.SEVERE, null, ex); + } + return new StreamingResolution("application/json", result.toJSONString()); + } + + /** + * Receives a map.js file and update it in according to the environment key + * in config.js. + * + * @return + */ + public Resolution pubby() { + JSONObject result = new JSONObject(); + try { + Boot.start(); + + System.out.println(method); + String environment = "env_" + Config.getEnvironment(); + String path = Config.getPath() + environment + "/"; + String map = path + "map.js"; + //update map.js file + result = updateFile(method, map); + //update files on the environment + updateFilesFromMap(path); + + //change to this env + applyEnvironment(path, Config.getPath(), environment, true); + + //apply values + Boot.resetConfig(); + Boot.resetStorage(); + + } catch (ParseException ex) { + result.put("status", 200); + result.put("message", "[COEUS][API][ConfigActionBean] ERROR: On parse map.js, check exception."); + Logger.getLogger(ConfigActionBean.class.getName()).log(Level.SEVERE, null, ex); + } catch (Exception ex) { + result.put("status", 200); + result.put("message", "[COEUS][API][ConfigActionBean] ERROR: On update map.js, check exception."); + Logger.getLogger(ConfigActionBean.class.getName()).log(Level.SEVERE, null, ex); + } + return new StreamingResolution("application/json", result.toJSONString()); + } + + /** + * Delete a environment. + * + * @return + */ + public Resolution delenv() { + JSONObject result = new JSONObject(); + try { + Boot.start(); + String envStr = Config.getPath() + "env_" + method; + File env = new File(envStr); + if (env.exists()) { + delete(env); + } + result.put("status", 100); + result.put("message", "[COEUS][API][ConfigActionBean] Environment deleted: " + method); + } catch (IOException ex) { + result.put("status", 200); + result.put("message", "[COEUS][API][ConfigActionBean] ERROR: " + method + " not deleted, check exception."); + Logger.getLogger(ConfigActionBean.class.getName()).log(Level.SEVERE, null, ex); + } + + return new StreamingResolution("application/json", result.toJSONString()); + } + + public Resolution readrdf() throws MalformedURLException, IOException { + String location = "http://localhost:8080/coeus/resource/"; + //String location ="http://purl.org/dc/elements/1.1/"; + URL url = new URL(location); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + //set linked data content to rdf + conn.setRequestProperty("Accept", " application/rdf+xml"); + //conn.setRequestProperty("User-Agent", ""); + conn.setInstanceFollowRedirects(true); + HttpURLConnection.setFollowRedirects(true); + //conn.setRequestProperty("Content-Type", "application/rdf+xml"); + //HttpURLConnection conn=conn.getInputStream(); + + + StringBuilder sb = new StringBuilder(); + String line; + BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream())); + while ((line = br.readLine()) != null) { + sb.append(line); + } + br.close(); + + Map> map = conn.getHeaderFields(); + for (Map.Entry> entry : map.entrySet()) { + System.out.println(entry.getKey() + " : " + entry.getValue()); + } + + System.out.println(context.getRequest().getServletPath()); + System.out.println(context.getRequest().getServerName()); + return new StreamingResolution("text/javascript", sb.toString()); + } + + /** + * List all Ontology Proprieties. + * + * @return + */ + public Resolution getprop() { + + Boot.start(); + Set set = new TreeSet(); + StringBuilder sb = new StringBuilder(); + //get all proprieties for each prefix + JSONObject prefixes = (JSONObject) Config.getFile().get("prefixes"); + for (Object o : prefixes.values()) { + System.err.println("Reading: " + o); + set.addAll(getOntologyProperties(o.toString())); + } + + for (String s : set) { + sb.append(s); + } + + return new StreamingResolution("text/javascript", sb.toString()); + } + + /** + * Update the config section of the config.js file. + * + * @return + */ + public Resolution config() { + JSONObject result = new JSONObject(); + try { + //update config.js + String jsonString = method; + String configKey = "config"; + JSONParser parser = new JSONParser(); + //new file + JSONObject n = (JSONObject) parser.parse(jsonString); + //old file + JSONObject old = Config.getFile(); + //old config key file + JSONObject oldConfig = (JSONObject) old.get(configKey); + //update the values + HashMap m = (HashMap) n.get(configKey); + for (Entry entry : m.entrySet()) { + oldConfig.put(entry.getKey(), entry.getValue()); + } + old.put(configKey, oldConfig); + //update the file + result = updateFile(old.toJSONString(), Config.getPath() + "config.js"); + + Boot.resetConfig(); + + } catch (ParseException ex) { + result.put("status", 200); + result.put("message", "[COEUS][API][ConfigActionBean] ERROR: check the ParseException."); + Logger.getLogger(ConfigActionBean.class.getName()).log(Level.SEVERE, null, ex); + } catch (Exception ex) { + result.put("status", 200); + result.put("message", "[COEUS][API][ConfigActionBean] ERROR: Please, check exception."); + Logger.getLogger(ConfigActionBean.class.getName()).log(Level.SEVERE, null, ex); + } + return new StreamingResolution("application/json", result.toJSONString()); + } + + /** + * Update the prefixes section on config.js file and loads all Object + * Proprieties to the predicates.csv file according to the prefixes section + * on config.js. + * + * @return + */ + public Resolution prefixes() { + JSONObject result = new JSONObject(); + try { + //update config.js + String jsonString = method; + String prefixesKey = "prefixes"; + JSONParser parser = new JSONParser(); + //new file + JSONObject n = (JSONObject) parser.parse(jsonString); + //new config key file + JSONObject nPrefixes = (JSONObject) n.get(prefixesKey); + //old file + JSONObject old = Config.getFile(); + + old.put(prefixesKey, nPrefixes); + result = updateFile(old.toJSONString(), Config.getPath() + "config.js"); + //apply values + Boot.resetConfig(); + + //update predicates.csv + Set set = new TreeSet(); + JSONObject prefixes = (JSONObject) Config.getFile().get("prefixes"); + for (Object o : prefixes.values()) { + System.err.println("[COEUS][API][ConfigActionBean] Reading: " + o); + set.addAll(getOntologyProperties(o.toString())); + } + //read local ontology TODO: FIX THAT + String localOntology = context.getRequest().getScheme() + "://" + context.getRequest().getServerName() + ":" + context.getRequest().getServerPort() + context.getRequest().getContextPath() + "/ontology/"; + set.addAll(getOntologyProperties(localOntology)); + + StringBuilder sb = new StringBuilder(); + for (String s : set) { + sb.append(s); + } + + updateFile(sb.toString(), Config.getPath() + "predicates.csv"); + + + } catch (ParseException ex) { + result.put("status", 200); + result.put("message", "[COEUS][API][ConfigActionBean] ERROR: Please, check the ParseException."); + Logger.getLogger(ConfigActionBean.class.getName()).log(Level.SEVERE, null, ex); + } catch (Exception ex) { + result.put("status", 200); + result.put("message", "[COEUS][API][ConfigActionBean] ERROR: Please, check exception."); + Logger.getLogger(ConfigActionBean.class.getName()).log(Level.SEVERE, null, ex); + } + return new StreamingResolution("application/json", result.toString()); + } + + /** + * Change the key-value in the top key of the config.js file + * + * @param topkey + * @param key + * @param value + * @return + */ + public JSONObject changeConfigValue(String topKey, String key, String value) { + + JSONObject f = Config.getFile(); + System.out.println(f.toJSONString()); + System.out.println(topKey); + //JSONObject config = (JSONObject) f.get(topKey); + HashMap m = (HashMap) f.get(topKey); +// Map m = new HashMap(); +// for (Iterator it = config.entrySet().iterator(); it.hasNext();) { +// Entry e = (Entry) it.next(); +// m.put(e.getKey(), e.getValue()); +// } + System.out.println(m); + m.put(key, value); + f.put(topKey, m); + return f; + } + + /** + * Update a existing file (writing the string value) + * + * @param value + * @param filename + * @return + */ + private JSONObject updateFile(String value, String filename) { + JSONObject result = new JSONObject(); + + try { + FileWriter writer = new FileWriter(filename); + writer.write(value); + writer.flush(); + writer.close(); + result.put("status", 100); + result.put("message", "[COEUS][API][ConfigActionBean] " + filename + " updated."); + + System.out.println("[COEUS][API][ConfigActionBean] Saved: " + filename); + } catch (Exception ex) { + result.put("status", 200); + result.put("message", "[COEUS][API][ConfigActionBean] ERROR: " + filename + " not updated, check exception."); + Logger.getLogger(ConfigActionBean.class.getName()).log(Level.SEVERE, null, ex); + } + + return result; + } + + /** + * Return all ontology properties from location URL. + * + * @param location + * @return + */ + public Set getOntologyProperties(String location) { + Set set = new HashSet(); + try { + //auxiliar model + OntModel auxModel = ModelFactory.createOntologyModel(); + auxModel.read(location); + ExtendedIterator op = auxModel.listOntProperties(); + + while (op.hasNext()) { + OntProperty prop = op.next(); + //if (prop.toString().startsWith(location)) { + set.add(prop.toString() + "\n"); + //} + } + } catch (Exception e) { + System.err.println("[COEUS][API][ConfigActionBean] ERROR in read model at: " + location); + } + return set; + } + + /** + * Copy a directory. + * + * @param src + * @param dest + * @throws IOException + */ + public static void copyFolder(File src, File dest, File skipFile) + throws IOException { + + if (src.isDirectory()) { + + //if directory not exists, create it + if (!dest.exists()) { + dest.mkdir(); + System.out.println("[COEUS][API][ConfigActionBean] Directory copied from " + + src + " to " + dest); + } + + //list all the directory contents + String files[] = src.list(); + + for (String file : files) { + //construct the src and dest file structure + File srcFile = new File(src, file); + File destFile = new File(dest, file); + //recursive copy + copyFolder(srcFile, destFile, skipFile); + } + + } else { + if (skipFile == null || !(skipFile.getName().equals(src.getName()))) { + //if file, then copy it + //Use bytes stream to support all file types + InputStream in = new FileInputStream(src); + OutputStream out = new FileOutputStream(dest); + + byte[] buffer = new byte[1024]; + + int length; + //copy the file content in bytes + while ((length = in.read(buffer)) > 0) { + out.write(buffer, 0, length); + } + + in.close(); + out.close(); + System.out.println("[COEUS][API][ConfigActionBean] File copied from " + src + " to " + dest); + } + } + } + + /** + * Delete a File or Directory. + * + * @param file + * @throws IOException + */ + public static void delete(File file) + throws IOException { + + if (file.isDirectory()) { + + //directory is empty, then delete it + if (file.list().length == 0) { + + file.delete(); + System.out.println("[COEUS][API][ConfigActionBean] Directory is deleted : " + + file.getAbsolutePath()); + + } else { + + //list all the directory contents + String files[] = file.list(); + + for (String temp : files) { + //construct the file structure + File fileDelete = new File(file, temp); + + //recursive delete + delete(fileDelete); + } + + //check the directory again, if empty then delete it + if (file.list().length == 0) { + file.delete(); + System.out.println("[COEUS][API][ConfigActionBean] Directory is deleted : " + + file.getAbsolutePath()); + } + } + + } else { + //if file, then delete it + file.delete(); + System.out.println("[COEUS][API][ConfigActionBean] File is deleted : " + file.getAbsolutePath()); + } + } + + /** + * Read and Convert a File to a String + * + * @param filename + * @return + */ + public String readToString(String filename) throws IOException { + StringBuilder sb = new StringBuilder(); + + BufferedReader br = new BufferedReader(new FileReader(filename)); + String line = br.readLine(); + + while (line != null) { + sb.append(line); + sb.append('\n'); + line = br.readLine(); + } + br.close(); + return sb.toString(); + } +} diff --git a/src/main/java/pt/ua/bioinformatics/coeus/actions/ManagerActionBean.java b/src/main/java/pt/ua/bioinformatics/coeus/actions/ManagerActionBean.java new file mode 100644 index 0000000..60fba98 --- /dev/null +++ b/src/main/java/pt/ua/bioinformatics/coeus/actions/ManagerActionBean.java @@ -0,0 +1,108 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package pt.ua.bioinformatics.coeus.actions; + +import net.sourceforge.stripes.action.ActionBean; +import net.sourceforge.stripes.action.ActionBeanContext; +import net.sourceforge.stripes.action.DefaultHandler; +import net.sourceforge.stripes.action.ForwardResolution; +import net.sourceforge.stripes.action.Resolution; +import net.sourceforge.stripes.action.UrlBinding; + +/** + * + * @author sernadela + */ +@UrlBinding("/manager/{$model}/{method}") +public class ManagerActionBean implements ActionBean { + + private static final String INDEX_VIEW = "/setup/index.jsp"; + private static final String SEEDS_VIEW = "/setup/seeds.jsp"; + //private static final String SEEDS_ADD_VIEW = "/setup/addseed.jsp"; + //private static final String ENTITY_ADD_VIEW = "/setup/addentity.jsp"; + private static final String ENTITIES_VIEW = "/setup/entities.jsp"; + //private static final String CONCEPT_ADD_VIEW = "/setup/addconcept.jsp"; + private static final String CONCEPTS_VIEW = "/setup/concepts.jsp"; + //private static final String RESOURCE_ADD_VIEW = "/setup/addresource.jsp"; + private static final String RESOURCES_VIEW = "/setup/resources.jsp"; + private static final String SELECTORS_VIEW = "/setup/selectors.jsp"; + private static final String ENVIRONMENTS_VIEW = "/setup/environments.jsp"; + private static final String ENVIRONMENTS_EDIT_VIEW = "/setup/editenvironment.jsp"; + private static final String NOTFOUND_VIEW = "/setup/404.jsp"; + private static final String GRAPH_VIEW = "/setup/graph.jsp"; + private String method; + private String model; + private ActionBeanContext context; + + @DefaultHandler + public Resolution handle() { + return new ForwardResolution(NOTFOUND_VIEW); + } + + public Resolution config() { + return new ForwardResolution("/setup/config.jsp"); + } + + public Resolution graph() { + return new ForwardResolution(GRAPH_VIEW); + } + + public Resolution environments() { + if (method != null && method.startsWith("edit")) { + return new ForwardResolution(ENVIRONMENTS_EDIT_VIEW); + } else { + return new ForwardResolution(ENVIRONMENTS_VIEW); + } + } + + public Resolution seed() { + if (method == null) { + return new ForwardResolution(SEEDS_VIEW); + } else { + return new ForwardResolution(INDEX_VIEW); + } + } + + public Resolution entity() { + return new ForwardResolution(ENTITIES_VIEW); + } + + public Resolution concept() { + return new ForwardResolution(CONCEPTS_VIEW); + } + + public Resolution resource() { + return new ForwardResolution(RESOURCES_VIEW); + } + public Resolution selector() { + return new ForwardResolution(SELECTORS_VIEW); + } + + public String getModel() { + return model; + } + + public void setModel(String model) { + this.model = model; + } + + public String getMethod() { + return method; + } + + public void setMethod(String method) { + this.method = method; + } + + @Override + public void setContext(ActionBeanContext actionBeanContext) { + this.context = actionBeanContext; + } + + @Override + public ActionBeanContext getContext() { + return context; + } +} diff --git a/src/main/java/pt/ua/bioinformatics/coeus/actions/SeedActionBean.java b/src/main/java/pt/ua/bioinformatics/coeus/actions/SeedActionBean.java deleted file mode 100644 index 61d2aaa..0000000 --- a/src/main/java/pt/ua/bioinformatics/coeus/actions/SeedActionBean.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package pt.ua.bioinformatics.coeus.actions; - -import net.sourceforge.stripes.action.ActionBean; -import net.sourceforge.stripes.action.ActionBeanContext; -import net.sourceforge.stripes.action.DefaultHandler; -import net.sourceforge.stripes.action.ForwardResolution; -import net.sourceforge.stripes.action.Resolution; -import net.sourceforge.stripes.action.UrlBinding; -import pt.ua.bioinformatics.coeus.common.Config; - - -/** - * - * @author sernadela - */ -@UrlBinding("/seed/") -public class SeedActionBean implements ActionBean{ - private static final String VIEW="/setup/index.jsp"; - private String name; - private ActionBeanContext context; - - @DefaultHandler - public Resolution handle(){ - setName(Config.getName()); - return new ForwardResolution(VIEW); - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - @Override - public void setContext(ActionBeanContext actionBeanContext) { - this.context=actionBeanContext;} - - @Override - public ActionBeanContext getContext() { - return context; - } - - -} diff --git a/src/main/java/pt/ua/bioinformatics/coeus/actions/UpdateActionBean.java b/src/main/java/pt/ua/bioinformatics/coeus/actions/UpdateActionBean.java index 920872d..7174ecb 100644 --- a/src/main/java/pt/ua/bioinformatics/coeus/actions/UpdateActionBean.java +++ b/src/main/java/pt/ua/bioinformatics/coeus/actions/UpdateActionBean.java @@ -108,7 +108,7 @@ public Resolution handle() { if (sub.indexOf(":") > 1) { try { if (pred.indexOf(":") > 1) { - + System.err.println(old_obj+" , "+new_obj); // test old_obj String xsd = "http://www.w3.org/2001/XMLSchema#"; Statement statToRemove = null; @@ -142,8 +142,9 @@ public Resolution handle() { if (Boot.getAPI().containsStatement(statToRemove)) { - Boot.getAPI().addStatement(statToAdd); Boot.getAPI().removeStatement(statToRemove); + Boot.getAPI().addStatement(statToAdd); + result.put("status", 100); result.put("message", "[COEUS][API][Update] Triples updated in the knowledge base."); diff --git a/src/main/java/pt/ua/bioinformatics/coeus/actions/WriteActionBean.java b/src/main/java/pt/ua/bioinformatics/coeus/actions/WriteActionBean.java index b1b4aa1..ee8d052 100644 --- a/src/main/java/pt/ua/bioinformatics/coeus/actions/WriteActionBean.java +++ b/src/main/java/pt/ua/bioinformatics/coeus/actions/WriteActionBean.java @@ -92,6 +92,7 @@ public Resolution handle() { //verify if is a xsd type if (obj.startsWith("xsd:")) { String[] old = obj.split(":", 3); + System.err.println(obj); Literal l = Boot.getAPI().getModel().createTypedLiteral(old[2], xsd + old[1]); statToAdd = Boot.getAPI().getModel().createLiteralStatement(Boot.getAPI().createResource(PrefixFactory.decode(sub)), Predicate.get(pred), l); } else if (obj.indexOf(":") > 1) { diff --git a/src/main/java/pt/ua/bioinformatics/coeus/api/DB.java b/src/main/java/pt/ua/bioinformatics/coeus/api/DB.java index 0763ff4..547afb5 100755 --- a/src/main/java/pt/ua/bioinformatics/coeus/api/DB.java +++ b/src/main/java/pt/ua/bioinformatics/coeus/api/DB.java @@ -1,5 +1,9 @@ package pt.ua.bioinformatics.coeus.api; +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; @@ -239,4 +243,53 @@ public ResultSet getData(String query) { } } + + /** + * Create the DB and it table structure if not exists according to the giving parameters + * + * @param url + * @param user + * @param pass + * @throws ClassNotFoundException + * @throws SQLException + * @throws IOException + */ + public void createDB(String url, String user, String pass) throws ClassNotFoundException, SQLException, IOException { + + Class.forName("com.mysql.jdbc.Driver"); + url=url.replace("?autoReconnect=true",""); + String[] urlSplited=url.split("/"); + String db=urlSplited[urlSplited.length-1]; + //System.out.println(db); + String jdbc=url.replace("/"+db, "") + "?allowMultiQueries=true&user=" + user + "&password=" + pass; + System.out.println(jdbc); + connection = DriverManager.getConnection(jdbc); + String script=readScript().replaceAll("coeusdb", db); + pStatement = connection.prepareStatement(script); + pStatement.execute(); + pStatement.close(); + connection.close(); + } + + /** + * Read the coeus.sql file and convert it to String + * + * @return + * @throws FileNotFoundException + * @throws IOException + */ + public String readScript() throws FileNotFoundException, IOException { + StringBuilder sb = new StringBuilder(); + + BufferedReader br = new BufferedReader(new FileReader(DB.class.getResource("/").getPath() + "coeus.sql")); + String line = br.readLine(); + + while (line != null) { + sb.append(line); + sb.append('\n'); + line = br.readLine(); + } + br.close(); + return sb.toString(); + } } diff --git a/src/main/java/pt/ua/bioinformatics/coeus/api/plugins/OMIMPlugin.java b/src/main/java/pt/ua/bioinformatics/coeus/api/plugins/OMIMPlugin.java deleted file mode 100755 index 4e199b7..0000000 --- a/src/main/java/pt/ua/bioinformatics/coeus/api/plugins/OMIMPlugin.java +++ /dev/null @@ -1,314 +0,0 @@ -package pt.ua.bioinformatics.coeus.api.plugins; - -import au.com.bytecode.opencsv.CSVReader; -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import pt.ua.bioinformatics.coeus.api.API; -import pt.ua.bioinformatics.coeus.api.PrefixFactory; -import pt.ua.bioinformatics.coeus.common.Boot; -import pt.ua.bioinformatics.coeus.common.Config; -import pt.ua.bioinformatics.coeus.data.Predicate; -import pt.ua.bioinformatics.coeus.domain.Resource; -import pt.ua.bioinformatics.diseasecard.domain.Disease; - -/** - * DiseaseCard plugin for OMIM data handling. - *

Generates initial gene and disease dataset based on OMIM's morbid map. - *

- * - * @author pedrolopes - */ -public class OMIMPlugin { - - private Resource res; - private API api; - private HashMap diseases; - private HashMap genotypes; - - public HashMap getGenotypes() { - return genotypes; - } - - public void setGenotypes(HashMap genotypes) { - this.genotypes = genotypes; - } - - public HashMap getDiseases() { - return diseases; - } - - public void setDiseases(HashMap diseases) { - this.diseases = diseases; - } - - public Resource getRes() { - return res; - } - - public void setRes(Resource res) { - this.res = res; - } - - public OMIMPlugin(Resource res) { - this.res = res; - this.diseases = new HashMap(); - this.genotypes = new HashMap(); - this.api = Boot.getAPI(); - } - - /** - * OMIMPlugin controller. - *

Workflow:

    - *
  • Load genotype information from OMIM genemap
  • - *
  • Load phenotype information from OMIM morbidmap
  • - *
  • Import loaded dataset into COEUS SDB
  • - *

- * - */ - public void itemize() { - if (loadGenotype() && loadPhenotype()) { - triplify(); - } - } - - /** - * Loads genotype information from OMIM genemap into internal memory. - * - * @return success of the operation. - */ - private boolean loadGenotype() { - boolean success = true; - try { - //URL u = new URL("ftp://ftp.ncbi.nih.gov/repository/OMIM/ARCHIVE/genemap"); - URL u = new URL("http://localhost/~pedrolopes/omim/genemap_small"); - BufferedReader in = new BufferedReader(new InputStreamReader(u.openStream())); - CSVReader reader = new CSVReader(in, '|'); - List genemap = reader.readAll(); - for (String[] genes : genemap) { - Disease d = new Disease(genes[7], genes[9]); - d.setLocation(genes[4]); - genotypes.put(d.getOmimId(), d); - String[] genelist = genes[5].split(", "); - d.getGenes().addAll(Arrays.asList(genelist)); - } - success = true; - } catch (Exception ex) { - if (Config.isDebug()) { - System.out.println("[COEUS][OMIM] Unable to load genotype information from OMIM"); - Logger.getLogger(OMIMPlugin.class.getName()).log(Level.SEVERE, null, ex); - } - } - return success; - - } - - /** - * Loads phenotype information from OMIM morbid into internal memory. - * - * @return success of the operation. - */ - private boolean loadPhenotype() { - boolean success = false; - try { - //URL u = new URL("ftp://ftp.ncbi.nih.gov/repository/OMIM/ARCHIVE/morbidmap"); - URL u = new URL("http://localhost/~pedrolopes/omim/morbidmap_small"); - BufferedReader in = new BufferedReader(new InputStreamReader(u.openStream())); - CSVReader reader = new CSVReader(in, '|'); - List morbidmap = reader.readAll(); - Pattern p = Pattern.compile("[0-9]{6}"); - - for (String[] disease : morbidmap) { - Disease d; - Matcher m = p.matcher(disease[0]); - String pheno_omim = ""; - String dis_name = ""; - - try { - if (m.find()) { - pheno_omim = m.group(0); - dis_name = disease[0].substring(0, disease[0].length() - 14); - - // check if disease is already on list - if (diseases.containsKey(pheno_omim)) { - d = diseases.get(pheno_omim); - d.getNames().add(dis_name); - Disease genotype = genotypes.get(disease[2]); - if (!d.getGenotypes().contains(genotype)) { - d.getGenotypes().add(genotype); - } - if (!genotype.getPhenotypes().contains(d)) { - genotype.getPhenotypes().add(d); - } - String[] genelist = disease[1].split(", "); - d.getGenes().addAll(Arrays.asList(genelist)); - } else { - d = new Disease(dis_name, pheno_omim); - d.setLocation(disease[3]); - d.getNames().add(dis_name); - diseases.put(pheno_omim, d); - Disease genotype = genotypes.get(disease[2]); - if (!d.getGenotypes().contains(genotype)) { - d.getGenotypes().add(genotype); - } - if (!genotype.getPhenotypes().contains(d)) { - genotype.getPhenotypes().add(d); - } - String[] genelist = disease[1].split(", "); - d.getGenes().addAll(Arrays.asList(genelist)); - } - // not a phenotype, add to only genotypes list - } else { - Disease genotype = genotypes.get(disease[2]); - d = new Disease(disease[0], genotype.getOmimId()); - d.getNames().add(disease[0]); - d.setLocation(disease[3]); - if (!d.getGenotypes().contains(genotype)) { - d.getGenotypes().add(genotype); - } - if (!genotype.getPhenotypes().contains(d)) { - genotype.getPhenotypes().add(d); - } - diseases.put(d.getOmimId(), d); - } - } catch (Exception ex) { - if (Config.isDebug()) { - System.out.println("[COEUS][OMIM] Unable to load phenotype information from OMIM for " + disease[0]); - Logger.getLogger(OMIMPlugin.class.getName()).log(Level.SEVERE, null, ex); - } - } - } - success = true; - } catch (Exception ex) { - if (Config.isDebug()) { - System.out.println("[COEUS][OMIM] Unable to load phenotype information from OMIM"); - Logger.getLogger(OMIMPlugin.class.getName()).log(Level.SEVERE, null, ex); - } - } - return success; - } - - /** - * Loads the in-memory data into COEUS SDB. - *

Workflow

    - *
  • Loads genotypes
  • - *
  • Loads genes for each genotype
  • - *
  • Loads genotypes for each genotype
  • - *
  • Loads genes for each phenotype
  • - *

- * - */ - public void triplify() { - for (Disease genotype : genotypes.values()) { - if (!genotype.getOmimId().equals("")) { - try { - String[] itemTmp = res.getIsResourceOf().getLabel().split("_"); - com.hp.hpl.jena.rdf.model.Resource geno_item = api.createResource(PrefixFactory.getURIForPrefix(Config.getKeyPrefix()) + itemTmp[1] + "_" + genotype.getOmimId()); - com.hp.hpl.jena.rdf.model.Resource geno_obj = api.createResource(PrefixFactory.getURIForPrefix(Config.getKeyPrefix()) + "Item"); - api.addStatement(geno_item, Predicate.get("rdf:type"), geno_obj); - - // set Item label - api.addStatement(geno_item, Predicate.get("rdfs:label"), "omim_" + genotype.getOmimId()); - - // associate Item with Concept - com.hp.hpl.jena.rdf.model.Resource con = api.getResource(res.getIsResourceOf().getUri()); - api.addStatement(geno_item, Predicate.get("coeus:hasConcept"), con); - api.addStatement(con, Predicate.get("coeus:isConceptOf"), geno_item); - - // add name/comment - api.addStatement(geno_item, Predicate.get("rdfs:comment"), genotype.getName()); - api.addStatement(geno_item, Predicate.get("dc:description"), genotype.getName()); - for (String name : genotype.getNames()) { - api.addStatement(geno_item, Predicate.get("diseasecard:name"), name); - } - - api.addStatement(geno_item, Predicate.get("diseasecard:omim"), genotype.getOmimId()); - api.addStatement(geno_item, Predicate.get("diseasecard:chromosomalLocation"), genotype.getLocation()); - - triplifyGenes(genotype.getGenes(), geno_item); - - for (Disease phenotype : genotype.getPhenotypes()) { - com.hp.hpl.jena.rdf.model.Resource pheno_item = api.createResource(PrefixFactory.getURIForPrefix(Config.getKeyPrefix()) + itemTmp[1] + "_" + phenotype.getOmimId()); - com.hp.hpl.jena.rdf.model.Resource pheno_obj = api.createResource(PrefixFactory.getURIForPrefix(Config.getKeyPrefix()) + "Item"); - api.addStatement(pheno_item, Predicate.get("rdf:type"), pheno_obj); - - // set Item label - api.addStatement(pheno_item, Predicate.get("rdfs:label"), "hgnc_" + phenotype.getOmimId()); - - // associate Item with Concept - com.hp.hpl.jena.rdf.model.Resource pheno_concept = api.getResource(res.getIsResourceOf().getUri()); - api.addStatement(pheno_item, Predicate.get("coeus:hasConcept"), pheno_concept); - api.addStatement(pheno_concept, Predicate.get("coeus:isConceptOf"), pheno_item); - - // add name/comment - api.addStatement(pheno_item, Predicate.get("rdfs:comment"), phenotype.getName()); - api.addStatement(pheno_item, Predicate.get("dc:description"), phenotype.getName()); - for (String name : phenotype.getNames()) { - api.addStatement(pheno_item, Predicate.get("diseasecard:name"), name); - } - api.addStatement(pheno_item, Predicate.get("diseasecard:omim"), phenotype.getOmimId()); - api.addStatement(pheno_item, Predicate.get("diseasecard:chromosomalLocation"), phenotype.getLocation()); - - //add diseasecard-specific info - api.addStatement(pheno_item, Predicate.get("diseasecard:phenotype"), "true"); - api.addStatement(pheno_item, Predicate.get("diseasecard:hasGenotype"), geno_item); - api.addStatement(geno_item, Predicate.get("diseasecard:hasPhenotype"), pheno_item); - - triplifyGenes(phenotype.getGenes(), pheno_item); - } - - api.addStatement(geno_item, Predicate.get("diseasecard:genotype"), "true"); - } catch (Exception ex) { - if (Config.isDebug()) { - System.out.println("[COEUS][OMIM] Unable to triplify inmemory data"); - Logger.getLogger(OMIMPlugin.class.getName()).log(Level.SEVERE, null, ex); - } - } - } - } - } - - /** - * Handles gene writing into COEUS SDB. - * - * @param genes the list of genes to insert. - * @param item the item where the genes will be associated - * (coeus:isAssociatedTo). - */ - private void triplifyGenes(ArrayList genes, com.hp.hpl.jena.rdf.model.Resource item) { - for (String gene : genes) { - try { - com.hp.hpl.jena.rdf.model.Resource gene_item = api.createResource(PrefixFactory.getURIForPrefix(Config.getKeyPrefix()) + "hgnc_" + gene); - com.hp.hpl.jena.rdf.model.Resource gene_obj = api.createResource(PrefixFactory.getURIForPrefix(Config.getKeyPrefix()) + "Item"); - api.addStatement(gene_item, Predicate.get("rdf:type"), gene_obj); - - // set Item label - api.addStatement(gene_item, Predicate.get("rdfs:label"), api.createResource("item_" + gene)); - - // set Item title - api.addStatement(gene_item, Predicate.get("dc:title"), gene.toUpperCase()); - - // associate Item with Concept - com.hp.hpl.jena.rdf.model.Resource gene_concept = api.getResource(PrefixFactory.getURIForPrefix(Config.getKeyPrefix()) + "concept_HGNC"); - api.addStatement(gene_item, Predicate.get("coeus:hasConcept"), gene_concept); - api.addStatement(gene_concept, Predicate.get("coeus:isConceptOf"), gene_item); - api.addStatement(gene_item, Predicate.get("coeus:isAssociatedTo"), item); - api.addStatement(item, Predicate.get("coeus:isAssociatedTo"), gene_item); - - } catch (Exception ex) { - if (Config.isDebug()) { - System.out.println("[COEUS][OMIM] Unable to triplify gene information"); - Logger.getLogger(OMIMPlugin.class.getName()).log(Level.SEVERE, null, ex); - } - } - } - } -} diff --git a/src/main/java/pt/ua/bioinformatics/coeus/common/Boot.java b/src/main/java/pt/ua/bioinformatics/coeus/common/Boot.java index cf38f7b..17960dd 100755 --- a/src/main/java/pt/ua/bioinformatics/coeus/common/Boot.java +++ b/src/main/java/pt/ua/bioinformatics/coeus/common/Boot.java @@ -31,6 +31,74 @@ public static void setAPI(API api) { Boot.api = api; } + /** + * Reset and load COEUS config.js. + */ + public static void resetConfig() { + try { + Config.setLoaded(false); + Config.load(); + } catch (Exception e) { + if (Config.isDebug()) { + System.out.println("[COEUS][Boot] Unable to reset COEUS instance"); + } + Logger.getLogger(Boot.class.getName()).log(Level.SEVERE, null, e); + } + + } + + /** + * Reset and load COEUS Storage information (connect, ontology, setup, + * predicates). + *

    + *
  1. Reset and load
  2. + *
  3. Reset and load config.js
  4. + *

+ */ + public static void resetStorage() { + try { + Storage.setLoaded(false); + Storage.load(); + Storage.loadPredicates(); + } catch (Exception e) { + if (Config.isDebug()) { + System.out.println("[COEUS][Boot] Unable to reset COEUS instance"); + } + Logger.getLogger(Boot.class.getName()).log(Level.SEVERE, null, e); + } + + } + + /** + * Build COEUS instance. + *

    + *
  1. Load Storage information (connect, ontology, setup, predicates)
  2. + *
  3. Build instance
  4. + *
  5. Save and restart
  6. + *

+ */ + public synchronized static void build() { + try { + Boot.start(); + if (!Config.isBuilt()) { + long i = System.currentTimeMillis(); + Builder.build(); + Builder.save(); + long f = System.currentTimeMillis(); + System.out.println("\n\t[COEUS] " + Config.getName() + " Integration done in " + ((f - i) / 1000) + " seconds.\n"); + Config.setBuiltOnFile(true); + } else { + System.out.println("\n\t[COEUS] " + Config.getName() + " Integration Already done.\n"); + } + } catch (Exception e) { + if (Config.isDebug()) { + System.out.println("[COEUS][Boot] Unable to build COEUS instance"); + } + Logger.getLogger(Boot.class.getName()).log(Level.SEVERE, null, e); + } + + } + /** * Starts the configured COEUS instance. *

Built workflow

    @@ -46,30 +114,11 @@ public static void setAPI(API api) { public static void start() { if (!started) { try { - try { - Config.load(); - } catch (Exception ex) { - if (Config.isDebug()) { - System.out.println("[COEUS][Boot] Unable to load configuration"); - } - Logger.getLogger(Boot.class.getName()).log(Level.SEVERE, null, ex); - } - if (!Config.isBuilt()) { - Storage.load(); - api = new API(); - Storage.loadPredicates(); - Builder.build(); - Builder.save(); - //remove - Config.setBuilt(true); - start(); - } else { - Storage.connect(); - api = new API(); - Storage.loadPredicates(); - System.out.println("\n\t[COEUS] " + Config.getName() + " Online\n"); - } - + Config.load(); + Storage.load(); + api = new API(); + Storage.loadPredicates(); + System.out.println("\n\t[COEUS] " + Config.getName() + " Online\n"); started = true; } catch (Exception ex) { if (Config.isDebug()) { diff --git a/src/main/java/pt/ua/bioinformatics/coeus/common/Builder.java b/src/main/java/pt/ua/bioinformatics/coeus/common/Builder.java index 0d53f1b..31d1816 100755 --- a/src/main/java/pt/ua/bioinformatics/coeus/common/Builder.java +++ b/src/main/java/pt/ua/bioinformatics/coeus/common/Builder.java @@ -10,7 +10,6 @@ import org.json.simple.parser.JSONParser; import pt.ua.bioinformatics.coeus.data.connect.CSVFactory; import pt.ua.bioinformatics.coeus.data.connect.LinkedDataFactory; -import pt.ua.bioinformatics.coeus.data.connect.PluginFactory; import pt.ua.bioinformatics.coeus.data.connect.RDFFactory; import pt.ua.bioinformatics.coeus.data.connect.ResourceFactory; import pt.ua.bioinformatics.coeus.data.connect.SPARQLFactory; @@ -158,9 +157,7 @@ public static boolean readData(Resource r) { ResourceFactory factory; try { if (!r.isBuilt()) { - if (r.getPublisher().equalsIgnoreCase("plugin")) { - factory = new PluginFactory(r); - } else if (r.getPublisher().equalsIgnoreCase("csv")) { + if (r.getPublisher().equalsIgnoreCase("csv")) { factory = new CSVFactory(r); } else if (r.getPublisher().equalsIgnoreCase("xml")) { factory = new XMLFactory(r); diff --git a/src/main/java/pt/ua/bioinformatics/coeus/common/Config.java b/src/main/java/pt/ua/bioinformatics/coeus/common/Config.java index bbe6183..649ebc6 100755 --- a/src/main/java/pt/ua/bioinformatics/coeus/common/Config.java +++ b/src/main/java/pt/ua/bioinformatics/coeus/common/Config.java @@ -3,6 +3,7 @@ import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; +import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; @@ -11,6 +12,7 @@ import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; +import pt.ua.bioinformatics.coeus.actions.ConfigActionBean; import pt.ua.bioinformatics.coeus.api.PrefixFactory; /** @@ -33,7 +35,7 @@ public class Config { private static boolean debug = false; private static boolean built = false; private static String path = ""; - private static String environment = "development"; + private static String environment = "default"; private static ArrayList apikeys = new ArrayList(); public static ArrayList getApikeys() { @@ -51,7 +53,6 @@ public static String getEnvironment() { public static void setEnvironment(String environment) { Config.environment = environment; } - public static String getPath() { return path; } @@ -192,7 +193,7 @@ public static boolean load() { predicates = (String) config.get("predicates"); environment = (String) config.get("environment"); apikeys.addAll(Arrays.asList(((String) config.get("apikey")).split("\\|"))); - sdb = ((String) config.get("sdb")).replace(".ttl", "_" + environment + ".ttl"); + sdb = ((String) config.get("sdb"));//.replace(".ttl", "_" + environment + ".ttl"); keyPrefix = (String) config.get("keyprefix"); JSONObject prefixes = (JSONObject) file.get("prefixes"); for (Object o : prefixes.keySet()) { @@ -238,4 +239,48 @@ private static String readFile() { } return new String(buffer); } + + /** + * Write new config.js file + * + * @param file + */ + static void writeFile(JSONObject file) { + try { + FileWriter writer = new FileWriter(path + "config.js"); + writer.write(file.toJSONString()); + writer.flush(); + writer.close(); + + if (Config.isDebug()) { + System.out.println("[COEUS][Config] config.js file updated."); + } + } catch (Exception ex) { + if (Config.isDebug()) { + System.out.println("[COEUS][Config] ERROR: updating config.js."); + } + Logger.getLogger(Config.class.getName()).log(Level.SEVERE, null, ex); + } + } + + /** + * Change built property on config file + * + * @param builder + */ + static void setBuiltOnFile(boolean builder) { + try { + JSONObject f = Config.getFile(); + JSONObject config = (JSONObject) f.get("config"); + config.put("built", builder); + f.put("config", config); + writeFile(f); + Config.setBuilt(builder); + } catch (Exception ex) { + if (Config.isDebug()) { + System.out.println("[COEUS][Config] ERROR: setBuiltOnFile."); + } + Logger.getLogger(Config.class.getName()).log(Level.SEVERE, null, ex); + } + } } \ No newline at end of file diff --git a/src/main/java/pt/ua/bioinformatics/coeus/common/ExecutorContextListener.java b/src/main/java/pt/ua/bioinformatics/coeus/common/ExecutorContextListener.java new file mode 100644 index 0000000..62a13a9 --- /dev/null +++ b/src/main/java/pt/ua/bioinformatics/coeus/common/ExecutorContextListener.java @@ -0,0 +1,47 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package pt.ua.bioinformatics.coeus.common; + +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; + +/** + * + * @author sernadela + */ +public class ExecutorContextListener implements ServletContextListener{ + private ExecutorService executor; + + @Override + public void contextInitialized(ServletContextEvent sce) { + ServletContext context = sce.getServletContext(); + executor = Executors.newFixedThreadPool(4); + context.setAttribute("INTEGRATION_EXECUTOR", executor); + Boot.start(); + System.out.println("ServletContextListener started"); + } + + @Override + public void contextDestroyed(ServletContextEvent sce) { + ServletContext context = sce.getServletContext(); + System.out.println("ServletContextListener destroyed"); + List list=executor.shutdownNow(); + //System.err.println("\n\n\nList of runnables:\n\n"); + //for(Runnable r : list){ + // System.err.println(r.toString()); + //} +// System.err.println("\n\n\nList of Threads:\n\n"); +// Set threadSet = Thread.getAllStackTraces().keySet(); +// Thread[] threadArray = threadSet.toArray(new Thread[threadSet.size()]); +// for(Thread t:threadArray) { +// System.err.println(t.getName()); +// } + } + +} diff --git a/src/main/java/pt/ua/bioinformatics/coeus/common/HttpListener.java b/src/main/java/pt/ua/bioinformatics/coeus/common/HttpListener.java index ef30aa3..04c9f59 100644 --- a/src/main/java/pt/ua/bioinformatics/coeus/common/HttpListener.java +++ b/src/main/java/pt/ua/bioinformatics/coeus/common/HttpListener.java @@ -20,7 +20,6 @@ public void sessionCreated(HttpSessionEvent se) { @Override public void sessionDestroyed(HttpSessionEvent se) { - } } diff --git a/src/main/java/pt/ua/bioinformatics/coeus/common/Run.java b/src/main/java/pt/ua/bioinformatics/coeus/common/Run.java index ec79b1c..25be558 100755 --- a/src/main/java/pt/ua/bioinformatics/coeus/common/Run.java +++ b/src/main/java/pt/ua/bioinformatics/coeus/common/Run.java @@ -2,6 +2,7 @@ import java.util.logging.Level; import java.util.logging.Logger; +import org.json.simple.JSONObject; /** * diff --git a/src/main/java/pt/ua/bioinformatics/coeus/common/Tester.java b/src/main/java/pt/ua/bioinformatics/coeus/common/Tester.java index 67c29b5..fe19ad8 100644 --- a/src/main/java/pt/ua/bioinformatics/coeus/common/Tester.java +++ b/src/main/java/pt/ua/bioinformatics/coeus/common/Tester.java @@ -40,7 +40,7 @@ public static void main(String[] args) { try { // clean sdb - cleanSDB("localhost","coeus", "demo", "demo"); + cleanSDB("localhost","3306","coeus", "demo", "demo"); // Start import process Boot.start(); @@ -81,9 +81,10 @@ public static void main(String[] args) { * @param dbUserName * @param dbPassword */ - public static void cleanSDB(String host, String dbname, String dbUserName, String dbPassword) { + public static boolean cleanSDB(String host,String port, String dbname, String dbUserName, String dbPassword) { - DB db = new DB(dbname, "jdbc:mysql://"+host+":3306/" + dbname + "?autoReconnect=true&user=" + dbUserName + "&password=" + dbPassword); + boolean result=false; + DB db = new DB(dbname, "jdbc:mysql://"+host+":"+port+"/" + dbname + "?autoReconnect=true&user=" + dbUserName + "&password=" + dbPassword); // test db connection boolean success = db.connectX(); @@ -94,9 +95,11 @@ public static void cleanSDB(String host, String dbname, String dbUserName, Strin db.update("Truncate table Quads", "TRUNCATE TABLE Quads;"); db.update("Truncate table Triples", "TRUNCATE TABLE Triples;"); System.out.println("Sdb clean OK\n"); + result=true; } else { System.err.println("FAIL: Sdb not clean!!"); } + return result; } /** diff --git a/src/main/java/pt/ua/bioinformatics/coeus/common/Worker.java b/src/main/java/pt/ua/bioinformatics/coeus/common/Worker.java new file mode 100644 index 0000000..b9d77e9 --- /dev/null +++ b/src/main/java/pt/ua/bioinformatics/coeus/common/Worker.java @@ -0,0 +1,29 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package pt.ua.bioinformatics.coeus.common; + +/** + * + * @author sernadela + */ +public class Worker implements Runnable{ + String name; + + public Worker(String name){ + this.name=name; + } + + @Override + public void run() { + System.out.println("worker run call"); + Boot.build(); + } + + @Override + public String toString(){ + return name; + } + +} diff --git a/src/main/java/pt/ua/bioinformatics/coeus/data/Storage.java b/src/main/java/pt/ua/bioinformatics/coeus/data/Storage.java index 0f7c6a3..2cc2241 100755 --- a/src/main/java/pt/ua/bioinformatics/coeus/data/Storage.java +++ b/src/main/java/pt/ua/bioinformatics/coeus/data/Storage.java @@ -98,6 +98,7 @@ public static void setStore(Store store) { */ public static boolean connect() { try { + Storage.close(); store = (Store) SDBFactory.connectStore(Config.getPath() + Config.getSdb()); model = SDBFactory.connectDefaultModel(store); infmodel = ModelFactory.createInfModel(reasoner, model); @@ -125,6 +126,7 @@ public static boolean connect() { */ public static boolean connectX() { try { + Storage.close(); store = (Store) SDBFactory.connectStore(Config.getPath() + Config.getSdb()); model = SDBFactory.connectDefaultModel(store); connected = true; @@ -388,4 +390,25 @@ private static boolean reset() { } return success; } + + /** + * Close COEUS Store connection if is not closed: + * + * Prevent the launch of new threads if already exists. + * + * @return + */ + private static boolean close() { + boolean success = true; + try { + if(store!=null && !store.isClosed()) store.close(); + success = true; + } catch (Exception ex) { + if (Config.isDebug()) { + System.out.println("[COEUS][Storage] unable to close COEUS SDB"); + } + Logger.getLogger(Storage.class.getName()).log(Level.SEVERE, null, ex); + } + return success; + } } diff --git a/src/main/java/pt/ua/bioinformatics/coeus/data/Triplify.java b/src/main/java/pt/ua/bioinformatics/coeus/data/Triplify.java index 7d26d1e..8205129 100755 --- a/src/main/java/pt/ua/bioinformatics/coeus/data/Triplify.java +++ b/src/main/java/pt/ua/bioinformatics/coeus/data/Triplify.java @@ -107,7 +107,7 @@ public boolean itemize(String i) { boolean success = false; try { // create initial Item triple with _ structure - String[] itemTmp = resource.getIsResourceOf().getLabel().split("_"); + String[] itemTmp = resource.getIsResourceOf().getUri().split("_"); com.hp.hpl.jena.rdf.model.Resource item = api.createResource(PrefixFactory.getURIForPrefix(Config.getKeyPrefix()) + itemTmp[1] + "_" + i); com.hp.hpl.jena.rdf.model.Resource obj = api.createResource(PrefixFactory.getURIForPrefix(Config.getKeyPrefix()) + "Item"); api.addStatement(item, Predicate.get("rdf:type"), obj); diff --git a/src/main/java/pt/ua/bioinformatics/coeus/data/connect/CSVFactory.java b/src/main/java/pt/ua/bioinformatics/coeus/data/connect/CSVFactory.java index 961f554..57cc34b 100755 --- a/src/main/java/pt/ua/bioinformatics/coeus/data/connect/CSVFactory.java +++ b/src/main/java/pt/ua/bioinformatics/coeus/data/connect/CSVFactory.java @@ -1,6 +1,7 @@ package pt.ua.bioinformatics.coeus.data.connect; import au.com.bytecode.opencsv.CSVReader; +import com.hp.hpl.jena.rdf.model.Statement; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; @@ -91,17 +92,9 @@ public void read() { reader = new CSVReader(in, csvDelimiter, defaultCsvQuotes, defaultCsvHeader); } else { String[] csvKeys = res.getQuery().split("\\|"); - char querySeparator = csvKeys[0].charAt(0); char queryQuotes = csvKeys[1].charAt(0); - char queryLinesSkip = csvKeys[2].charAt(0); - - //Fix that - if (querySeparator == 't') { - querySeparator = '\t'; - } - if (querySeparator == 'n') { - querySeparator = '\n'; - } + char queryLinesSkip = csvKeys[0].charAt(0); + char querySeparator = guessDelimiter(u, queryQuotes, queryLinesSkip); //System.out.println(res.getQuery() + " - " +querySeparator+ queryQuotes + queryLinesSkip); reader = new CSVReader(in, querySeparator, queryQuotes, queryLinesSkip); @@ -147,17 +140,9 @@ public void read() { reader = new CSVReader(in, csvDelimiter, defaultCsvQuotes, defaultCsvHeader); } else { String[] csvKeys = res.getQuery().split("\\|"); - char querySeparator = csvKeys[0].charAt(0); char queryQuotes = csvKeys[1].charAt(0); - char queryLinesSkip = csvKeys[2].charAt(0); - - //Fix that - if (querySeparator == 't') { - querySeparator = '\t'; - } - if (querySeparator == 'n') { - querySeparator = '\n'; - } + char queryLinesSkip = csvKeys[0].charAt(0); + char querySeparator = guessDelimiter(u, queryQuotes, queryLinesSkip); //System.out.println(res.getQuery() + " - " +querySeparator+ queryQuotes + queryLinesSkip); reader = new CSVReader(in, querySeparator, queryQuotes, queryLinesSkip); @@ -195,17 +180,9 @@ public void read() { reader = new CSVReader(in, csvDelimiter, defaultCsvQuotes, defaultCsvHeader); } else { String[] csvKeys = res.getQuery().split("\\|"); - char querySeparator = csvKeys[0].charAt(0); char queryQuotes = csvKeys[1].charAt(0); - char queryLinesSkip = csvKeys[2].charAt(0); - - //Fix that - if (querySeparator == 't') { - querySeparator = '\t'; - } - if (querySeparator == 'n') { - querySeparator = '\n'; - } + char queryLinesSkip = csvKeys[0].charAt(0); + char querySeparator = guessDelimiter(u, queryQuotes, queryLinesSkip); //System.out.println(res.getQuery() + " - " +querySeparator+ queryQuotes + queryLinesSkip); reader = new CSVReader(in, querySeparator, queryQuotes, queryLinesSkip); @@ -258,17 +235,9 @@ public void read() { reader = new CSVReader(in, csvDelimiter, defaultCsvQuotes, defaultCsvHeader); } else { String[] csvKeys = res.getQuery().split("\\|"); - char querySeparator = csvKeys[0].charAt(0); char queryQuotes = csvKeys[1].charAt(0); - char queryLinesSkip = csvKeys[2].charAt(0); - - //Fix that - if (querySeparator == 't') { - querySeparator = '\t'; - } - if (querySeparator == 'n') { - querySeparator = '\n'; - } + char queryLinesSkip = csvKeys[0].charAt(0); + char querySeparator = guessDelimiter(u, queryQuotes, queryLinesSkip); //System.out.println(res.getQuery() + " - " + querySeparator + queryQuotes + queryLinesSkip); reader = new CSVReader(in, querySeparator, queryQuotes, queryLinesSkip); @@ -325,6 +294,8 @@ public boolean save() { try { API api = Boot.getAPI(); com.hp.hpl.jena.rdf.model.Resource resource = api.getResource(this.res.getUri()); + Statement statementToRemove = api.getModel().createLiteralStatement(resource, Predicate.get("coeus:built"), false); + api.removeStatement(statementToRemove); api.addStatement(resource, Predicate.get("coeus:built"), true); success = true; if (Config.isDebug()) { @@ -356,10 +327,9 @@ public char guessDelimiter(URL urlLocation, char quotes, int headerSkip) { int minColums = 1; int linesToCheck = 4; - try { - - for (int a = 0; a < delimiters.length; a++) { - boolean b = true; + for (int a = 0; a < delimiters.length; a++) { + boolean b = true; + try { BufferedReader br = new BufferedReader(new InputStreamReader(urlLocation.openStream())); CSVReader testReader = new CSVReader(br, delimiters[a], quotes, headerSkip); @@ -381,17 +351,16 @@ public char guessDelimiter(URL urlLocation, char quotes, int headerSkip) { } } - if (b) { - //System.out.println("Find:" + delimiters[a]); - return delimiters[a]; - } + } catch (Exception e) { + b = false; } - } catch (IOException ex) { - Logger.getLogger(CSVFactory.class.getName()).log(Level.SEVERE, null, ex); - } catch (NullPointerException ex) { - Logger.getLogger(CSVFactory.class.getName()).log(Level.SEVERE, null, ex); + if (b) { + //System.out.println("Find:" + delimiters[a]); + return delimiters[a]; + } } + return failReturn; } } diff --git a/src/main/java/pt/ua/bioinformatics/coeus/data/connect/JSONFactory.java b/src/main/java/pt/ua/bioinformatics/coeus/data/connect/JSONFactory.java index 04b15e5..4d4ee47 100644 --- a/src/main/java/pt/ua/bioinformatics/coeus/data/connect/JSONFactory.java +++ b/src/main/java/pt/ua/bioinformatics/coeus/data/connect/JSONFactory.java @@ -4,6 +4,7 @@ */ package pt.ua.bioinformatics.coeus.data.connect; +import com.hp.hpl.jena.rdf.model.Statement; import com.jayway.jsonpath.JsonPath; import java.io.InputStreamReader; import java.net.URL; @@ -270,6 +271,8 @@ public boolean save() { try { API api = Boot.getAPI(); com.hp.hpl.jena.rdf.model.Resource resource = api.getResource(this.res.getUri()); + Statement statementToRemove=api.getModel().createLiteralStatement(resource, Predicate.get("coeus:built"), false); + api.removeStatement(statementToRemove); api.addStatement(resource, Predicate.get("coeus:built"), true); success = true; if (Config.isDebug()) { diff --git a/src/main/java/pt/ua/bioinformatics/coeus/data/connect/LinkedDataFactory.java b/src/main/java/pt/ua/bioinformatics/coeus/data/connect/LinkedDataFactory.java index 9293483..7663441 100644 --- a/src/main/java/pt/ua/bioinformatics/coeus/data/connect/LinkedDataFactory.java +++ b/src/main/java/pt/ua/bioinformatics/coeus/data/connect/LinkedDataFactory.java @@ -4,6 +4,7 @@ */ package pt.ua.bioinformatics.coeus.data.connect; +import com.hp.hpl.jena.rdf.model.Statement; import java.net.URL; import java.net.URLConnection; import java.util.HashMap; @@ -115,6 +116,8 @@ public boolean save() { try { API api = Boot.getAPI(); com.hp.hpl.jena.rdf.model.Resource resource = api.getResource(this.res.getUri()); + Statement statementToRemove=api.getModel().createLiteralStatement(resource, Predicate.get("coeus:built"), false); + api.removeStatement(statementToRemove); api.addStatement(resource, Predicate.get("coeus:built"), true); success = true; if (Config.isDebug()) { diff --git a/src/main/java/pt/ua/bioinformatics/coeus/data/connect/PluginFactory.java b/src/main/java/pt/ua/bioinformatics/coeus/data/connect/PluginFactory.java deleted file mode 100755 index 2a68860..0000000 --- a/src/main/java/pt/ua/bioinformatics/coeus/data/connect/PluginFactory.java +++ /dev/null @@ -1,86 +0,0 @@ -package pt.ua.bioinformatics.coeus.data.connect; - -import java.util.logging.Level; -import java.util.logging.Logger; -import pt.ua.bioinformatics.coeus.api.API; -import pt.ua.bioinformatics.coeus.api.plugins.OMIMPlugin; -import pt.ua.bioinformatics.coeus.common.Boot; -import pt.ua.bioinformatics.coeus.common.Config; -import pt.ua.bioinformatics.coeus.data.Predicate; -import pt.ua.bioinformatics.coeus.domain.Resource; - -/** - * Data factory for transforming SPARQL data into RDF items using generic - * Triplify. - * - * @author pedrolopes - */ -public class PluginFactory implements ResourceFactory { - - private Resource res; - - public Resource getRes() { - return res; - } - - public void setRes(Resource res) { - this.res = res; - } - - public PluginFactory(Resource r) { - this.res = r; - } - - /** - * Reads SPARQL data according to Resource information. - *

    Workflow

      - *
    1. Check if resource is starter/extends
    2. - *
    3. Load SPARQL resource into ResultSet
    4. - *
    5. Start Triplify with factory Resource
    6. - *
    7. Get data for Item key into Triplify
    8. - *
    9. Load data for each InheritedResource property into Triplify hashmap - * based on SPARQL elements
    10. - *
    11. Itemize single item
    12. - *

    - */ - public void read() { - String[] divide = res.getEndpoint().split("://"); - String type = divide[0]; - try { - if (type.equals("omim")) { - OMIMPlugin omim = new OMIMPlugin(res); - omim.itemize(); - } - } catch (Exception ex) { - if (Config.isDebug()) { - System.out.println("[COEUS][SPARQLFactory] unable to load data for " + res.getUri()); - Logger.getLogger(PluginFactory.class.getName()).log(Level.SEVERE, null, ex); - } - } - } - - /** - * Updates the resource coeus:built property once the resource finished - * building. - * - * @return success of the operation - */ - public boolean save() { - boolean success = false; - try { - API api = Boot.getAPI(); - com.hp.hpl.jena.rdf.model.Resource resource = api.getResource(this.res.getUri()); - api.addStatement(resource, Predicate.get("coeus:built"), true); - success = true; - if (Config.isDebug()) { - System.out.println("[COEUS][API] Saved resource " + res.getUri()); - } - } catch (Exception ex) { - if (Config.isDebug()) { - System.out.println("[COEUS][API] Unable to save resource " + res.getUri()); - Logger.getLogger(PluginFactory.class.getName()).log(Level.SEVERE, null, ex); - } - } - return success; - } -} diff --git a/src/main/java/pt/ua/bioinformatics/coeus/data/connect/RDFFactory.java b/src/main/java/pt/ua/bioinformatics/coeus/data/connect/RDFFactory.java index fb55b8c..c1e6ab2 100644 --- a/src/main/java/pt/ua/bioinformatics/coeus/data/connect/RDFFactory.java +++ b/src/main/java/pt/ua/bioinformatics/coeus/data/connect/RDFFactory.java @@ -8,6 +8,7 @@ import com.hp.hpl.jena.ontology.OntModel; import com.hp.hpl.jena.rdf.model.Model; import com.hp.hpl.jena.rdf.model.ModelFactory; +import com.hp.hpl.jena.rdf.model.Statement; import com.hp.hpl.jena.util.iterator.ExtendedIterator; import java.net.URL; import java.net.URLConnection; @@ -158,6 +159,8 @@ public boolean save() { boolean success = false; try { com.hp.hpl.jena.rdf.model.Resource resource = api.getResource(this.res.getUri()); + Statement statementToRemove=api.getModel().createLiteralStatement(resource, Predicate.get("coeus:built"), false); + api.removeStatement(statementToRemove); api.addStatement(resource, Predicate.get("coeus:built"), true); success = true; if (Config.isDebug()) { diff --git a/src/main/java/pt/ua/bioinformatics/coeus/data/connect/SPARQLFactory.java b/src/main/java/pt/ua/bioinformatics/coeus/data/connect/SPARQLFactory.java index 4b814ae..d178ab2 100755 --- a/src/main/java/pt/ua/bioinformatics/coeus/data/connect/SPARQLFactory.java +++ b/src/main/java/pt/ua/bioinformatics/coeus/data/connect/SPARQLFactory.java @@ -6,6 +6,7 @@ import com.hp.hpl.jena.query.QuerySolution; import com.hp.hpl.jena.query.ResultSet; import com.hp.hpl.jena.query.Syntax; +import com.hp.hpl.jena.rdf.model.Statement; import java.util.ArrayList; import java.util.HashMap; import java.util.logging.Level; @@ -159,6 +160,8 @@ public boolean save() { try { API api = Boot.getAPI(); com.hp.hpl.jena.rdf.model.Resource resource = api.getResource(this.res.getUri()); + Statement statementToRemove=api.getModel().createLiteralStatement(resource, Predicate.get("coeus:built"), false); + api.removeStatement(statementToRemove); api.addStatement(resource, Predicate.get("coeus:built"), true); success = true; if (Config.isDebug()) { diff --git a/src/main/java/pt/ua/bioinformatics/coeus/data/connect/SQLFactory.java b/src/main/java/pt/ua/bioinformatics/coeus/data/connect/SQLFactory.java index 3cbb8fa..6450b48 100755 --- a/src/main/java/pt/ua/bioinformatics/coeus/data/connect/SQLFactory.java +++ b/src/main/java/pt/ua/bioinformatics/coeus/data/connect/SQLFactory.java @@ -1,5 +1,6 @@ package pt.ua.bioinformatics.coeus.data.connect; +import com.hp.hpl.jena.rdf.model.Statement; import java.sql.ResultSet; import java.util.ArrayList; import java.util.HashMap; @@ -212,6 +213,8 @@ public boolean save() { try { API api = Boot.getAPI(); com.hp.hpl.jena.rdf.model.Resource resource = api.getResource(this.res.getUri()); + Statement statementToRemove=api.getModel().createLiteralStatement(resource, Predicate.get("coeus:built"), false); + api.removeStatement(statementToRemove); api.addStatement(resource, Predicate.get("coeus:built"), true); success = true; if (Config.isDebug()) { diff --git a/src/main/java/pt/ua/bioinformatics/coeus/data/connect/XMLFactory.java b/src/main/java/pt/ua/bioinformatics/coeus/data/connect/XMLFactory.java index ac18057..918921e 100755 --- a/src/main/java/pt/ua/bioinformatics/coeus/data/connect/XMLFactory.java +++ b/src/main/java/pt/ua/bioinformatics/coeus/data/connect/XMLFactory.java @@ -1,5 +1,6 @@ package pt.ua.bioinformatics.coeus.data.connect; +import com.hp.hpl.jena.rdf.model.Statement; import java.net.URL; import java.net.URLEncoder; import java.util.HashMap; @@ -277,6 +278,8 @@ public boolean save() { try { API api = Boot.getAPI(); com.hp.hpl.jena.rdf.model.Resource resource = api.getResource(this.res.getUri()); + Statement statementToRemove=api.getModel().createLiteralStatement(resource, Predicate.get("coeus:built"), false); + api.removeStatement(statementToRemove); api.addStatement(resource, Predicate.get("coeus:built"), true); success = true; if (Config.isDebug()) { diff --git a/src/main/java/pt/ua/bioinformatics/coeus/ext/COEUSActionBeanContext.java b/src/main/java/pt/ua/bioinformatics/coeus/ext/COEUSActionBeanContext.java deleted file mode 100755 index 9ba40d1..0000000 --- a/src/main/java/pt/ua/bioinformatics/coeus/ext/COEUSActionBeanContext.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package pt.ua.bioinformatics.coeus.ext; - -import java.util.ArrayList; -import net.sourceforge.stripes.action.ActionBeanContext; -import pt.ua.bioinformatics.diseasecard.domain.Disease; - -/** - * Context Extender for COEUS Default Actions. - *

    Enables the creation of custom context actions in ActionBeans, check - * Stripes Docs for further information.

    - * - * @author pedrolopes - */ -public class COEUSActionBeanContext extends ActionBeanContext { - - private static final String DISEASE = "disease"; - - public void setDisease(String key, Object value) { - getRequest().getSession().setAttribute(key, value); - } - - public void setDisease(Object value) { - getRequest().getSession().setAttribute(DISEASE, value); - } - - public T getDisease() { - return (T) getRequest().getSession().getAttribute(DISEASE); - } - - public T getDisease(String key) { - return (T) getRequest().getSession().getAttribute(key); - } - - public T getDiseases() { - return (T) getRequest().getSession().getAttribute(DISEASE); - } - - public T getDiseases(String key) { - return (T) getRequest().getSession().getAttribute(key); - } - - public void setSearchResults(String key, ArrayList value) { - getRequest().getSession().setAttribute(key, value); - } - - public ArrayList getSearchResults(String key) { - return (ArrayList) getRequest().getSession().getAttribute(key); - } - - public void setCurrent(String key, Object value) { - getRequest().getSession().setAttribute(key, value); - } - - @SuppressWarnings("unchecked") - public T getCurrent(String key) { - return (T) getRequest().getSession().getAttribute(key); - } -} diff --git a/src/main/java/pt/ua/bioinformatics/diseasecard/domain/Disease.java b/src/main/java/pt/ua/bioinformatics/diseasecard/domain/Disease.java deleted file mode 100755 index 4045d22..0000000 --- a/src/main/java/pt/ua/bioinformatics/diseasecard/domain/Disease.java +++ /dev/null @@ -1,122 +0,0 @@ -package pt.ua.bioinformatics.diseasecard.domain; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.logging.Level; -import java.util.logging.Logger; -import pt.ua.bioinformatics.coeus.domain.Item; - -/** - * - * @author pedrolopes - */ -public class Disease { - - private int id; - private String name; - private String omimId; - private String location; - private ArrayList genes = new ArrayList(); - private ArrayList names = new ArrayList(); - private ArrayList genotypes = new ArrayList(); - private ArrayList phenotypes = new ArrayList(); - - public ArrayList getGenes() { - return genes; - } - - public String getOmimId() { - return omimId; - } - - public void setOmimId(String omim_id) { - this.omimId = omim_id; - } - - public void setGenes(ArrayList genes) { - this.genes = genes; - } - - public String getLocation() { - return location; - } - - public void setLocation(String location) { - this.location = location; - } - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public ArrayList getPhenotypes() { - return phenotypes; - } - - public void setPhenotypes(ArrayList phenotypes) { - this.phenotypes = phenotypes; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public ArrayList getNames() { - return names; - } - - public void setNames(ArrayList names) { - this.names = names; - } - - /** - * Loads Disease information from SDB based on its key - OMIM code. - * - * @param key - */ - public Disease(int key) { - this.id = key; - this.omimId = String.valueOf(key); - // this.omim = String.valueOf(key); - try { - } catch (Exception ex) { - Logger.getLogger(Item.class.getName()).log(Level.SEVERE, null, ex); - } - } - - public Disease(String name, String omim) { - this.name = name; - this.genotypes = new ArrayList(); - this.phenotypes = new ArrayList(); - this.names = new ArrayList(); - } - - public ArrayList getGenotypes() { - return genotypes; - } - - public void setGenotypes(ArrayList genotypes) { - this.genotypes = genotypes; - } - - @Override - public String toString() { - String response = ""; - - response += this.omimId + "\t" + this.name; - for (Disease s : genotypes) { - response += "\n\t" + s.getName() + " > " + s.getOmimId(); - } - response += "\n\tGenes"; - - return response; - } -} diff --git a/src/main/resources/coeus.sql b/src/main/resources/coeus.sql new file mode 100644 index 0000000..a9f2847 --- /dev/null +++ b/src/main/resources/coeus.sql @@ -0,0 +1,83 @@ +# ************************************************************ +# COEUS +# Semantic Web Application Framework +# +# Default triplestore database schema +# ************************************************************ + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +CREATE DATABASE IF NOT EXISTS coeusdb; +USE coeusdb; + +# Dump of table Nodes +# ------------------------------------------------------------ + +CREATE TABLE IF NOT EXISTS `Nodes` ( + `hash` bigint(20) NOT NULL DEFAULT '0', + `lex` longtext CHARACTER SET utf8 COLLATE utf8_bin, + `lang` varchar(10) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `datatype` varchar(200) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', + `type` int(10) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`hash`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + + + +# Dump of table Prefixes +# ------------------------------------------------------------ + +CREATE TABLE IF NOT EXISTS `Prefixes` ( + `prefix` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, + `uri` varchar(500) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, + PRIMARY KEY (`prefix`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + + + +# Dump of table quads +# ------------------------------------------------------------ + +CREATE TABLE IF NOT EXISTS `quads` ( + `g` bigint(20) NOT NULL, + `s` bigint(20) NOT NULL, + `p` bigint(20) NOT NULL, + `o` bigint(20) NOT NULL, + PRIMARY KEY (`g`,`s`,`p`,`o`), + KEY `SubjPredObj` (`s`,`p`,`o`), + KEY `PredObjSubj` (`p`,`o`,`s`), + KEY `ObjSubjPred` (`o`,`s`,`p`), + KEY `GraPredObj` (`g`,`p`,`o`), + KEY `GraObjSubj` (`g`,`o`,`s`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + + + +# Dump of table triples +# ------------------------------------------------------------ + +CREATE TABLE IF NOT EXISTS `Triples` ( + `s` bigint(20) NOT NULL, + `p` bigint(20) NOT NULL, + `o` bigint(20) NOT NULL, + PRIMARY KEY (`s`,`p`,`o`), + KEY `ObjSubj` (`o`,`s`), + KEY `PredObj` (`p`,`o`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + + + + +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/src/main/resources/config.js b/src/main/resources/config.js index d30bdd9..6192672 100644 --- a/src/main/resources/config.js +++ b/src/main/resources/config.js @@ -1,19 +1,20 @@ { "config": { -"name": "tester", - "description": "COEUS tester", + "name": "Model Test", + "description": "COEUS Model Test", "keyprefix":"coeus", "version": "1.0a", - "ontology": "http://bioinformatics.ua.pt/diseasecard/diseasecard.owl", - "setup": "tester/setup.rdf", - "sdb":"tester/sdb.ttl", - "predicates":"tester/predicates.csv", + "ontology": "http://bioinformatics.ua.pt/coeus/ontology/", + "setup": "setup.rdf", + "sdb":"sdb.ttl", + "predicates":"predicates.csv", "built": false, "debug": true, "apikey":"coeus|uavr", - "environment": "production" + "environment":"default", + "wizard":false }, - "prefixes" : { +"prefixes" : { "coeus": "http://bioinformatics.ua.pt/coeus/resource/", "owl2xml":"http://www.w3.org/2006/12/owl2-xml#", "xsd": "http://www.w3.org/2001/XMLSchema#", diff --git a/src/main/resources/env_default/joseki.ttl b/src/main/resources/env_default/joseki.ttl new file mode 100644 index 0000000..19b8e38 --- /dev/null +++ b/src/main/resources/env_default/joseki.ttl @@ -0,0 +1,97 @@ +@prefix rdfs: . +@prefix rdf: . +@prefix xsd: . +@prefix coeus: . +@prefix module: . +@prefix joseki: . +@prefix ja: . +@prefix sdb: . + +<> rdfs:label "Joseki Configuration File - SDB example" . +# Stripped down to support one service that exposes an +# SDB store as a SPARQL endpoint for query and one for +# one of the graphs in an SDB store. + +[] rdf:type joseki:Server . + +## -------------------------------------------------------------- +## Services + +# Service publishes the whole of the SDB store - this is the usual way to use SDB. +<#service1> + rdf:type joseki:Service ; + rdfs:label "SPARQL-SDB" ; + joseki:serviceRef "sparql" ; # web.xml must route this name to Joseki + joseki:dataset <#sdb> ; + joseki:processor joseki:ProcessorSPARQL_FixedDS ; + . + + +## -------------------------------------------------------------- +## Datasets + +## See also SDB documentation -- http://jena.hpl.hp.com/wiki/SDB +## Special declarations to cause SDB to be used. + +## Initialize SDB. +## Tell the system that sdb:DatasetStore is an implementation of ja:RDFDataset . +## Tell the system that sdb:Model is an implementation of ja:RDFDataset . + +[] ja:loadClass "com.hp.hpl.jena.sdb.SDB" . +sdb:DatasetStore rdfs:subClassOf ja:RDFDataset . +sdb:Model rdfs:subClassOf ja:Model . + +<#sdb> rdf:type sdb:DatasetStore ; + ## Number of concurrent connections allowed to this dataset. + joseki:poolSize 2; + sdb:store <#store> . + +<#store> rdf:type sdb:Store ; + rdfs:label "SDB" ; + sdb:layout "layout2" ; + sdb:connection + [ rdf:type sdb:SDBConnection ; + sdb:sdbType "mysql" ; + #sdb:sdbHost "localhost:3306" ; + #sdb:sdbName "coeus" ; + sdb:jdbcURL "$sdb:jdbcURL" ; + sdb:sdbUser "$sdb:sdbUser" ; + sdb:sdbPassword "$sdb:sdbPassword" ; + ] + . + +# Pick one graph out of the SDB store. +# Do not assemble the whole of the store this way - it is less efficient for that. +<#sdb-part> rdf:type ja:RDFDataset ; + # If ja:namedGraph is used here, there is no correspondence + # with the name in the SDB store. + ja:defaultGraph <#sdb-one-graph> ; + . + +<#sdb-one-graph> a sdb:Model ; + sdb:dataset <#sdb> ; + # Uncomment to pick out a named graph from the store. + # If no "sdb:namedGraph" appearsm the store's default graph is used. + # is used as default graph of the dataset publically visible. + #sdb:graphName ; + # Or even the merge of all named graphs + #sdb:graphName ; + . + +## -------------------------------------------------------------- +## Processors + +joseki:ProcessorSPARQL_FixedDS + rdfs:label "SPARQL processor for fixed datasets" ; + rdf:type joseki:Processor ; + module:implementation + [ rdf:type joseki:ServiceImpl ; + module:className + ] ; + + # This processor does not accept queries with FROM/FROM NAMED + joseki:allowExplicitDataset "false"^^xsd:boolean ; + joseki:allowWebLoading "false"^^xsd:boolean ; + # The database is safe for MRSW (multiple-reader, single-writer). + joseki:lockingPolicy joseki:lockingPolicyMRSW ; + . \ No newline at end of file diff --git a/src/main/resources/env_default/map.js b/src/main/resources/env_default/map.js new file mode 100644 index 0000000..681d03d --- /dev/null +++ b/src/main/resources/env_default/map.js @@ -0,0 +1,13 @@ +{ + "$sdb:jdbcURL" : "jdbc:mysql://localhost:3306/coeus?autoReconnect=true", + "$sdb:sdbUser" : "demo", + "$sdb:sdbPassword" :"demo", + + "$conf:projectName" :"coeus.demo", + "$conf:projectHomepage" :"http://bioinformatics.ua.pt/coeus/", + "$conf:webBase" :"http://localhost:8080/coeus/", + "$conf:sparqlEndpoint" :"http://localhost:8080/coeus/sparql", + "$conf:datasetBase" :"http://bioinformatics.ua.pt/coeus/resource/", + "$conf:webResourcePrefix" :"resource/", + +} \ No newline at end of file diff --git a/src/main/resources/pubby_localhost.ttl b/src/main/resources/env_default/pubby.ttl similarity index 92% rename from src/main/resources/pubby_localhost.ttl rename to src/main/resources/env_default/pubby.ttl index c64fa6d..1a5d679 100644 --- a/src/main/resources/pubby_localhost.ttl +++ b/src/main/resources/env_default/pubby.ttl @@ -40,11 +40,11 @@ # Server configuration section <> a conf:Configuration; # Project name for display in page titles - conf:projectName "coeus.demo"; + conf:projectName "$conf:projectName"; # Homepage with description of the project for the link in the page header - conf:projectHomepage ; + conf:projectHomepage <$conf:projectHomepage>; # The Pubby root, where the webapp is running inside the servlet container. - conf:webBase ; + conf:webBase <$conf:webBase>; # URL of an RDF file whose prefix mapping is to be used by the # server; defaults to <>, which is *this* file. conf:usePrefixesFrom <>; @@ -61,15 +61,15 @@ # URIs on the Web: http://localhost:8080/resource/* conf:dataset [ # SPARQL endpoint URL of the dataset - conf:sparqlEndpoint ; + conf:sparqlEndpoint <$conf:sparqlEndpoint>; #conf:sparqlEndpoint ; # Default graph name to query (not necessary for most endpoints) # conf:sparqlDefaultGraph <>; # Common URI prefix of all resource URIs in the SPARQL dataset - conf:datasetBase ; + conf:datasetBase <$conf:datasetBase>; # Will be appended to the conf:webBase to form the public # resource URIs; if not present, defaults to "" - conf:webResourcePrefix "resource/"; + conf:webResourcePrefix "$conf:webResourcePrefix"; # Fixes an issue with the server running behind an Apache proxy; # can be ignored otherwise conf:fixUnescapedCharacters "(),'!$&*+;=@"; diff --git a/src/main/resources/env_default/sdb.ttl b/src/main/resources/env_default/sdb.ttl new file mode 100644 index 0000000..ac180fd --- /dev/null +++ b/src/main/resources/env_default/sdb.ttl @@ -0,0 +1,19 @@ +@prefix sdb: . +@prefix rdfs: . +@prefix rdf: . +@prefix ja: . +@prefix coeus: . + +<#store> rdf:type sdb:Store ; + sdb:layout "layout2" ; + sdb:connection <#conn> ; + sdb:engine "InnoDB" ; +. + +<#conn> rdf:type sdb:SDBConnection ; + sdb:sdbType "MySQL" ; + sdb:jdbcURL "$sdb:jdbcURL" ; + sdb:sdbUser "$sdb:sdbUser" ; + sdb:sdbPassword "$sdb:sdbPassword" ; + sdb:driver "com.mysql.jdbc.Driver" ; + . \ No newline at end of file diff --git a/src/main/resources/init/joseki.ttl b/src/main/resources/init/joseki.ttl new file mode 100644 index 0000000..19b8e38 --- /dev/null +++ b/src/main/resources/init/joseki.ttl @@ -0,0 +1,97 @@ +@prefix rdfs: . +@prefix rdf: . +@prefix xsd: . +@prefix coeus: . +@prefix module: . +@prefix joseki: . +@prefix ja: . +@prefix sdb: . + +<> rdfs:label "Joseki Configuration File - SDB example" . +# Stripped down to support one service that exposes an +# SDB store as a SPARQL endpoint for query and one for +# one of the graphs in an SDB store. + +[] rdf:type joseki:Server . + +## -------------------------------------------------------------- +## Services + +# Service publishes the whole of the SDB store - this is the usual way to use SDB. +<#service1> + rdf:type joseki:Service ; + rdfs:label "SPARQL-SDB" ; + joseki:serviceRef "sparql" ; # web.xml must route this name to Joseki + joseki:dataset <#sdb> ; + joseki:processor joseki:ProcessorSPARQL_FixedDS ; + . + + +## -------------------------------------------------------------- +## Datasets + +## See also SDB documentation -- http://jena.hpl.hp.com/wiki/SDB +## Special declarations to cause SDB to be used. + +## Initialize SDB. +## Tell the system that sdb:DatasetStore is an implementation of ja:RDFDataset . +## Tell the system that sdb:Model is an implementation of ja:RDFDataset . + +[] ja:loadClass "com.hp.hpl.jena.sdb.SDB" . +sdb:DatasetStore rdfs:subClassOf ja:RDFDataset . +sdb:Model rdfs:subClassOf ja:Model . + +<#sdb> rdf:type sdb:DatasetStore ; + ## Number of concurrent connections allowed to this dataset. + joseki:poolSize 2; + sdb:store <#store> . + +<#store> rdf:type sdb:Store ; + rdfs:label "SDB" ; + sdb:layout "layout2" ; + sdb:connection + [ rdf:type sdb:SDBConnection ; + sdb:sdbType "mysql" ; + #sdb:sdbHost "localhost:3306" ; + #sdb:sdbName "coeus" ; + sdb:jdbcURL "$sdb:jdbcURL" ; + sdb:sdbUser "$sdb:sdbUser" ; + sdb:sdbPassword "$sdb:sdbPassword" ; + ] + . + +# Pick one graph out of the SDB store. +# Do not assemble the whole of the store this way - it is less efficient for that. +<#sdb-part> rdf:type ja:RDFDataset ; + # If ja:namedGraph is used here, there is no correspondence + # with the name in the SDB store. + ja:defaultGraph <#sdb-one-graph> ; + . + +<#sdb-one-graph> a sdb:Model ; + sdb:dataset <#sdb> ; + # Uncomment to pick out a named graph from the store. + # If no "sdb:namedGraph" appearsm the store's default graph is used. + # is used as default graph of the dataset publically visible. + #sdb:graphName ; + # Or even the merge of all named graphs + #sdb:graphName ; + . + +## -------------------------------------------------------------- +## Processors + +joseki:ProcessorSPARQL_FixedDS + rdfs:label "SPARQL processor for fixed datasets" ; + rdf:type joseki:Processor ; + module:implementation + [ rdf:type joseki:ServiceImpl ; + module:className + ] ; + + # This processor does not accept queries with FROM/FROM NAMED + joseki:allowExplicitDataset "false"^^xsd:boolean ; + joseki:allowWebLoading "false"^^xsd:boolean ; + # The database is safe for MRSW (multiple-reader, single-writer). + joseki:lockingPolicy joseki:lockingPolicyMRSW ; + . \ No newline at end of file diff --git a/src/main/resources/init/map.js b/src/main/resources/init/map.js new file mode 100644 index 0000000..681d03d --- /dev/null +++ b/src/main/resources/init/map.js @@ -0,0 +1,13 @@ +{ + "$sdb:jdbcURL" : "jdbc:mysql://localhost:3306/coeus?autoReconnect=true", + "$sdb:sdbUser" : "demo", + "$sdb:sdbPassword" :"demo", + + "$conf:projectName" :"coeus.demo", + "$conf:projectHomepage" :"http://bioinformatics.ua.pt/coeus/", + "$conf:webBase" :"http://localhost:8080/coeus/", + "$conf:sparqlEndpoint" :"http://localhost:8080/coeus/sparql", + "$conf:datasetBase" :"http://bioinformatics.ua.pt/coeus/resource/", + "$conf:webResourcePrefix" :"resource/", + +} \ No newline at end of file diff --git a/src/main/resources/pubby_production.ttl b/src/main/resources/init/pubby.ttl similarity index 90% rename from src/main/resources/pubby_production.ttl rename to src/main/resources/init/pubby.ttl index 2d649be..1a5d679 100644 --- a/src/main/resources/pubby_production.ttl +++ b/src/main/resources/init/pubby.ttl @@ -40,11 +40,11 @@ # Server configuration section <> a conf:Configuration; # Project name for display in page titles - conf:projectName "coeus.demo"; + conf:projectName "$conf:projectName"; # Homepage with description of the project for the link in the page header - conf:projectHomepage ; + conf:projectHomepage <$conf:projectHomepage>; # The Pubby root, where the webapp is running inside the servlet container. - conf:webBase ; + conf:webBase <$conf:webBase>; # URL of an RDF file whose prefix mapping is to be used by the # server; defaults to <>, which is *this* file. conf:usePrefixesFrom <>; @@ -61,15 +61,15 @@ # URIs on the Web: http://localhost:8080/resource/* conf:dataset [ # SPARQL endpoint URL of the dataset - #conf:sparqlEndpoint ; - conf:sparqlEndpoint ; + conf:sparqlEndpoint <$conf:sparqlEndpoint>; + #conf:sparqlEndpoint ; # Default graph name to query (not necessary for most endpoints) # conf:sparqlDefaultGraph <>; # Common URI prefix of all resource URIs in the SPARQL dataset - conf:datasetBase ; + conf:datasetBase <$conf:datasetBase>; # Will be appended to the conf:webBase to form the public # resource URIs; if not present, defaults to "" - conf:webResourcePrefix "resource/"; + conf:webResourcePrefix "$conf:webResourcePrefix"; # Fixes an issue with the server running behind an Apache proxy; # can be ignored otherwise conf:fixUnescapedCharacters "(),'!$&*+;=@"; diff --git a/src/main/resources/init/sdb.ttl b/src/main/resources/init/sdb.ttl new file mode 100644 index 0000000..ac180fd --- /dev/null +++ b/src/main/resources/init/sdb.ttl @@ -0,0 +1,19 @@ +@prefix sdb: . +@prefix rdfs: . +@prefix rdf: . +@prefix ja: . +@prefix coeus: . + +<#store> rdf:type sdb:Store ; + sdb:layout "layout2" ; + sdb:connection <#conn> ; + sdb:engine "InnoDB" ; +. + +<#conn> rdf:type sdb:SDBConnection ; + sdb:sdbType "MySQL" ; + sdb:jdbcURL "$sdb:jdbcURL" ; + sdb:sdbUser "$sdb:sdbUser" ; + sdb:sdbPassword "$sdb:sdbPassword" ; + sdb:driver "com.mysql.jdbc.Driver" ; + . \ No newline at end of file diff --git a/src/main/resources/joseki.ttl b/src/main/resources/joseki.ttl index 8f1b04f..c40d69c 100644 --- a/src/main/resources/joseki.ttl +++ b/src/main/resources/joseki.ttl @@ -43,7 +43,7 @@ sdb:Model rdfs:subClassOf ja:Model . <#sdb> rdf:type sdb:DatasetStore ; ## Number of concurrent connections allowed to this dataset. - joseki:poolSize 200; + joseki:poolSize 2; sdb:store <#store> . <#store> rdf:type sdb:Store ; diff --git a/src/main/resources/newsaggregator/predicates.csv b/src/main/resources/newsaggregator/predicates.csv index 6b0b8fd..1c8c267 100644 --- a/src/main/resources/newsaggregator/predicates.csv +++ b/src/main/resources/newsaggregator/predicates.csv @@ -75,4 +75,5 @@ http://bioinformatics.ua.pt/coeus/resource/enabled http://bioinformatics.ua.pt/coeus/resource/isConnectedTo http://bioinformatics.ua.pt/coeus/resource/loadsFrom http://bioinformatics.ua.pt/coeus/resource/hasBridge -http://bioinformatics.ua.pt/coeus/resource/hasConcept \ No newline at end of file +http://bioinformatics.ua.pt/coeus/resource/hasConcept +http://bioinformatics.ua.pt/coeus/resource/regex \ No newline at end of file diff --git a/src/main/resources/newsaggregator/setup.rdf b/src/main/resources/newsaggregator/setup.rdf index 2a085c2..6b8899f 100644 --- a/src/main/resources/newsaggregator/setup.rdf +++ b/src/main/resources/newsaggregator/setup.rdf @@ -971,333 +971,235 @@ - - - - - - concept_abola - A Bola - - - + + + News Aggregator + Seed News + + News Aggregator - - - - - + + + News + Entity News + + + + + + News + + + + - concept_bbc - BBC + Reuters + - - + Reuters - - - - concept_marca - Marca - + + Marca + + Marca - - - - - + + - concept_reuters - Reuters + Abola + - - + Abola - - - - - - - entity_news - News - News entity for coeus.NA - + + + + BBC + + + BBC - - - - - + + + + + + + + - resource_abola - //item - 1 - BBC - Resource loader for A Bola XML feeds. - cache - http://www.abola.pt/rss/index.aspx - xml - - - - - - - - + Abola + Resource loader for A Bola XML feeds. + + 1 + cache + http://www.abola.pt/rss/index.aspx + + //item + xml + Abola - - - - - + + + + + + + - resource_bbc - //item - 1 - BBC - Resource loader for BBC XML feeds. - cache - http://feeds.bbci.co.uk/sport/0/rss.xml - xml - - - - - - - - + Reuters + Resource loader for Reuters XML feeds. + + 4 + cache + http://feeds.reuters.com/reuters/sportsNews + + //item + xml + Reuters - - - - + + + + + + - resource_marca - //item - 1 - Marca - Resource loader for Marca XML feeds. - cache - http://estaticos.marca.com/rss/portada.xml - xml - + Marca + Resource loader for Marca XML feeds. - - - - - - + 2 + cache + http://estaticos.marca.com/rss/portada.xml + + //item + xml + Marca - - - - - + + + + + + + - resource_reuters - //item - 1 - Resource loader for Reuters XML feeds. - Reuters - cache - http://feeds.reuters.com/reuters/sportsNews - xml - - - - - - - - - - - - - - - - - seed_coeusna - coeus.NA - + BBC + Resource loader for BBC XML feeds. + + 3 + cache + http://feeds.bbci.co.uk/sport/0/rss.xml + + //item + xml + BBC - - - - - + - xml_abola_id - A Bola identifier - [0-9]{5,} - dc:identifier - guid - - + xml_link + + + + + dc:publisher + link + xml_link - - - - - + - xml_abola_title - A Bola entry title - dc:title - title - + xml_Reuters_id + + dc:identifier + guid + + xml_Reuters_id + [0-9]{5,} - - - - - + - xml_bbc_id - BBC identifier - [0-9]{5,} - dc:identifier - guid + xml_BBC_id + dc:identifier + guid + xml_BBC_id + [0-9]{5,} - - - - - + - xml_bbc_title - BBC entry title - dc:title - title + xml_description + + + + dc:description + description + xml_description - - - - - + - xml_marca_id - Marca identifier - [0-9]{5,} - dc:identifier - guid - + xml_date + + + + dc:date + pubDate + xml_date - - - - - + - xml_marca_title - Marca entry title - dc:title - title + xml_Marca_id + dc:identifier + guid + + xml_Marca_id + [0-9]{5,} - - - - - + - xml_reuters_id - Reuters identifier - [0-9]{5,} - dc:identifier - guid + xml_title - - - - - - - - - - xml_reuters__title - Reuters entry title - dc:title - title - - - - - - - - - xml_date - dc:date - pubDate - entry date - - - + + dc:title + title + xml_title - - - - - + - xml_description - dc:description - description - entry description - - - - + xml_Abola_id + + dc:identifier + guid + + xml_Abola_id + [0-9]{5,} - - - - - - - xml_link - dc:publisher - link - entry link - - - - - diff --git a/src/main/resources/predicates.csv b/src/main/resources/predicates.csv new file mode 100644 index 0000000..3481f70 --- /dev/null +++ b/src/main/resources/predicates.csv @@ -0,0 +1,120 @@ +http://bioinformatics.ua.pt/coeus/resource/built +http://bioinformatics.ua.pt/coeus/resource/database +http://bioinformatics.ua.pt/coeus/resource/enabled +http://bioinformatics.ua.pt/coeus/resource/endpoint +http://bioinformatics.ua.pt/coeus/resource/extends +http://bioinformatics.ua.pt/coeus/resource/extension +http://bioinformatics.ua.pt/coeus/resource/hasBridge +http://bioinformatics.ua.pt/coeus/resource/hasConcept +http://bioinformatics.ua.pt/coeus/resource/hasEntity +http://bioinformatics.ua.pt/coeus/resource/hasKey +http://bioinformatics.ua.pt/coeus/resource/hasModule +http://bioinformatics.ua.pt/coeus/resource/hasResource +http://bioinformatics.ua.pt/coeus/resource/host +http://bioinformatics.ua.pt/coeus/resource/includes +http://bioinformatics.ua.pt/coeus/resource/isAssociatedTo +http://bioinformatics.ua.pt/coeus/resource/isBridgedTo +http://bioinformatics.ua.pt/coeus/resource/isConceptOf +http://bioinformatics.ua.pt/coeus/resource/isConnectedTo +http://bioinformatics.ua.pt/coeus/resource/isEntityOf +http://bioinformatics.ua.pt/coeus/resource/isExtendedBy +http://bioinformatics.ua.pt/coeus/resource/isIncludedIn +http://bioinformatics.ua.pt/coeus/resource/isKeyOf +http://bioinformatics.ua.pt/coeus/resource/isModuleOf +http://bioinformatics.ua.pt/coeus/resource/isResourceOf +http://bioinformatics.ua.pt/coeus/resource/line +http://bioinformatics.ua.pt/coeus/resource/loadsFor +http://bioinformatics.ua.pt/coeus/resource/loadsFrom +http://bioinformatics.ua.pt/coeus/resource/mappedFrom +http://bioinformatics.ua.pt/coeus/resource/mapsTo +http://bioinformatics.ua.pt/coeus/resource/method +http://bioinformatics.ua.pt/coeus/resource/order +http://bioinformatics.ua.pt/coeus/resource/plugin +http://bioinformatics.ua.pt/coeus/resource/property +http://bioinformatics.ua.pt/coeus/resource/public +http://bioinformatics.ua.pt/coeus/resource/query +http://bioinformatics.ua.pt/coeus/resource/regex +http://bioinformatics.ua.pt/coeus/resource/replace +http://bioinformatics.ua.pt/coeus/resource/select +http://purl.org/dc/elements/1.1/contributor +http://purl.org/dc/elements/1.1/coverage +http://purl.org/dc/elements/1.1/creator +http://purl.org/dc/elements/1.1/date +http://purl.org/dc/elements/1.1/description +http://purl.org/dc/elements/1.1/format +http://purl.org/dc/elements/1.1/identifier +http://purl.org/dc/elements/1.1/language +http://purl.org/dc/elements/1.1/publisher +http://purl.org/dc/elements/1.1/relation +http://purl.org/dc/elements/1.1/rights +http://purl.org/dc/elements/1.1/source +http://purl.org/dc/elements/1.1/subject +http://purl.org/dc/elements/1.1/title +http://purl.org/dc/elements/1.1/type +http://www.w3.org/1999/02/22-rdf-syntax-ns#first +http://www.w3.org/1999/02/22-rdf-syntax-ns#object +http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate +http://www.w3.org/1999/02/22-rdf-syntax-ns#rest +http://www.w3.org/1999/02/22-rdf-syntax-ns#subject +http://www.w3.org/1999/02/22-rdf-syntax-ns#type +http://www.w3.org/1999/02/22-rdf-syntax-ns#value +http://www.w3.org/2000/01/rdf-schema#comment +http://www.w3.org/2000/01/rdf-schema#domain +http://www.w3.org/2000/01/rdf-schema#isDefinedBy +http://www.w3.org/2000/01/rdf-schema#label +http://www.w3.org/2000/01/rdf-schema#member +http://www.w3.org/2000/01/rdf-schema#range +http://www.w3.org/2000/01/rdf-schema#seeAlso +http://www.w3.org/2000/01/rdf-schema#subClassOf +http://www.w3.org/2000/01/rdf-schema#subPropertyOf +http://www.w3.org/2002/07/owl#allValuesFrom +http://www.w3.org/2002/07/owl#annotatedProperty +http://www.w3.org/2002/07/owl#annotatedSource +http://www.w3.org/2002/07/owl#annotatedTarget +http://www.w3.org/2002/07/owl#assertionProperty +http://www.w3.org/2002/07/owl#backwardCompatibleWith +http://www.w3.org/2002/07/owl#bottomDataProperty +http://www.w3.org/2002/07/owl#bottomObjectProperty +http://www.w3.org/2002/07/owl#cardinality +http://www.w3.org/2002/07/owl#complementOf +http://www.w3.org/2002/07/owl#datatypeComplementOf +http://www.w3.org/2002/07/owl#deprecated +http://www.w3.org/2002/07/owl#differentFrom +http://www.w3.org/2002/07/owl#disjointUnionOf +http://www.w3.org/2002/07/owl#disjointWith +http://www.w3.org/2002/07/owl#distinctMembers +http://www.w3.org/2002/07/owl#equivalentClass +http://www.w3.org/2002/07/owl#equivalentProperty +http://www.w3.org/2002/07/owl#hasKey +http://www.w3.org/2002/07/owl#hasSelf +http://www.w3.org/2002/07/owl#hasValue +http://www.w3.org/2002/07/owl#imports +http://www.w3.org/2002/07/owl#incompatibleWith +http://www.w3.org/2002/07/owl#intersectionOf +http://www.w3.org/2002/07/owl#inverseOf +http://www.w3.org/2002/07/owl#maxCardinality +http://www.w3.org/2002/07/owl#maxQualifiedCardinality +http://www.w3.org/2002/07/owl#members +http://www.w3.org/2002/07/owl#minCardinality +http://www.w3.org/2002/07/owl#minQualifiedCardinality +http://www.w3.org/2002/07/owl#onClass +http://www.w3.org/2002/07/owl#onDataRange +http://www.w3.org/2002/07/owl#onDatatype +http://www.w3.org/2002/07/owl#onProperties +http://www.w3.org/2002/07/owl#onProperty +http://www.w3.org/2002/07/owl#oneOf +http://www.w3.org/2002/07/owl#priorVersion +http://www.w3.org/2002/07/owl#propertyChainAxiom +http://www.w3.org/2002/07/owl#propertyDisjointWith +http://www.w3.org/2002/07/owl#qualifiedCardinality +http://www.w3.org/2002/07/owl#sameAs +http://www.w3.org/2002/07/owl#someValuesFrom +http://www.w3.org/2002/07/owl#sourceIndividual +http://www.w3.org/2002/07/owl#targetIndividual +http://www.w3.org/2002/07/owl#targetValue +http://www.w3.org/2002/07/owl#topDataProperty +http://www.w3.org/2002/07/owl#topObjectProperty +http://www.w3.org/2002/07/owl#unionOf +http://www.w3.org/2002/07/owl#versionIRI +http://www.w3.org/2002/07/owl#versionInfo +http://www.w3.org/2002/07/owl#withRestrictions diff --git a/src/main/resources/proteinator/predicates.csv b/src/main/resources/proteinator/predicates.csv index 6b0b8fd..1c8c267 100644 --- a/src/main/resources/proteinator/predicates.csv +++ b/src/main/resources/proteinator/predicates.csv @@ -75,4 +75,5 @@ http://bioinformatics.ua.pt/coeus/resource/enabled http://bioinformatics.ua.pt/coeus/resource/isConnectedTo http://bioinformatics.ua.pt/coeus/resource/loadsFrom http://bioinformatics.ua.pt/coeus/resource/hasBridge -http://bioinformatics.ua.pt/coeus/resource/hasConcept \ No newline at end of file +http://bioinformatics.ua.pt/coeus/resource/hasConcept +http://bioinformatics.ua.pt/coeus/resource/regex \ No newline at end of file diff --git a/src/main/resources/sdb.ttl b/src/main/resources/sdb.ttl new file mode 100644 index 0000000..b8d5d4e --- /dev/null +++ b/src/main/resources/sdb.ttl @@ -0,0 +1,19 @@ +@prefix sdb: . +@prefix rdfs: . +@prefix rdf: . +@prefix ja: . +@prefix coeus: . + +<#store> rdf:type sdb:Store ; + sdb:layout "layout2" ; + sdb:connection <#conn> ; + sdb:engine "InnoDB" ; +. + +<#conn> rdf:type sdb:SDBConnection ; + sdb:sdbType "MySQL" ; + sdb:jdbcURL "jdbc:mysql://localhost:3306/coeus?autoReconnect=true" ; + sdb:sdbUser "demo" ; + sdb:sdbPassword "demo" ; + sdb:driver "com.mysql.jdbc.Driver" ; + . \ No newline at end of file diff --git a/src/main/resources/setup.rdf b/src/main/resources/setup.rdf new file mode 100644 index 0000000..5fdf2ff --- /dev/null +++ b/src/main/resources/setup.rdf @@ -0,0 +1,980 @@ + + + + + + + + + +]> + + + + + coeusna + 1.0b + 2013-03-15 + COEUS and COEUS Ontology are licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA. + Pedro Lopes pedrolopes@ua.pt + coeus.NA + coeus.NA + coeus.NA + en + http://bioinformatics.ua.pt + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + objectproperty_extends + 1.0a + 2011-01-20 + A Resource extends a Concept - items are source for data loading + A Resource extends a Concept - items are source for data loading + Pedro Lopes pedrolopes@ua.pt + extends + + + + + + + + + + objectproperty_hasbridge + 1.0a + 2011-01-19 + A Concept has a Bridge + A Concept has a Bridge + Pedro Lopes pedrolopes@ua.pt + hasBridge + + + + + + + + + + objectproperty_hasconcept + 1.0a + 2011-01-14 + Item individuals belong to Concept individuals + Item individuals belong to Concept individuals + Pedro Lopes pedrolopes@ua.pt + hasConcept + + + + + + + + + + objectproperty_hasentity + 1.0a + 2011-01-14 + Concept individuals has Entity individuals + Concept individuals has Entity individuals + Pedro Lopes pedrolopes@ua.pt + hasEntity + + + + + + + + + + objectproperty_haskey + 1.0a + 2011-01-27 + Defines the key for a given Resource + Defines the key for a given Resource + Pedro Lopes pedrolopes@ua.pt + hasKey + + + + + + + + + + + + + objectproperty_hasmodule + 1.0a + 2011-01-19 + A Seed has a Module + A Seed has a Module + Pedro Lopes pedrolopes@ua.pt + hasModule + + + + + + + + + + objectproperty_hasresource + 1.0a + 2011-01-19 + A Concept has a Resource + A Concept has a Resource + Pedro Lopes pedrolopes@ua.pt + hasResource + + + + + + + + + + objectproperty_includes + 1.0a + 2011-01-14 + Defines which Entity individuals are included in Seed individuals + Defines which Entity individuals are included in Seed individuals + Pedro Lopes pedrolopes@ua.pt + includes + + + + + + + + + + + + + objectproperty_isassociatedto + 1.0a + 2011-01-19 + Pedro Lopes pedrolopes@ua.pt + Relationship between two "Item" individuals + Relationship between two "Item" individuals + isAssociatedTo + + + + + + + + + + + iobjectproperty_sbridgedto + 1.0a + 2011-01-19 + A Briged is bridged to a Concept + A Briged is bridged to a Concept + Pedro Lopes pedrolopes@ua.pt + isBridgedTo + + + + + + + + + + + objectproperty_isconceptof + 1.0a + 2011-01-19 + A Concept has an Item + A Concept has an Item + Pedro Lopes pedrolopes@ua.pt + isConceptOf + + + + + + + + + + + + + objectproperty_isconnectedto + 1.0a + 2011-01-14 + Defines connection between two Concept individuals + Defines connection between two Concept individuals + Pedro Lopes pedrolopes@ua.pt + isConnectedTo + + + + + + + + + + + objectproperty_isentityof + 1.0a + 2011-01-19 + An Entity is of a Concept + An Entity is of a Concept + Pedro Lopes pedrolopes@ua.pt + isEntityOf + + + + + + + + + + + objectproperty_isextendedby + 1.0a + 2011-01-27 + A Resource extends a Concept - items are source for data loading + A Resource extends a Concept - items are source for data loading + Pedro Lopes pedrolopes@ua.pt + isExtendedBy + + + + + + + + + + + objectproperty_isincludedin + 1.0a + 2011-01-14 + Defines which Entity individuals are included in Seed individuals + Defines which Entity individuals are included in Seed individuals + Pedro Lopes pedrolopes@ua.pt + isIncludedIn + + + + + + + + + + objectproperty_iskeyof + 1.0a + 2011-01-27 + Defines the key for a given Resource + Defines the key for a given Resource + Pedro Lopes pedrolopes@ua.pt + isKeyOf + + + + + + + + + + + + + + objectproperty_ismoduleof + 1.0a + 2011-01-19 + A Module is of a Seed + A Module is of a Seed + Pedro Lopes pedrolopes@ua.pt + isModuleOf + + + + + + + + + + + objectproperty_isresourceof + 1.0a + 2011-01-19 + A Resource is of a Concept + A Resource is of a Concept + Pedro Lopes pedrolopes@ua.pt + isResourceOf + + + + + + + + + + + objectproperty_loadsfor + 1.0a + 2011-01-20 + A CSV,XML,SQL loads data for a Resource + A CSV,XML,SQL loads data for a Resource + Pedro Lopes pedrolopes@ua.pt + loadsFor + + + + + + + + + + + + + + objectproperty_loadsfrom + 1.0a + 2011-01-20 + A Resource loads data from a CSV, XML, SQL, SPARQL + A Resource loads data from a CSV, XML, SQL, SPARQL + Pedro Lopes pedrolopes@ua.pt + loadsFrom + + + + + + + + + + + + + objectproperty_mappedfrom + 1.0b + 2011-03-24 + Defines a mapping destination (Concept) for a given Resource + Defines a mapping destination (Concept) for a given Resource + Pedro Lopes pedrolopes@ua.pt + mappedFrom + + + + + + + + + + + objectproperty_mapsto + 1.0b + 2011-03-24 + Defines a mapping destination (Concept) for a given Resource + Defines a mapping destination (Concept) for a given Resource + Pedro Lopes pedrolopes@ua.pt + mapsTo + + + + + + + + + + + + + + + dataproperty_loaded + 1.0b + 2011-03-31 + Defines that a Seed, Entity, Concept is or is not built. + Defines that a Seed, Entity, Concept is or is not built. + Pedro Lopes pedrolopes@ua.pt + loaded + + + + + + + + + + + + + + + + + + + + dataproperty_database + 1.0b + 2011-03-24 + Database identifier for connectionn info in .js config file + Database identifier for connectionn info in .js config file + Pedro Lopes pedrolopes@ua.pt + database + + + + + + + + + + dataproperty_delimiter + 1.0a + 2011-01-19 + Column separator in CSV file + Column separator in CSV file + Pedro Lopes pedrolopes@ua.pt + delimiter + + + + + + + + + + dataproperty_enabled + 1.0a + 2011-01-14 + Defines if an individual is enabled or not + Defines if an individual is enabled or not + Pedro Lopes pedrolopes@ua.pt + enabled + + + + + + + + + dataproperty_endpoint + 1.0b + 2011-04-04 + Endpoint for a given Resource. + Endpoint for a given Resource. + Pedro Lopes pedrolopes@ua.pt + endpoint + + + + + + + + dataproperty_extension + 1.0b + 2011-03-24 + Defines the source for a Resource extension + Defines the source for a Resource extension + Pedro Lopes pedrolopes@ua.pt + extension + + + + + + + + + + dataproperty_host + 1.0a + 2011-01-14 + Defines a Seed individual host + Defines a Seed individual host + Pedro Lopes pedrolopes@ua.pt + host + + + + + + + + + + dataproperty_line + 1.0a + 2011-01-19 + Pedro Lopes pedrolopes@ua.pt + The line where the CSV reader will start + The line where the CSV reader will start + line + + + + + + + + + + dataproperty_method + 1.0a + 2011-01-19 + A Resource access method or Bridge method + A Resource access method or Bridge method + Pedro Lopes pedrolopes@ua.pt + method + + + + + + + + + + + dataproperty_order + 1.0a + 2011-02-21 + Defines resource load order, useful for data-dependencies. + Defines resource load order, useful for data-dependencies. + Pedro Lopes pedrolopes@ua.pt + order + + + + + + + + + + dataproperty_plugin + 1.0a + 2011-01-20 + Defines if a module is a plugin or not + Defines if a module is a plugin or not + Pedro Lopes pedrolopes@ua.pt + plugin + + + + + + + + + + dataproperty_property + 1.0a + 2011-01-19 + An Item predicate where Resource will be loaded into + An Item predicate where Resource will be loaded into + Pedro Lopes pedrolopes@ua.pt + property + + + + + + + + + + + + + dataproperty_public + 1.0a + 2011-01-14 + Defines if a Seed data is publishable or not + Defines if a Seed data is publishable or not + Pedro Lopes pedrolopes@ua.pt + public + + + + + + + + + dataproperty_query + 1.0a + 2011-01-27 + A Column selector for the associated Resource + A Column selector for the associated Resource + Pedro Lopes pedrolopes@ua.pt + query + + + + + + + + + + + + + dataproperty_regex + 1.0b + 2011-05-03 + Description for used regular expressions. + Description for used regular expressions. + Pedro Lopes pedrolopes@ua.pt + regex + + + + + + + + + dataproperty_replace + 1.0a + 2011-01-19 + Pedro Lopes pedrolopes@ua.pt + The replaceable token in a Resource + The replaceable token in a Resource + replace + + + + + + + + + + + + + dataproperty_select + 1.0a + 2011-01-27 + Pedro Lopes pedrolopes@ua.pt + The select statement to get data from a Resource + The select statement to get data from a Resource + select + + + + + + + + + + + + + + + class_bridge + + 1.0a + 2011-01-19 + Bridge individuals are connections to external resources. They are used to interact with these resources. A Bridge can be a composeable URL or simple text to be replaced with data from the 3SDB. + Bridge individuals are connections to external resources. They are used to interact with these resources. A Bridge can be a composeable URL or simple text to be replaced with data from the 3SDB. + Pedro Lopes pedrolopes@ua.pt + Title + + + + + + + + class_csv + + 1.0a + 2011-01-18 + CSV + Class for CSV resource individuals and definitions + Class for CSV resource individuals and definitions + Pedro Lopes pedrolopes@ua.pt + + + + + + + + class_concept + + 1.0a + 2011-01-14 + Concept + Concept element are used to organize distinct resources. + + Examples: + - HGNC + - UniProt + Concept element are used to organize distinct resources. + + Examples: + - HGNC + - UniProt + Pedro Lopes pedrolopes@ua.pt + + + + + + + + class_entity + + 1.0a + 2011-01-14 + Entity + Entity elements are the main data organizational class inside COEUS. Entities act as upper classes to all other elements in the Seed. + + Everything is an Entity. + + Example: + - Gene + - Protein + Entity elements are the main data organizational class inside COEUS. Entities act as upper classes to all other elements in the Seed. + + Everything is an Entity. + + Example: + - Gene + - Protein + Pedro Lopes pedrolopes@ua.pt + + + + + + + + class_item + + 1.0a + 2011-01-14 + Item + Item elements are the most atomic information units in COEUS. + Item elements are the most atomic information units in COEUS. + Pedro Lopes pedrolopes@ua.pt + + + + + + + + class_module + + 1.0a + 2011-01-19 + Class for platform modules: "Module" individual + Class for platform modules: "Module" individual + Module + Pedro Lopes pedrolopes@ua.pt + + + + + + + + class_resource + + 1.0a + 2011-01-18 + Pedro Lopes pedrolopes@ua.pt + Resource + Resource individuals reflect the data, information or knowledge sources for each Seed Concept + Resource individuals reflect the data, information or knowledge sources for each Seed Concept + + + + + + + + class_sparql + + 1.0a + 2011-01-26 + Class for SPARQL resource individuals and definitions + Class for SPARQL resource individuals and definitions + Pedro Lopes pedrolopes@ua.pt + SPARQL + + + + + + + + class_sql + + 1.0a + 2011-01-18 + Class for SQL resource individuals and definitions + Class for SQL resource individuals and definitions + Pedro Lopes pedrolopes@ua.pt + SQL + + + + + + + + class_seed + 1.0a + 2011-01-14 + Pedro Lopes pedrolopes@ua.pt + Seed + This class is used to store Seed information such has host features or availability. + This class is used to store Seed information such has host features or availability. + + + + + + + + class_xml + + 1.0a + 2011-01-18 + Class for XML resource individuals and definitions + Class for XML resource individuals and definitions + Pedro Lopes pedrolopes@ua.pt + XML + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/tester/predicates.csv b/src/main/resources/tester/predicates.csv index 9f5cce3..8c31162 100644 --- a/src/main/resources/tester/predicates.csv +++ b/src/main/resources/tester/predicates.csv @@ -76,4 +76,5 @@ http://bioinformatics.ua.pt/coeus/resource/isConnectedTo http://bioinformatics.ua.pt/coeus/resource/loadsFrom http://bioinformatics.ua.pt/coeus/resource/hasBridge http://bioinformatics.ua.pt/coeus/resource/hasConcept -http://www.w3.org/2000/01/rdf-schema#seeAlso \ No newline at end of file +http://www.w3.org/2000/01/rdf-schema#seeAlso +http://bioinformatics.ua.pt/coeus/resource/regex \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index a12d0c5..a08d544 100755 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -34,7 +34,8 @@ org.joseki.http.Servlet org.joseki.rdfserver.config - joseki.ttl + + joseki.ttl @@ -49,7 +50,8 @@ config-file - classes/pubby.ttl + + classes/pubby.ttl @@ -64,13 +66,13 @@ de.fuberlin.wiwiss.pubby.servlets.PageURLServlet 1 - + WebURLServlet de.fuberlin.wiwiss.pubby.servlets.PageURLServlet 1 - + WebURLServlet /resource/* @@ -120,8 +122,42 @@ - pt.ua.bioinformatics.coeus.common.HttpListener + pt.ua.bioinformatics.coeus.common.HttpListener + + pt.ua.bioinformatics.coeus.common.ExecutorContextListener + + + + index.jsp diff --git a/src/main/webapp/assets/css/bootstrap.css b/src/main/webapp/assets/css/bootstrap.css index 6f5ca08..a23ac60 100644 --- a/src/main/webapp/assets/css/bootstrap.css +++ b/src/main/webapp/assets/css/bootstrap.css @@ -1669,7 +1669,7 @@ select:focus:invalid:focus { .input-prepend { display: inline-block; margin-bottom: 10px; - font-size: 0; + font-size: 14px; white-space: nowrap; vertical-align: middle; } diff --git a/src/main/webapp/assets/css/typeahead.css b/src/main/webapp/assets/css/typeahead.css new file mode 100644 index 0000000..56653de --- /dev/null +++ b/src/main/webapp/assets/css/typeahead.css @@ -0,0 +1,49 @@ +.twitter-typeahead .tt-query, +.twitter-typeahead .tt-hint { + margin-bottom: 0; +} + +.tt-dropdown-menu { + min-width: 160px; + margin-top: 2px; + padding: 5px 0; + background-color: #fff; + border: 1px solid #ccc; + border: 1px solid rgba(0,0,0,.2); + *border-right-width: 2px; + *border-bottom-width: 2px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2); + -moz-box-shadow: 0 5px 10px rgba(0,0,0,.2); + box-shadow: 0 5px 10px rgba(0,0,0,.2); + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box; +} + +.tt-suggestion { + display: block; + padding: 3px 20px; +} + +.tt-suggestion.tt-is-under-cursor { + color: #fff; + background-color: #0081c2; + background-image: -moz-linear-gradient(top, #0088cc, #0077b3); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3)); + background-image: -webkit-linear-gradient(top, #0088cc, #0077b3); + background-image: -o-linear-gradient(top, #0088cc, #0077b3); + background-image: linear-gradient(to bottom, #0088cc, #0077b3); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0) +} + +.tt-suggestion.tt-is-under-cursor a { + color: #fff; +} + +.tt-suggestion p { + margin: 0; +} \ No newline at end of file diff --git a/src/main/webapp/assets/js/bootstrap-tooltip.js b/src/main/webapp/assets/js/bootstrap-tooltip.js new file mode 100644 index 0000000..a3bbd58 --- /dev/null +++ b/src/main/webapp/assets/js/bootstrap-tooltip.js @@ -0,0 +1,361 @@ +/* =========================================================== + * bootstrap-tooltip.js v2.3.2 + * http://twitter.github.com/bootstrap/javascript.html#tooltips + * Inspired by the original jQuery.tipsy by Jason Frame + * =========================================================== + * Copyright 2012 Twitter, 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. + * ========================================================== */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* TOOLTIP PUBLIC CLASS DEFINITION + * =============================== */ + + var Tooltip = function (element, options) { + this.init('tooltip', element, options) + } + + Tooltip.prototype = { + + constructor: Tooltip + + , init: function (type, element, options) { + var eventIn + , eventOut + , triggers + , trigger + , i + + this.type = type + this.$element = $(element) + this.options = this.getOptions(options) + this.enabled = true + + triggers = this.options.trigger.split(' ') + + for (i = triggers.length; i--;) { + trigger = triggers[i] + if (trigger == 'click') { + this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) + } else if (trigger != 'manual') { + eventIn = trigger == 'hover' ? 'mouseenter' : 'focus' + eventOut = trigger == 'hover' ? 'mouseleave' : 'blur' + this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) + this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) + } + } + + this.options.selector ? + (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : + this.fixTitle() + } + + , getOptions: function (options) { + options = $.extend({}, $.fn[this.type].defaults, this.$element.data(), options) + + if (options.delay && typeof options.delay == 'number') { + options.delay = { + show: options.delay + , hide: options.delay + } + } + + return options + } + + , enter: function (e) { + var defaults = $.fn[this.type].defaults + , options = {} + , self + + this._options && $.each(this._options, function (key, value) { + if (defaults[key] != value) options[key] = value + }, this) + + self = $(e.currentTarget)[this.type](options).data(this.type) + + if (!self.options.delay || !self.options.delay.show) return self.show() + + clearTimeout(this.timeout) + self.hoverState = 'in' + this.timeout = setTimeout(function() { + if (self.hoverState == 'in') self.show() + }, self.options.delay.show) + } + + , leave: function (e) { + var self = $(e.currentTarget)[this.type](this._options).data(this.type) + + if (this.timeout) clearTimeout(this.timeout) + if (!self.options.delay || !self.options.delay.hide) return self.hide() + + self.hoverState = 'out' + this.timeout = setTimeout(function() { + if (self.hoverState == 'out') self.hide() + }, self.options.delay.hide) + } + + , show: function () { + var $tip + , pos + , actualWidth + , actualHeight + , placement + , tp + , e = $.Event('show') + + if (this.hasContent() && this.enabled) { + this.$element.trigger(e) + if (e.isDefaultPrevented()) return + $tip = this.tip() + this.setContent() + + if (this.options.animation) { + $tip.addClass('fade') + } + + placement = typeof this.options.placement == 'function' ? + this.options.placement.call(this, $tip[0], this.$element[0]) : + this.options.placement + + $tip + .detach() + .css({ top: 0, left: 0, display: 'block' }) + + this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element) + + pos = this.getPosition() + + actualWidth = $tip[0].offsetWidth + actualHeight = $tip[0].offsetHeight + + switch (placement) { + case 'bottom': + tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2} + break + case 'top': + tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2} + break + case 'left': + tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth} + break + case 'right': + tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width} + break + } + + this.applyPlacement(tp, placement) + this.$element.trigger('shown') + } + } + + , applyPlacement: function(offset, placement){ + var $tip = this.tip() + , width = $tip[0].offsetWidth + , height = $tip[0].offsetHeight + , actualWidth + , actualHeight + , delta + , replace + + $tip + .offset(offset) + .addClass(placement) + .addClass('in') + + actualWidth = $tip[0].offsetWidth + actualHeight = $tip[0].offsetHeight + + if (placement == 'top' && actualHeight != height) { + offset.top = offset.top + height - actualHeight + replace = true + } + + if (placement == 'bottom' || placement == 'top') { + delta = 0 + + if (offset.left < 0){ + delta = offset.left * -2 + offset.left = 0 + $tip.offset(offset) + actualWidth = $tip[0].offsetWidth + actualHeight = $tip[0].offsetHeight + } + + this.replaceArrow(delta - width + actualWidth, actualWidth, 'left') + } else { + this.replaceArrow(actualHeight - height, actualHeight, 'top') + } + + if (replace) $tip.offset(offset) + } + + , replaceArrow: function(delta, dimension, position){ + this + .arrow() + .css(position, delta ? (50 * (1 - delta / dimension) + "%") : '') + } + + , setContent: function () { + var $tip = this.tip() + , title = this.getTitle() + + $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) + $tip.removeClass('fade in top bottom left right') + } + + , hide: function () { + var that = this + , $tip = this.tip() + , e = $.Event('hide') + + this.$element.trigger(e) + if (e.isDefaultPrevented()) return + + $tip.removeClass('in') + + function removeWithAnimation() { + var timeout = setTimeout(function () { + $tip.off($.support.transition.end).detach() + }, 500) + + $tip.one($.support.transition.end, function () { + clearTimeout(timeout) + $tip.detach() + }) + } + + $.support.transition && this.$tip.hasClass('fade') ? + removeWithAnimation() : + $tip.detach() + + this.$element.trigger('hidden') + + return this + } + + , fixTitle: function () { + var $e = this.$element + if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') { + $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') + } + } + + , hasContent: function () { + return this.getTitle() + } + + , getPosition: function () { + var el = this.$element[0] + return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : { + width: el.offsetWidth + , height: el.offsetHeight + }, this.$element.offset()) + } + + , getTitle: function () { + var title + , $e = this.$element + , o = this.options + + title = $e.attr('data-original-title') + || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) + + return title + } + + , tip: function () { + return this.$tip = this.$tip || $(this.options.template) + } + + , arrow: function(){ + return this.$arrow = this.$arrow || this.tip().find(".tooltip-arrow") + } + + , validate: function () { + if (!this.$element[0].parentNode) { + this.hide() + this.$element = null + this.options = null + } + } + + , enable: function () { + this.enabled = true + } + + , disable: function () { + this.enabled = false + } + + , toggleEnabled: function () { + this.enabled = !this.enabled + } + + , toggle: function (e) { + var self = e ? $(e.currentTarget)[this.type](this._options).data(this.type) : this + self.tip().hasClass('in') ? self.hide() : self.show() + } + + , destroy: function () { + this.hide().$element.off('.' + this.type).removeData(this.type) + } + + } + + + /* TOOLTIP PLUGIN DEFINITION + * ========================= */ + + var old = $.fn.tooltip + + $.fn.tooltip = function ( option ) { + return this.each(function () { + var $this = $(this) + , data = $this.data('tooltip') + , options = typeof option == 'object' && option + if (!data) $this.data('tooltip', (data = new Tooltip(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + $.fn.tooltip.Constructor = Tooltip + + $.fn.tooltip.defaults = { + animation: true + , placement: 'top' + , selector: false + , template: '
    ' + , trigger: 'hover focus' + , title: '' + , delay: 0 + , html: false + , container: false + } + + + /* TOOLTIP NO CONFLICT + * =================== */ + + $.fn.tooltip.noConflict = function () { + $.fn.tooltip = old + return this + } + +}(window.jQuery); diff --git a/src/main/webapp/assets/js/coeus.api.js b/src/main/webapp/assets/js/coeus.api.js index a048f5d..1380531 100644 --- a/src/main/webapp/assets/js/coeus.api.js +++ b/src/main/webapp/assets/js/coeus.api.js @@ -34,7 +34,7 @@ function writeTriple(subject, predicate, object, key) { * @returns {undefined} */ function updateTriple(subject, predicate, old_object, new_object, key) { - $.ajax({url: './api/' + key + '/update/' + subject + '/' + predicate + '/' + old_object+ ','+new_object, dataType: 'json'}).done(function(data) { + $.ajax({url: './api/' + key + '/update/' + subject + '/' + predicate + '/' + old_object + ',' + new_object, dataType: 'json'}).done(function(data) { if (data.status === 100) { console.log('[COEUS] data successfully updated in knowledge base.'); // All OK function handler. @@ -58,7 +58,7 @@ function updateTriple(subject, predicate, old_object, new_object, key) { * @returns {undefined} */ function deleteTriple(subject, predicate, object, key) { - $.ajax({url: './api/' + key + '/delete/' + subject + '/' + predicate + '/' +object, dataType: 'json'}).done(function(data) { + $.ajax({url: './api/' + key + '/delete/' + subject + '/' + predicate + '/' + object, dataType: 'json'}).done(function(data) { if (data.status === 100) { console.log('[COEUS] data successfully deleted in knowledge base.'); // All OK function handler. diff --git a/src/main/webapp/assets/js/coeus.setup.js b/src/main/webapp/assets/js/coeus.setup.js new file mode 100644 index 0000000..d45cca5 --- /dev/null +++ b/src/main/webapp/assets/js/coeus.setup.js @@ -0,0 +1,1188 @@ +/** + * COEUS Setup JS functions (included in most pages..) + */ + +/** + * init service prefix + * @returns {query} */ +function initSparqlerQuery() { + var sparqler = new SPARQL.Service("/coeus/sparql"); + + var prefixes = getPrefixURI(); + for (var key in prefixes) { + sparqler.setPrefix(key, prefixes[key]); + } + + var query = sparqler.createQuery(); + return query; +} + +function getPrefixURI() { + var prefixes = { + dc: "http://purl.org/dc/elements/1.1/", + rdf: "http://www.w3.org/1999/02/22-rdf-syntax-ns#", + rdfs: "http://www.w3.org/2000/01/rdf-schema#", + coeus: "http://bioinformatics.ua.pt/coeus/resource/", + owl: "http://www.w3.org/2002/07/owl#" + }; + return prefixes; +} + +/** + * Get the namespace prefix + * + * @param {type} uri + * @returns {undefined} + */ +function getPrefix(uri) { + var prefixes = getPrefixURI(); + + for (var key in prefixes) { + if (prefixes[key] === uri) + return key; + } + return ''; +} + +/** + * Split the URI to give the namespace + * @param {type} uri + * @returns {splitURIPrefix.mapping} + */ +function splitURIPrefix(uri) { + var value; + var uriToSlit = uri; + if (uriToSlit.indexOf("#") !== -1) + value = uriToSlit.split('#').pop(); + else + value = uriToSlit.split('/').pop(); + var namespace = uri.substr(0, uri.length - value.length); + + var mapping = { + "namespace": namespace, + "value": value + }; + + return mapping; +} +/** + * Call api through URL and change the HTML (component id) according to the result. + * @param {type} url + * @param {type} html + * @returns {undefined} + */ +//function callAPI(url, html) { +// url = encodeURI(url); +// $.ajax({url: url, async: false, dataType: 'json'}).done(function(data) { +// console.log(url + ' ' + data.status); +// if (data.status === 100) { +// //$(html).append('Call: ' + url + '
    Message: ' + data.message+'

    '); +// $(html).addClass('alert alert-success'); +// } else { +// $(html).addClass('alert alert-error'); +// $(html).append('Call: ' + url + '
    Status: ' + data.status + ' Message: ' + data.message + '

    '); +// } +// +// }).fail(function(jqXHR, textStatus) { +// $(html).addClass('alert alert-error'); +// $(html).append('Call: ' + url + '
    ' + 'ERROR: ' + textStatus + '

    '); +// // Server communication error function handler. +// }); +//} +/** + * Return the first apikey + * + * @returns {unresolved} */ +function getApiKey() { + return document.getElementById('apikey').innerHTML.split('|')[0]; +} +/** + * Return last element divided by / of url + * @returns {unresolved} + */ +function lastPath() { + var pathArray = window.location.pathname.split('/'); + var path = pathArray[pathArray.length - 1]; + return path; +} + +/** + * Return penultimate element divided by / of url + * @returns {unresolved} + */ +function penulPath() { + var pathArray = window.location.pathname.split('/'); + var path = pathArray[pathArray.length - 2]; + return path; +} + +function redirect(location) { + window.location = location; +} +/** + * + * remove all subjects and predicates associated. + * + * example urlPrefix = "../../api/" + getApiKey() ; + * + * @param {type} urlPrefix + * @param {type} object + * @returns {undefined} + */ +function removeAllTriplesFromObject(urlPrefix, object, showResult, showError) { + + var qObject = "SELECT ?subject ?predicate {?subject ?predicate " + object + " . }"; + queryToResult(qObject, foreachRemoveObjects.bind(this, urlPrefix, object, showResult, showError)); +} +function foreachRemoveObjects(urlPrefix, object, showResult, showError, result) { + console.log(result); + for (var r in result) { + var subject = resultToObject(result[r].subject); + var predicate = resultToPredicate(result[r].predicate); + + var url = "/delete/" + subject.prefix + subject.value + '/' + predicate.prefix + predicate.value + '/' + object; + + console.log("Delete call: " + urlPrefix + url); + callURL(urlPrefix + url, showResult, showError); + } +} + +/** + * Clears all unlinked triples in the DB + * @param {type} urlPrefix + * @param {type} showResult + * @param {type} showError + * @returns {undefined} + */ +function cleanUnlikedTriples(urlPrefix, showResult, showError) { + console.log("cleanUnlikedTriples call"); + //Clean unlinked entities + var qEntities = "SELECT * {{ ?entity a coeus:Entity . FILTER NOT EXISTS{ ?entity coeus:isIncludedIn ?seed }}UNION {?entity a coeus:Entity . FILTER NOT EXISTS { ?seed coeus:includes ?entity }} }"; + queryToResult(qEntities, function(result) { + for (var r in result) { + var entity = splitURIPrefix(result[r].entity.value); + var prefix = getPrefix(entity.namespace) + ":"; + removeAllTriplesFromSubject(urlPrefix, prefix + entity.value, showResult, showError); + } + }); + //Clean unlinked concepts + var qConcepts = "SELECT * {{ ?concept a coeus:Concept . FILTER NOT EXISTS{ ?concept coeus:hasEntity ?entity }}UNION {?concept a coeus:Concept . FILTER NOT EXISTS { ?entity coeus:isEntityOf ?concept }} }"; + queryToResult(qConcepts, function(result) { + for (var r in result) { + var concept = splitURIPrefix(result[r].concept.value); + var prefix = getPrefix(concept.namespace) + ":"; + removeAllTriplesFromSubject(urlPrefix, prefix + concept.value, showResult, showError); + } + }); + //Clean unlinked resources + var qResources = "SELECT * {{ ?resource a coeus:Resource . FILTER NOT EXISTS{ ?resource coeus:isResourceOf ?concept} }UNION {?resource a coeus:Resource . FILTER NOT EXISTS { ?concept coeus:hasResource ?resource}} }"; + queryToResult(qResources, function(result) { + for (var r in result) { + var resource = splitURIPrefix(result[r].resource.value); + var prefix = getPrefix(resource.namespace) + ":"; + removeAllTriplesFromSubject(urlPrefix, prefix + resource.value, showResult, showError); + } + }); + //Clean unlinked selectores + var qSelectores = "SELECT * {{ ?selector coeus:property ?property . FILTER NOT EXISTS { ?selector coeus:loadsFor ?resource } }UNION {?selector coeus:property ?property . FILTER NOT EXISTS { ?resource coeus:loadsFrom ?selector}}}"; + queryToResult(qSelectores, function(result) { + for (var r in result) { + var selector = splitURIPrefix(result[r].selector.value); + var prefix = getPrefix(selector.namespace) + ":"; + removeAllTriplesFromSubject(urlPrefix, prefix + selector.value, showResult, showError); + } + }); +} + +//function isModel(key) { +// var b = false; +// +// if (key.indexOf("coeus:seed_") !== -1 | key.indexOf("coeus:entity_") !== -1 | key.indexOf("coeus:concept_") !== -1 | key.indexOf("coeus:resource_") !== -1) +// b = true; +// +// console.log(key + ' ' + b); +// return b; +// +//} +// +//function removeRecursive(urlPrefix, subject) { +// var query = initSparqlerQuery(); +// var qObject = "SELECT ?predicate ?object {" + subject + " ?predicate ?object . }"; +// console.log("Recursive call: " + qObject); +// query.query(qObject, +// {success: function(json) { +// var result = json.results.bindings; +// +// for (var r in result) { +// var object = resultToObject(result[r].object); +// var predicate = resultToPredicate(result[r].predicate); +// +// var url = "/delete/" + subject + '/' + predicate.prefix + predicate.value + '/' + object.prefix + object.value; +// console.log("Recursive Delete call: " + urlPrefix + url); +// //callAPI(urlPrefix + url, "#result"); +// if (isModel(object.prefix + object.value)) { +// // console.log("Another recursive call: "+url); +// //removeRecursive(urlPrefix, object.prefix + object.value); +// } +// +// } +// +// +// }} +// ); +//} + +/** + * Remove all triples associated with the subject + * + * @param {type} urlPrefix + * @param {type} subject + * @param {type} showResult + * @param {type} showError + * @returns {undefined} + */ +function removeAllTriplesFromSubject(urlPrefix, subject, showResult, showError) { + var qSubject = "SELECT ?predicate ?object {" + subject + " ?predicate ?object . }"; + queryToResult(qSubject, foreachRemoveSubjects.bind(this, urlPrefix, subject, showResult, showError) + ); +} +function foreachRemoveSubjects(urlPrefix, subject, showResult, showError, result) { + console.log(result); + for (var r in result) { + var object = resultToObject(result[r].object); + var predicate = resultToPredicate(result[r].predicate); + + var url = "/delete/" + subject + '/' + predicate.prefix + predicate.value + '/' + object.prefix + object.value; + console.log("Deleting: " + url); + callURL(urlPrefix + url, showResult, showError); + } +} + +//function removeAllTriplesFromSubjectAndPredicate(urlPrefix, subject, predicate) { +// var qSubject = "SELECT ?object {" + subject + " " + predicate + " ?object . }"; +// console.log(qSubject); +// queryToResult(qSubject, function(result) { +// console.log(result); +// for (var r in result) { +// var object = resultToObject(result[r].object); +// +// var url = "/delete/" + subject + '/' + predicate + '/' + object.prefix + object.value; +// console.log(url); +// callAPI(urlPrefix + url, "#result"); +// } +// +// //if success refresh page +// if (document.getElementById('result').className !== 'alert alert-error') { +// // window.location="../entity/"+lastPath(); +// console.log("REDIRECTING..."); +// //window.location.reload(true); +// } +// } +// ); +//} +//function removeAllTriplesFromPredicateAndObject(urlPrefix, predicate, object) { +// var qSubject = "SELECT ?subject {?subject " + predicate + " " + object + " . }"; +// console.log(qSubject); +// queryToResult(qSubject, function(result) { +// console.log(result); +// for (var r in result) { +// var subject = resultToPredicate(result[r].subject); +// +// var url = "/delete/" + subject.prefix + subject.value + '/' + predicate + '/' + object; +// //console.log(url); +// callAPI(urlPrefix + url, "#result"); +// } +// } +// ); +//} + +/** + * Converts a object from the json result to a url usage + * @param {type} object + * @returns {resultToObject.mapping} + */ +function resultToObject(object) { + var val = object.value; + var objectPrefix = ''; + + if (object.type === "uri") { + var splitedObject = splitURIPrefix(val); + val = splitedObject.value; + objectPrefix = getPrefix(splitedObject.namespace); + } + + if (objectPrefix !== '') + objectPrefix = objectPrefix + ':'; + else + objectPrefix = 'xsd:' + splitURIPrefix(object.datatype).value + ':' + objectPrefix; + //TO ALLOW '/' in the string call encodeBars(string); + var mapping = { + "prefix": objectPrefix, + "value": encodeBars(val) + }; + return mapping; +} +/** + * Converts a predicate from the json result to a url usage + * @param {type} pred + * @returns {resultToPredicate.mapping} + */ +function resultToPredicate(pred) { + var splitedPredicate = splitURIPrefix(pred.value); + var predicatePrefix = getPrefix(splitedPredicate.namespace); + if (predicatePrefix !== '') + predicatePrefix = predicatePrefix + ':'; + + var mapping = { + "prefix": predicatePrefix, + "value": splitedPredicate.value + }; + + return mapping; + +} +/** + * Do a query to retrive the result in a callback way + * + * return callback(result); + * + * @param {type} selectQuery + * @param {type} callback + * @returns {undefined} + */ +function queryToResult(selectQuery, callback) { + var query = initSparqlerQuery(); + query.query(selectQuery, + {success: function(json) { + var result = json.results.bindings; + //console.log(result); + callback(result); + }} + ); +} + +/** + * Manually encode of some chars (;/#?) + * @param {type} value + * @returns {unresolved} + */ +function encodeBars(value) { + value = value.split(';').join('%3B'); + value = value.split('/').join('%2F'); + value = value.split('#').join('%23'); + value = value.split('?').join('%3F'); + return value; +} +/** + * Remove an component by id + * @param {type} childDiv + * @param {type} parentDiv + * @returns {undefined} + */ +function removeById(childDiv, parentDiv) +{ + console.log(childDiv + ' ' + parentDiv); + if (childDiv === parentDiv) { + alert("The parent div cannot be removed."); + } + else if (document.getElementById(childDiv)) { + var child = document.getElementById(childDiv); + var parent = document.getElementById(parentDiv); + parent.removeChild(child); + } + else { + alert("Child div has already been removed or does not exist."); + } +} + +/** + * Call a url with 2 callbacks functions (success or error) + * + * @param {type} url + * @param {type} success + * @param {type} error + * @returns {undefined} + */ +function callURL(url, success, error) { + url = encodeURI(url); + console.log(url); + $.ajax({url: url, dataType: 'json'}).done(success).fail(error); +} + +/** + * Generate a html code message + * Ex: var htmlMessage=generateHtmlMessage("Error!", "It already exists!","alert-error"); + * + * @param {type} strong + * @param {type} message + * @param {type} type + * @returns {String} + */ +function generateHtmlMessage(strong, message, type) { + var error = '
    ' + strong + ' ' + message + '
    '; + return error; +} + +/** + * Begin of the code used to manage the modals (Seed,Entity,Concept) + */ + +/** + * Associate click event to loading btn's. + */ +$('.loading').click(function() { + var text = $(this).html(); + $(this).html('Waiting...'); + $(this).addClass('disabled'); + setTimeout(btnInit.bind(this, text), 1500); + + function btnInit(text) { + $(this).html(text); + $(this).removeClass('disabled'); + } +}); +//timer for manage success or errors on modals +var timer; +var delay = 1000; + +/** + * Remove the link between the triples and the triples + * @returns {undefined} + */ +function removeTriples() { + var individual = $('#removeModalLabel').html(); + console.log('Remove: ' + individual); + + var urlPrefix = "../../api/" + getApiKey(); + //remove all subjects and predicates associated. + removeAllTriplesFromObject(urlPrefix, individual, showResult.bind(this, "#removeResult", ""), showError.bind(this, "#removeResult", "")); + //remove all predicates and objects associated. + removeAllTriplesFromSubject(urlPrefix, individual, showResult.bind(this, "#removeResult", ""), showError.bind(this, "#removeResult", "")); + + timer = setTimeout(function() { + $('#closeRemoveModal').click(); + refresh(); + }, delay); + +} +/** + * remove preview - called before remove + * @param {type} individual + * @returns {undefined} + */ +function selectToRemove(individual) { + $('#removeResult').html(""); + $('#removeModalLabel').html(individual); + if (individual.indexOf('coeus:entity') === 0) { + $('#removeType').html("Entity"); + } else if (individual.indexOf('coeus:concept') === 0) { + $('#removeType').html("Concept"); + } else if (individual.indexOf('coeus:seed') === 0) { + $('#removeType').html("Seed"); + } else if (individual.indexOf('coeus:resource') === 0) { + $('#removeType').html("Resource"); + } else { + } +} +//End of Remove functions +//Edit functions +/** + * Edit preview for Seed,Entity or Concept + * @param {type} individual + * @returns {undefined} + */ +function prepareEdit(individual) { + //reset values + $('#editResult').html(""); + document.getElementById('editURI').innerHTML = individual; + if (individual.indexOf('coeus:entity') === 0) { + $('#editType').html("Entity"); + $('#helpEdit').html("Entity individuals match the general data terms. These elements grouping concepts with a common set of properties."); + } else if (individual.indexOf('coeus:concept') === 0) { + $('#editType').html("Concept"); + $('#helpEdit').html("Concept individuals are area-specific terms, aggregating any number of items and belonging to a unique entity. Concept individuals are also connected to Resources."); + } else if (individual.indexOf('coeus:seed') === 0) { + $('#editType').html("Seed"); + $('#helpEdit').html("A Seed defines a single framework instance that permits access to all data available in the seed, providing an over-arching entry point to the system information. Seed individuals are also connected to included entities. "); + } else { + } + + $('#editTitle').val(""); + $('#editLabel').val(""); + $('#editComment').val(""); + + var q = "SELECT ?label ?title ?comment {" + individual + " dc:title ?title . " + individual + " rdfs:label ?label . " + individual + " rdfs:comment ?comment }"; + queryToResult(q, fillEdit); +} +function fillEdit(result) { + //var resultTitle = json.results.bindings[0].title; + console.log(result); + try + { + //PUT VALUES IN THE INPUT FIELD + $('#editTitle').val(result[0].title.value); + //document.getElementById('title').setAttribute("disabled"); + $('#editLabel').val(result[0].label.value); + $('#editComment').val(result[0].comment.value); + } + catch (err) + { + $('#editResult').append(generateHtmlMessage("Error!", "Some fields do not exist." + err, "alert-error")); + } + //PUT OLD VALUES IN THE STATIC FIELD + $('#oldTitle').val($('#editTitle').val()); + $('#oldLabel').val($('#editLabel').val()); + $('#oldComment').val($('#editComment').val()); + +} +/** + * Function to edit a Seed, Entity or Concept + * @returns {undefined} + */ +function edit() { + var individual = $('#editURI').html(); + var urlUpdate = "../../api/" + getApiKey() + "/update/"; + var url; + timer = setTimeout(function() { + $('#closeEditModal').click(); + refresh(); + }, delay); + + if ($('#oldLabel').val() !== $('#editLabel').val()) { + url = urlUpdate + individual + "/" + "rdfs:label" + "/xsd:string:" + $('#oldLabel').val() + ",xsd:string:" + $('#editLabel').val(); + callURL(url, showResult.bind(this, "#editResult", url), (this, "#editResult", url)); + } + if ($('#oldTitle').val() !== $('#editTitle').val()) { + url = urlUpdate + individual + "/" + "dc:title" + "/xsd:string:" + $('#oldTitle').val() + ",xsd:string:" + $('#editTitle').val(); + callURL(url, showResult.bind(this, "#editResult", url), (this, "#editResult", url)); + } + if ($('#oldComment').val() !== $('#editComment').val()) { + url = urlUpdate + individual + "/" + "rdfs:comment" + "/xsd:string:" + $('#oldComment').val() + ",xsd:string:" + $('#editComment').val(); + callURL(url, showResult.bind(this, "#editResult", url), (this, "#editResult", url)); + } +} +//End of Edit functions + +/** + * change the uri when the user fill the title box. + * @param {type} type + * @param {type} link + * @returns {undefined} + */ +function changeURI(id, type, value) { + document.getElementById(id).innerHTML = 'coeus:' + type.toLowerCase() + '_' + value.split(' ').join('_'); +} +/** + * Function to be called before add a Seed, Entity or Concept + * @param {type} type + * @param {type} link + * @returns {undefined} + */ +function prepareAdd(type, link) { + $('#addResult').html(""); + $('#title').val(""); + $('#label').val(""); + $('#comment').val(""); + $('#linkedWith').val(link); + //$('#addType').html(type); + var individual = 'coeus:' + type.toLowerCase(); + document.getElementById('uri').innerHTML = individual; + + if (individual.indexOf('coeus:entity') === 0) { + $('#addType').html("Entity"); + $('#helpAdd').html("Entity individuals match the general data terms. These elements grouping concepts with a common set of properties."); + } else if (individual.indexOf('coeus:concept') === 0) { + $('#addType').html("Concept"); + $('#helpAdd').html("Concept individuals are area-specific terms, aggregating any number of items and belonging to a unique entity. Concept individuals are also connected to Resources."); + } else if (individual.indexOf('coeus:seed') === 0) { + $('#addType').html("Seed"); + $('#helpAdd').html("A Seed defines a single framework instance that permits access to all data available in the seed, providing an over-arching entry point to the system information. Seed individuals are also connected to included entities. "); + } else { + } + +} +/** + * Function to add a Seed, Entity or Concept + * @param {type} id + * @param {type} url + * @param {type} result + * @returns {undefined} + */ +function add() { + + var individual = $('#uri').html(); + var type = $('#addType').html(); + console.log("Adding type: " + type); + var title = $('#title').val(); + var label = $('#label').val(); + var comment = $('#comment').val(); + var urlWrite = "../../api/" + getApiKey() + "/write/"; + var link = $('#linkedWith').val(); + + // verify all fields: + var empty = false; + if (title === '') { + $('#titleForm').addClass('controls control-group error'); + empty = true; + } else + $('#titleForm').removeClass('controls control-group error'); + if (label === '') { + $('#labelForm').addClass('controls control-group error'); + empty = true; + } else + $('#labelForm').removeClass('controls control-group error'); + if (comment === '') { + $('#commentForm').addClass('controls control-group error'); + empty = true; + } else + $('#commentForm').removeClass('controls control-group error'); + if (!empty) { + var array = new Array(); + var urlIndividual = urlWrite + individual + "/rdf:type/owl:NamedIndividual"; + var urlType = urlWrite + individual + "/rdf:type/coeus:" + type; + var urlTitle = urlWrite + individual + "/dc:title/xsd:string:" + title; + var urlLabel = urlWrite + individual + "/rdfs:label/xsd:string:" + label; + var urlComment = urlWrite + individual + "/rdfs:comment/xsd:string:" + comment; + if (type === 'Entity') { + var urlIsIncludedIn = urlWrite + individual + "/coeus:isIncludedIn/" + link; + var urlIncludes = urlWrite + link + "/coeus:includes/" + individual; + array.push(urlIndividual, urlType, urlTitle, urlLabel, urlComment, urlIsIncludedIn, urlIncludes); + } else if (type === 'Concept') { + var urlHasEntity = urlWrite + individual + "/coeus:hasEntity/" + link; + var urlIsEntityOf = urlWrite + link + "/coeus:isEntityOf/" + individual; + array.push(urlIndividual, urlType, urlTitle, urlLabel, urlComment, urlHasEntity, urlIsEntityOf); + } else { + array.push(urlIndividual, urlType, urlTitle, urlLabel, urlComment); + } + submitIfNotExists(array, individual); + } +} +function submitIfNotExists(array, individual) { + var qSeeds = "SELECT (COUNT(*) AS ?total) {" + individual + " ?p ?o }"; + queryToResult(qSeeds, function(result) { + if (result[0].total.value == 0) { + + timer = setTimeout(function() { + if (individual.indexOf('coeus:resource') === 0) { + $('#closeAddResourceModal').click(); + refresh(); + } + else { + $('#closeAddModal').click(); + refresh(); + } + }, delay); + + if (individual.indexOf('coeus:resource') !== 0) { + var idResult = "#addResult"; + } else { + var idResult = "#addResourceResult"; + } + //call the service + array.forEach(function(url) { + callURL(url, showResult.bind(this, idResult, url), showError.bind(this, idResult, url)); + + }); + } else { + console.log('This individual ' + individual + ' already exists.'); + if (individual.indexOf('coeus:resource') !== 0) { + $('#addResult').append(generateHtmlMessage("Warning!", "This individual already exists. Try another title.", "alert-warning")); + } else { + $('#addResourceResult').append(generateHtmlMessage("Warning!", "This individual already exists. Try another title.", "alert-warning")); + } + } + }); +} +/** + * show the retrived result in the div (id) + * + * @param {type} id + * @param {type} url + * @param {type} result + * @returns {undefined} + */ +function showResult(id, url, result) { + if (result.status === 100) { + $(id).append(generateHtmlMessage("Success!", url + "
    " + result.message, "alert-success")); + } + else { + clearTimeout(timer); + $(id).append(generateHtmlMessage("Warning!", url + "
    Status Code:" + result.status + " " + result.message, "alert-warning")); + } +} +/** + * show the error result in the div (id) + * @param {type} id + * @param {type} url + * @param {type} jqXHR + * @param {type} result + * @returns {undefined} + */ +function showError(id, url, jqXHR, result) { + clearTimeout(timer); + $(id).append(generateHtmlMessage("Server error!", url + "
    Status Code:" + result.status + " " + result.message, "alert-error")); +} + +/** + * End of the code used to manage the modals (Seed,Entity,Concept) + */ + +/** + * Begin of the code used to manage the modals (Resource) + */ + +/** + * called before add resource to clean input fields + * @param {type} link + * @returns {undefined} + */ +function prepareAddResourceModal(link) { + $('#addResourceResult').html(""); + $('#titleResource').val(""); + $('#labelResource').val(""); + $('#commentResource').val(""); + document.getElementById('resourceURI').innerHTML = 'coeus:resource'; + $('#method').val(""); + $('#publisher').val(""); + $('#endpoint').val(""); + $('#query').val(""); + $('#order').val(""); + $('#extends').val(""); + $('#resourceLink').val(link); + var q = "SELECT ?concept ?c {?entity coeus:isEntityOf " + link + " . ?seed coeus:includes ?entity . ?concept coeus:hasEntity ?ent . ?ent coeus:isIncludedIn ?seed . ?concept dc:title ?c}"; + queryToResult(q, fillConceptsExtension); +} +function fillConceptsExtension(result) { + $('#extends').html(""); + $('#editExtends').html(""); + for (var r in result) { + var concept = splitURIPrefix(result[r].concept.value); + $('#extends').append(''); + $('#editExtends').append(''); + } +} +/** + * Add a Resource + * @returns {undefined} + */ +function addResource() { + + var type = 'Resource'; + var individual = $('#resourceURI').html(); + var title = $('#titleResource').val(); + var label = $('#labelResource').val(); + var comment = $('#commentResource').val(); + var method = $('#method').val(); + var publisher = $('#publisher').val(); + var endpoint = $('#endpoint').val(); + var query = $('#query').val(); + var order = $('#order').val(); + var concept_ext = $('#extends').val(); + var link = $('#resourceLink').val(); + var urlWrite = "../../api/" + getApiKey() + "/write/"; + + // verify all fields: + var empty = false; + if (title === '') { + $('#resourceTitleForm').addClass('controls control-group error'); + empty = true; + } else + $('#resourceTitleForm').removeClass('controls control-group error'); + if (label === '') { + $('#resourceLabelForm').addClass('controls control-group error'); + empty = true; + } else + $('#resourceLabelForm').removeClass('controls control-group error'); + if (comment === '') { + $('#resourceCommentForm').addClass('controls control-group error'); + empty = true; + } else + $('#resourceCommentForm').removeClass('controls control-group error'); + if (endpoint === '') { + $('#endpointForm').addClass('controls control-group error'); + empty = true; + } else + $('#endpointForm').removeClass('controls control-group error'); + if (query === '' && publisher !== ("csv")) { + $('#queryForm').addClass('controls control-group error'); + empty = true; + } else + $('#queryForm').removeClass('controls control-group error'); + if (order === '') { + $('#orderForm').addClass('controls control-group error'); + empty = true; + } else + $('#orderForm').removeClass('controls control-group error'); + if (!empty) { + var array = new Array(); + var urlIndividual = urlWrite + individual + "/rdf:type/owl:NamedIndividual"; + var urlType = urlWrite + individual + "/rdf:type/coeus:" + type; + var urlTitle = urlWrite + individual + "/dc:title/xsd:string:" + title; + var urlLabel = urlWrite + individual + "/rdfs:label/xsd:string:" + label; + var urlComment = urlWrite + individual + "/rdfs:comment/xsd:string:" + comment; + var urlIsResourceOf = urlWrite + individual + "/" + "coeus:isResourceOf" + "/" + link; + var urlHasResource = urlWrite + link + "/" + "coeus:hasResource" + "/" + individual; + var urlMethod = urlWrite + individual + "/" + "coeus:method" + "/xsd:string:" + method; + var urlPublisher = urlWrite + individual + "/" + "dc:publisher" + "/xsd:string:" + publisher; + var urlEndpoint = urlWrite + individual + "/" + "coeus:endpoint" + "/xsd:string:" + encodeBars(endpoint); + var urlQuery = urlWrite + individual + "/" + "coeus:query" + "/xsd:string:" + encodeBars(query); + var urlOrder = urlWrite + individual + "/" + "coeus:order" + "/xsd:string:" + order; + var urlExtends = urlWrite + individual + "/" + "coeus:extends" + "/coeus:" + concept_ext; + var urlIsExtendedBy = urlWrite + "coeus:" + concept_ext + "/" + "coeus:isExtendedBy" + "/" + individual; + var urlBuilt = urlWrite + individual + "/" + "coeus:built" + "/xsd:boolean:false"; + + array.push(urlIndividual, urlType, urlTitle, urlLabel, urlComment, urlIsResourceOf, urlHasResource, urlMethod, urlPublisher, urlEndpoint, urlQuery, urlOrder, urlExtends, urlIsExtendedBy, urlBuilt); + submitIfNotExists(array, individual); + } +} +/** + * Called when user change publisher in the modal Resource + * @param {type} mode + * @returns {undefined} + */ +function publisherChange(mode) { + + if (mode === 'edit') { + //sql + var publisher = $('#editPublisher').val(); + var sqlEnpointForm = '#editSqlEndpointForm'; + var enpointForm = '#editEndpointForm'; + var endpoint = '#editEndpoint'; + var driverEndpoint = '#editDriverEndpoint'; + var hostEndpoint = '#editHostEndpoint'; + var dbEndpoint = '#editDbEndpoint'; + var portEndpoint = '#editPortEndpoint'; + var userEndpoint = '#editUserEndpoint'; + var passwordEndpoint = '#editPasswordEndpoint'; + //csv + var query = '#editQuery'; + var queryForm = '#editQueryForm'; + var csvQueryForm = '#editCsvQueryForm'; + var csvQueryDelimiter = '#editCsvQueryDelimiter'; + var csvQueryHeaderSkip = '#editCsvQueryHeaderSkip'; + } else { + //sql + var publisher = $('#publisher').val(); + var sqlEnpointForm = '#sqlEndpointForm'; + var enpointForm = '#endpointForm'; + var endpoint = '#endpoint'; + var driverEndpoint = '#driverEndpoint'; + var hostEndpoint = '#hostEndpoint'; + var dbEndpoint = '#dbEndpoint'; + var portEndpoint = '#portEndpoint'; + var userEndpoint = '#userEndpoint'; + var passwordEndpoint = '#passwordEndpoint'; + //csv + var query = '#query'; + var queryForm = '#queryForm'; + var csvQueryForm = '#csvQueryForm'; + var csvQueryDelimiter = '#csvQueryDelimiter'; + var csvQueryHeaderSkip = '#csvQueryHeaderSkip'; + } + + if (publisher === "sql") { + $(sqlEnpointForm).removeClass('hide'); + $(enpointForm).addClass('hide'); + var endpoint = $(endpoint).val(); + //Endpoint sqlserver example: jdbc:mysql://host:3306;database=name;user=user;password=pass + //Endpoint mysql example: jdbc:mysql://host:3306/coeus?user=user&password=pass + if (endpoint !== "") { + try { + var url = endpoint.split("://"); //[jdbc:mysql] :// [host:3306/coeus?user=user&password=pass] + var driver = url[0].split("jdbc:")[1]; + if (driver === "sqlserver") { + //sqlserver + var cut = url[1].split(":"); + var host = cut[0]; + var cut2 = cut[1].split(";"); + var port = cut2[0]; + var db = cut2[1].split("database=")[1]; + var user = cut2[2].split("user=")[1]; + var password = cut2[3].split("password=")[1]; + } else { + //mysql + var splitHost = url[1].split(":"); //[host] : [3306/coeus?user=user&password=pass] + var host = splitHost[0]; + var splitPort = splitHost[1].split("/"); // [3306] / [coeus?user=user&password=pass] + var port = splitPort[0]; + var splitDB = splitPort[1].split("?");// [coeus] ? [user=user&password=pass] + var db = splitDB[0]; + var user = splitDB[1].split("&")[0].split("=")[1]; + var password = splitDB[1].split("&")[1].split("=")[1]; + } + + } catch (e) { + //ignore errors + } + + $(driverEndpoint).val(driver); + $(hostEndpoint).val(host); + $(dbEndpoint).val(db); + $(portEndpoint).val(port); + $(userEndpoint).val(user); + $(passwordEndpoint).val(password); + } + + } else { + $(sqlEnpointForm).addClass('hide'); + $(enpointForm).removeClass('hide'); + } + + if (publisher === "csv") { + $(queryForm).addClass('hide'); + $(csvQueryForm).removeClass('hide'); + + query = $(query).val(); + + if (query !== "") { + var q = query.split("|"); + + $(csvQueryDelimiter).val(q[1]); + $(csvQueryHeaderSkip).val(q[0]); + } else { + $(csvQueryHeaderSkip).val("1"); + refreshQuery(); + } + + } + else { + $(csvQueryForm).addClass('hide'); + $(queryForm).removeClass('hide'); + } +} + +/** + * Called when user change endpoint in the modal Resource + * @param {type} mode + * @returns {undefined} + */ +function refreshEnpoint(mode) { + + if (mode === 'edit') { + var portEndpoint = '#editPortEndpoint'; + var userEndpoint = '#editUserEndpoint'; + var passwordEndpoint = '#editPasswordEndpoint'; + var driverEndpoint = '#editDriverEndpoint'; + var hostEndpoint = '#editHostEndpoint'; + var dbEndpoint = '#editDbEndpoint'; + var endpoint = '#editEndpoint'; + } else { + var portEndpoint = '#portEndpoint'; + var userEndpoint = '#userEndpoint'; + var passwordEndpoint = '#passwordEndpoint'; + var driverEndpoint = '#driverEndpoint'; + var hostEndpoint = '#hostEndpoint'; + var dbEndpoint = '#dbEndpoint'; + var endpoint = '#endpoint'; + } + + if ($(driverEndpoint).val() === "sqlserver") { + var port = $(portEndpoint).val(); + if (port !== "") + port = ":" + port; + var user = $(userEndpoint).val(); + if (user !== "") + user = ";user=" + user; + var password = $(passwordEndpoint).val(); + if (password !== "") + password = ";password=" + password; + var endpointFinal = "jdbc:" + $(driverEndpoint).val() + "://" + $(hostEndpoint).val() + port + ";database=" + $(dbEndpoint).val() + user + password; + } else { + var port = $(portEndpoint).val(); + if (port !== "") + port = ":" + port; + var user = $(userEndpoint).val(); + if (user !== "") + user = "user=" + user; + var password = $(passwordEndpoint).val(); + if (password !== "") + password = "password=" + password; + var endpointFinal = "jdbc:" + $(driverEndpoint).val() + "://" + $(hostEndpoint).val() + port + "/" + $(dbEndpoint).val() + "?" + user + "&" + password; + } + $(endpoint).val(endpointFinal); +} + +/** + * Called when user change query in the modal Resource + * @param {type} mode + * @returns {undefined} + */ +function refreshQuery(mode) { + if (mode === 'edit') { + var delimiter = $('#editCsvQueryDelimiter').val(); + var header = $('#editCsvQueryHeaderSkip').val(); + $('#editQuery').val(header + "|" + delimiter); + } else { + var delimiter = $('#csvQueryDelimiter').val(); + var header = $('#csvQueryHeaderSkip').val(); + $('#query').val(header + "|" + delimiter); + + } +} +/** + * Called before the edit of a Resource + * @param {type} individual + * @returns {undefined} + */ +function prepareResourceEdit(individual) { + //reset values + $('#editResourceResult').html(""); + document.getElementById('editResourceURI').innerHTML = individual; + //CLEAN THE INPUT FIELDS + $('#editResourceTitle').val(""); + $('#editResourceLabel').val(""); + $('#editResourceComment').val(""); + $('#editMethod').val(""); + $('#editPublisher').val(""); + $('#editEndpoint').val(""); + $('#editQuery').val(""); + $('#editOrder').val(""); + $('#editExtends').val(""); + $('#built').prop('checked', false); + + //CLEAN ALSO OLD VALUES IN THE STATIC FIELD + $('#oldTitle').val(""); + $('#oldLabel').val(""); + $('#oldComment').val(""); + $('#oldMethod').val(""); + $('#oldPublisher').val(""); + $('#oldEndpoint').val(""); + $('#oldQuery').val(""); + $('#oldOrder').val(""); + $('#oldExtends').val(""); + $('#oldBuilt').val("false"); + + var q = "SELECT ?concept ?c {?concep coeus:hasResource " + individual + " . ?entity coeus:isEntityOf ?concep . ?seed coeus:includes ?entity . ?concept coeus:hasEntity ?ent . ?ent coeus:isIncludedIn ?seed . ?concept dc:title ?c}"; + queryToResult(q, fillConceptsExtension); + var q = "SELECT ?title ?label ?comment ?method ?publisher ?endpoint ?query ?order ?extends ?built {" + individual + " dc:title ?title . " + individual + " rdfs:label ?label . " + individual + " rdfs:comment ?comment . " + individual + " coeus:method ?method . " + individual + " dc:publisher ?publisher . " + individual + " coeus:endpoint ?endpoint . " + individual + " coeus:query ?query . " + individual + " coeus:order ?order . " + individual + " coeus:extends ?extends . OPTIONAL{" + individual + " coeus:built ?built } }"; + queryToResult(q, fillResourceEdit); + +} +function fillResourceEdit(result) { + console.log(result); + try + { + //PUT VALUES IN THE INPUT FIELD + $('#editResourceTitle').val(result[0].title.value); + $('#editResourceLabel').val(result[0].label.value); + $('#editResourceComment').val(result[0].comment.value); + $('#editMethod').val(result[0].method.value); + $('#editPublisher option:contains(' + result[0].publisher.value + ')').prop({selected: true}); + $('#editEndpoint').val(result[0].endpoint.value); + $('#editQuery').val(result[0].query.value); + $('#editOrder').val(result[0].order.value); + $('#editExtends option:contains(' + splitURIPrefix(result[0].extends.value).value + ')').prop({selected: true}); + if (result[0].built !== undefined && result[0].built.value === "true") + $('#built').prop('checked', true); + else + $('#built').prop('checked', false); + } + catch (err) + { + $('#editResourceResult').append(generateHtmlMessage("Error!", "Some fields do not exist." + err, "alert-error")); + } + //PUT OLD VALUES IN THE STATIC FIELD + $('#oldResourceTitle').val($('#editResourceTitle').val()); + $('#oldResourceLabel').val($('#editResourceLabel').val()); + $('#oldResourceComment').val($('#editResourceComment').val()); + $('#oldMethod').val($('#editMethod').val()); + $('#oldPublisher').val($('#editPublisher').val()); + $('#oldEndpoint').val($('#editEndpoint').val()); + $('#oldQuery').val($('#editQuery').val()); + $('#oldOrder').val($('#editOrder').val()); + $('#oldExtends').val(splitURIPrefix(result[0].extends.value).value); + $('#oldBuilt').val($('#built').is(':checked')); + //change publisher according to the result + publisherChange('edit'); + +} + +/** + * Called when a Resource is edited / updated + * @returns {undefined} + */ +function editResource() { + var individual = $('#editResourceURI').html(); + var urlUpdate = "../../api/" + getApiKey() + "/update/"; + var urlDelete = "../../api/" + getApiKey() + "/delete/"; + var urlWrite = "../../api/" + getApiKey() + "/write/"; + var url; + var array = new Array(); + + if ($('#oldResourceLabel').val() !== $('#editResourceLabel').val()) { + url = urlUpdate + individual + "/" + "rdfs:label" + "/xsd:string:" + $('#oldResourceLabel').val() + ",xsd:string:" + $('#editResourceLabel').val(); + array.push(url); + } + if ($('#oldResourceTitle').val() !== $('#editResourceTitle').val()) { + url = urlUpdate + individual + "/" + "dc:title" + "/xsd:string:" + $('#oldResourceTitle').val() + ",xsd:string:" + $('#editResourceTitle').val(); + array.push(url); + } + if ($('#oldResourceComment').val() !== $('#editResourceComment').val()) { + url = urlUpdate + individual + "/" + "rdfs:comment" + "/xsd:string:" + $('#oldResourceComment').val() + ",xsd:string:" + $('#editResourceComment').val(); + array.push(url); + } + if ($('#oldMethod').val() !== $('#editMethod').val()) { + url = urlUpdate + individual + "/" + "coeus:method" + "/xsd:string:" + $('#oldMethod').val() + ",xsd:string:" + $('#editMethod').val(); + array.push(url); + } + if ($('#oldEndpoint').val() !== $('#editEndpoint').val()) { + url = urlUpdate + individual + "/" + "coeus:endpoint" + "/xsd:string:" + encodeBars($('#oldEndpoint').val()) + ",xsd:string:" + encodeBars($('#editEndpoint').val()); + array.push(url); + } + if ($('#oldQuery').val() !== $('#editQuery').val()) { + url = urlUpdate + individual + "/" + "coeus:query" + "/xsd:string:" + encodeBars($('#oldQuery').val()) + ",xsd:string:" + encodeBars($('#editQuery').val()); + array.push(url); + } + if ($('#oldOrder').val() !== $('#editOrder').val()) { + url = urlUpdate + individual + "/" + "coeus:order" + "/xsd:string:" + $('#oldOrder').val() + ",xsd:string:" + $('#editOrder').val(); + array.push(url); + } + if ($('#oldExtends').val() !== $('#editExtends').val()) { + url = urlUpdate + individual + "/" + "coeus:extends" + "/coeus:" + $('#oldExtends').val() + ",coeus:" + $('#editExtends').val(); + array.push(url); + url = urlDelete + "coeus:" + $('#oldExtends').val() + "/" + "coeus:isExtendedBy" + "/" + individual; + array.push(url); + url = urlWrite + "coeus:" + $('#editExtends').val() + "/" + "coeus:isExtendedBy" + "/" + individual; + array.push(url); + } + if ($('#oldPublisher').val() !== $('#editPublisher').val()) { + url = urlUpdate + individual + "/" + "dc:publisher" + "/xsd:string:" + $('#oldPublisher').val() + ",xsd:string:" + $('#editPublisher').val(); + updatePublisherOnSelectores(urlUpdate, individual, $('#oldPublisher').val(), $('#editPublisher').val()); + array.push(url); + } + if ($('#oldBuilt').val().toString() !== $('#built').is(':checked').toString()) { + url = urlUpdate + individual + "/" + "coeus:built" + "/xsd:boolean:" + $('#oldBuilt').val() + ",xsd:boolean:" + $('#built').is(':checked'); + array.push(url); + } + + timer = setTimeout(function() { + $('#closeEditResourceModal').click(); + refresh(); + }, delay); + + array.forEach(function(url) { + callURL(url, showResult.bind(this, "#editResourceResult", url), showError.bind(this, "#editResourceResult", url)); + }); +} +/** + * Update all selectors type (csv,xml,sql,..) of the resource when the resource publisher change. + * @param {type} urlUpdate + * @param {type} res + * @param {type} oldPublisher + * @param {type} newPublisher + * @returns {undefined} + */ +function updatePublisherOnSelectores(urlUpdate, res, oldPublisher, newPublisher) { + var q = "SELECT * {" + res + " coeus:loadsFrom ?selector}"; + queryToResult(q, function(result) { + for (var r in result) { + var res = splitURIPrefix(result[r].selector.value); + var url = urlUpdate + "coeus:" + res.value + "/rdf:type/coeus:" + oldPublisher.toUpperCase() + ",coeus:" + newPublisher.toUpperCase(); + callURL(url, showResult.bind(this, "#editResourceResult", url), showError.bind(this, "#editResourceResult", url)); + } + }); +} + +/** + * End of the code used to manage the modals (Resource) + */ diff --git a/src/main/webapp/assets/js/typeahead.js b/src/main/webapp/assets/js/typeahead.js new file mode 100644 index 0000000..9365bd6 --- /dev/null +++ b/src/main/webapp/assets/js/typeahead.js @@ -0,0 +1,1139 @@ +/*! + * typeahead.js 0.9.3 + * https://github.com/twitter/typeahead + * Copyright 2013 Twitter, Inc. and other contributors; Licensed MIT + */ + +(function($) { + var VERSION = "0.9.3"; + var utils = { + isMsie: function() { + var match = /(msie) ([\w.]+)/i.exec(navigator.userAgent); + return match ? parseInt(match[2], 10) : false; + }, + isBlankString: function(str) { + return !str || /^\s*$/.test(str); + }, + escapeRegExChars: function(str) { + return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); + }, + isString: function(obj) { + return typeof obj === "string"; + }, + isNumber: function(obj) { + return typeof obj === "number"; + }, + isArray: $.isArray, + isFunction: $.isFunction, + isObject: $.isPlainObject, + isUndefined: function(obj) { + return typeof obj === "undefined"; + }, + bind: $.proxy, + bindAll: function(obj) { + var val; + for (var key in obj) { + $.isFunction(val = obj[key]) && (obj[key] = $.proxy(val, obj)); + } + }, + indexOf: function(haystack, needle) { + for (var i = 0; i < haystack.length; i++) { + if (haystack[i] === needle) { + return i; + } + } + return -1; + }, + each: $.each, + map: $.map, + filter: $.grep, + every: function(obj, test) { + var result = true; + if (!obj) { + return result; + } + $.each(obj, function(key, val) { + if (!(result = test.call(null, val, key, obj))) { + return false; + } + }); + return !!result; + }, + some: function(obj, test) { + var result = false; + if (!obj) { + return result; + } + $.each(obj, function(key, val) { + if (result = test.call(null, val, key, obj)) { + return false; + } + }); + return !!result; + }, + mixin: $.extend, + getUniqueId: function() { + var counter = 0; + return function() { + return counter++; + }; + }(), + defer: function(fn) { + setTimeout(fn, 0); + }, + debounce: function(func, wait, immediate) { + var timeout, result; + return function() { + var context = this, args = arguments, later, callNow; + later = function() { + timeout = null; + if (!immediate) { + result = func.apply(context, args); + } + }; + callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) { + result = func.apply(context, args); + } + return result; + }; + }, + throttle: function(func, wait) { + var context, args, timeout, result, previous, later; + previous = 0; + later = function() { + previous = new Date(); + timeout = null; + result = func.apply(context, args); + }; + return function() { + var now = new Date(), remaining = wait - (now - previous); + context = this; + args = arguments; + if (remaining <= 0) { + clearTimeout(timeout); + timeout = null; + previous = now; + result = func.apply(context, args); + } else if (!timeout) { + timeout = setTimeout(later, remaining); + } + return result; + }; + }, + tokenizeQuery: function(str) { + return $.trim(str).toLowerCase().split(/[\s]+/); + }, + tokenizeText: function(str) { + return $.trim(str).toLowerCase().split(/[\s\-_]+/); + }, + getProtocol: function() { + return location.protocol; + }, + noop: function() {} + }; + var EventTarget = function() { + var eventSplitter = /\s+/; + return { + on: function(events, callback) { + var event; + if (!callback) { + return this; + } + this._callbacks = this._callbacks || {}; + events = events.split(eventSplitter); + while (event = events.shift()) { + this._callbacks[event] = this._callbacks[event] || []; + this._callbacks[event].push(callback); + } + return this; + }, + trigger: function(events, data) { + var event, callbacks; + if (!this._callbacks) { + return this; + } + events = events.split(eventSplitter); + while (event = events.shift()) { + if (callbacks = this._callbacks[event]) { + for (var i = 0; i < callbacks.length; i += 1) { + callbacks[i].call(this, { + type: event, + data: data + }); + } + } + } + return this; + } + }; + }(); + var EventBus = function() { + var namespace = "typeahead:"; + function EventBus(o) { + if (!o || !o.el) { + $.error("EventBus initialized without el"); + } + this.$el = $(o.el); + } + utils.mixin(EventBus.prototype, { + trigger: function(type) { + var args = [].slice.call(arguments, 1); + this.$el.trigger(namespace + type, args); + } + }); + return EventBus; + }(); + var PersistentStorage = function() { + var ls, methods; + try { + ls = window.localStorage; + ls.setItem("~~~", "!"); + ls.removeItem("~~~"); + } catch (err) { + ls = null; + } + function PersistentStorage(namespace) { + this.prefix = [ "__", namespace, "__" ].join(""); + this.ttlKey = "__ttl__"; + this.keyMatcher = new RegExp("^" + this.prefix); + } + if (ls && window.JSON) { + methods = { + _prefix: function(key) { + return this.prefix + key; + }, + _ttlKey: function(key) { + return this._prefix(key) + this.ttlKey; + }, + get: function(key) { + if (this.isExpired(key)) { + this.remove(key); + } + return decode(ls.getItem(this._prefix(key))); + }, + set: function(key, val, ttl) { + if (utils.isNumber(ttl)) { + ls.setItem(this._ttlKey(key), encode(now() + ttl)); + } else { + ls.removeItem(this._ttlKey(key)); + } + return ls.setItem(this._prefix(key), encode(val)); + }, + remove: function(key) { + ls.removeItem(this._ttlKey(key)); + ls.removeItem(this._prefix(key)); + return this; + }, + clear: function() { + var i, key, keys = [], len = ls.length; + for (i = 0; i < len; i++) { + if ((key = ls.key(i)).match(this.keyMatcher)) { + keys.push(key.replace(this.keyMatcher, "")); + } + } + for (i = keys.length; i--; ) { + this.remove(keys[i]); + } + return this; + }, + isExpired: function(key) { + var ttl = decode(ls.getItem(this._ttlKey(key))); + return utils.isNumber(ttl) && now() > ttl ? true : false; + } + }; + } else { + methods = { + get: utils.noop, + set: utils.noop, + remove: utils.noop, + clear: utils.noop, + isExpired: utils.noop + }; + } + utils.mixin(PersistentStorage.prototype, methods); + return PersistentStorage; + function now() { + return new Date().getTime(); + } + function encode(val) { + return JSON.stringify(utils.isUndefined(val) ? null : val); + } + function decode(val) { + return JSON.parse(val); + } + }(); + var RequestCache = function() { + function RequestCache(o) { + utils.bindAll(this); + o = o || {}; + this.sizeLimit = o.sizeLimit || 10; + this.cache = {}; + this.cachedKeysByAge = []; + } + utils.mixin(RequestCache.prototype, { + get: function(url) { + return this.cache[url]; + }, + set: function(url, resp) { + var requestToEvict; + if (this.cachedKeysByAge.length === this.sizeLimit) { + requestToEvict = this.cachedKeysByAge.shift(); + delete this.cache[requestToEvict]; + } + this.cache[url] = resp; + this.cachedKeysByAge.push(url); + } + }); + return RequestCache; + }(); + var Transport = function() { + var pendingRequestsCount = 0, pendingRequests = {}, maxPendingRequests, requestCache; + function Transport(o) { + utils.bindAll(this); + o = utils.isString(o) ? { + url: o + } : o; + requestCache = requestCache || new RequestCache(); + maxPendingRequests = utils.isNumber(o.maxParallelRequests) ? o.maxParallelRequests : maxPendingRequests || 6; + this.url = o.url; + this.wildcard = o.wildcard || "%QUERY"; + this.filter = o.filter; + this.replace = o.replace; + this.ajaxSettings = { + type: "get", + cache: o.cache, + timeout: o.timeout, + dataType: o.dataType || "json", + beforeSend: o.beforeSend + }; + this._get = (/^throttle$/i.test(o.rateLimitFn) ? utils.throttle : utils.debounce)(this._get, o.rateLimitWait || 300); + } + utils.mixin(Transport.prototype, { + _get: function(url, cb) { + var that = this; + if (belowPendingRequestsThreshold()) { + this._sendRequest(url).done(done); + } else { + this.onDeckRequestArgs = [].slice.call(arguments, 0); + } + function done(resp) { + var data = that.filter ? that.filter(resp) : resp; + cb && cb(data); + requestCache.set(url, resp); + } + }, + _sendRequest: function(url) { + var that = this, jqXhr = pendingRequests[url]; + if (!jqXhr) { + incrementPendingRequests(); + jqXhr = pendingRequests[url] = $.ajax(url, this.ajaxSettings).always(always); + } + return jqXhr; + function always() { + decrementPendingRequests(); + pendingRequests[url] = null; + if (that.onDeckRequestArgs) { + that._get.apply(that, that.onDeckRequestArgs); + that.onDeckRequestArgs = null; + } + } + }, + get: function(query, cb) { + var that = this, encodedQuery = encodeURIComponent(query || ""), url, resp; + cb = cb || utils.noop; + url = this.replace ? this.replace(this.url, encodedQuery) : this.url.replace(this.wildcard, encodedQuery); + if (resp = requestCache.get(url)) { + utils.defer(function() { + cb(that.filter ? that.filter(resp) : resp); + }); + } else { + this._get(url, cb); + } + return !!resp; + } + }); + return Transport; + function incrementPendingRequests() { + pendingRequestsCount++; + } + function decrementPendingRequests() { + pendingRequestsCount--; + } + function belowPendingRequestsThreshold() { + return pendingRequestsCount < maxPendingRequests; + } + }(); + var Dataset = function() { + var keys = { + thumbprint: "thumbprint", + protocol: "protocol", + itemHash: "itemHash", + adjacencyList: "adjacencyList" + }; + function Dataset(o) { + utils.bindAll(this); + if (utils.isString(o.template) && !o.engine) { + $.error("no template engine specified"); + } + if (!o.local && !o.prefetch && !o.remote) { + $.error("one of local, prefetch, or remote is required"); + } + this.name = o.name || utils.getUniqueId(); + this.limit = o.limit || 5; + this.minLength = o.minLength || 1; + this.header = o.header; + this.footer = o.footer; + this.valueKey = o.valueKey || "value"; + this.template = compileTemplate(o.template, o.engine, this.valueKey); + this.local = o.local; + this.prefetch = o.prefetch; + this.remote = o.remote; + this.itemHash = {}; + this.adjacencyList = {}; + this.storage = o.name ? new PersistentStorage(o.name) : null; + } + utils.mixin(Dataset.prototype, { + _processLocalData: function(data) { + this._mergeProcessedData(this._processData(data)); + }, + _loadPrefetchData: function(o) { + var that = this, thumbprint = VERSION + (o.thumbprint || ""), storedThumbprint, storedProtocol, storedItemHash, storedAdjacencyList, isExpired, deferred; + if (this.storage) { + storedThumbprint = this.storage.get(keys.thumbprint); + storedProtocol = this.storage.get(keys.protocol); + storedItemHash = this.storage.get(keys.itemHash); + storedAdjacencyList = this.storage.get(keys.adjacencyList); + } + isExpired = storedThumbprint !== thumbprint || storedProtocol !== utils.getProtocol(); + o = utils.isString(o) ? { + url: o + } : o; + o.ttl = utils.isNumber(o.ttl) ? o.ttl : 24 * 60 * 60 * 1e3; + if (storedItemHash && storedAdjacencyList && !isExpired) { + this._mergeProcessedData({ + itemHash: storedItemHash, + adjacencyList: storedAdjacencyList + }); + deferred = $.Deferred().resolve(); + } else { + deferred = $.getJSON(o.url).done(processPrefetchData); + } + return deferred; + function processPrefetchData(data) { + var filteredData = o.filter ? o.filter(data) : data, processedData = that._processData(filteredData), itemHash = processedData.itemHash, adjacencyList = processedData.adjacencyList; + if (that.storage) { + that.storage.set(keys.itemHash, itemHash, o.ttl); + that.storage.set(keys.adjacencyList, adjacencyList, o.ttl); + that.storage.set(keys.thumbprint, thumbprint, o.ttl); + that.storage.set(keys.protocol, utils.getProtocol(), o.ttl); + } + that._mergeProcessedData(processedData); + } + }, + _transformDatum: function(datum) { + var value = utils.isString(datum) ? datum : datum[this.valueKey], tokens = datum.tokens || utils.tokenizeText(value), item = { + value: value, + tokens: tokens + }; + if (utils.isString(datum)) { + item.datum = {}; + item.datum[this.valueKey] = datum; + } else { + item.datum = datum; + } + item.tokens = utils.filter(item.tokens, function(token) { + return !utils.isBlankString(token); + }); + item.tokens = utils.map(item.tokens, function(token) { + return token.toLowerCase(); + }); + return item; + }, + _processData: function(data) { + var that = this, itemHash = {}, adjacencyList = {}; + utils.each(data, function(i, datum) { + var item = that._transformDatum(datum), id = utils.getUniqueId(item.value); + itemHash[id] = item; + utils.each(item.tokens, function(i, token) { + var character = token.charAt(0), adjacency = adjacencyList[character] || (adjacencyList[character] = [ id ]); + !~utils.indexOf(adjacency, id) && adjacency.push(id); + }); + }); + return { + itemHash: itemHash, + adjacencyList: adjacencyList + }; + }, + _mergeProcessedData: function(processedData) { + var that = this; + utils.mixin(this.itemHash, processedData.itemHash); + utils.each(processedData.adjacencyList, function(character, adjacency) { + var masterAdjacency = that.adjacencyList[character]; + that.adjacencyList[character] = masterAdjacency ? masterAdjacency.concat(adjacency) : adjacency; + }); + }, + _getLocalSuggestions: function(terms) { + var that = this, firstChars = [], lists = [], shortestList, suggestions = []; + utils.each(terms, function(i, term) { + var firstChar = term.charAt(0); + !~utils.indexOf(firstChars, firstChar) && firstChars.push(firstChar); + }); + utils.each(firstChars, function(i, firstChar) { + var list = that.adjacencyList[firstChar]; + if (!list) { + return false; + } + lists.push(list); + if (!shortestList || list.length < shortestList.length) { + shortestList = list; + } + }); + if (lists.length < firstChars.length) { + return []; + } + utils.each(shortestList, function(i, id) { + var item = that.itemHash[id], isCandidate, isMatch; + isCandidate = utils.every(lists, function(list) { + return ~utils.indexOf(list, id); + }); + isMatch = isCandidate && utils.every(terms, function(term) { + return utils.some(item.tokens, function(token) { + return token.indexOf(term) === 0; + }); + }); + isMatch && suggestions.push(item); + }); + return suggestions; + }, + initialize: function() { + var deferred; + this.local && this._processLocalData(this.local); + this.transport = this.remote ? new Transport(this.remote) : null; + deferred = this.prefetch ? this._loadPrefetchData(this.prefetch) : $.Deferred().resolve(); + this.local = this.prefetch = this.remote = null; + this.initialize = function() { + return deferred; + }; + return deferred; + }, + getSuggestions: function(query, cb) { + var that = this, terms, suggestions, cacheHit = false; + if (query.length < this.minLength) { + return; + } + terms = utils.tokenizeQuery(query); + suggestions = this._getLocalSuggestions(terms).slice(0, this.limit); + if (suggestions.length < this.limit && this.transport) { + cacheHit = this.transport.get(query, processRemoteData); + } + !cacheHit && cb && cb(suggestions); + function processRemoteData(data) { + suggestions = suggestions.slice(0); + utils.each(data, function(i, datum) { + var item = that._transformDatum(datum), isDuplicate; + isDuplicate = utils.some(suggestions, function(suggestion) { + return item.value === suggestion.value; + }); + !isDuplicate && suggestions.push(item); + return suggestions.length < that.limit; + }); + cb && cb(suggestions); + } + } + }); + return Dataset; + function compileTemplate(template, engine, valueKey) { + var renderFn, compiledTemplate; + if (utils.isFunction(template)) { + renderFn = template; + } else if (utils.isString(template)) { + compiledTemplate = engine.compile(template); + renderFn = utils.bind(compiledTemplate.render, compiledTemplate); + } else { + renderFn = function(context) { + return "

    " + context[valueKey] + "

    "; + }; + } + return renderFn; + } + }(); + var InputView = function() { + function InputView(o) { + var that = this; + utils.bindAll(this); + this.specialKeyCodeMap = { + 9: "tab", + 27: "esc", + 37: "left", + 39: "right", + 13: "enter", + 38: "up", + 40: "down" + }; + this.$hint = $(o.hint); + this.$input = $(o.input).on("blur.tt", this._handleBlur).on("focus.tt", this._handleFocus).on("keydown.tt", this._handleSpecialKeyEvent); + if (!utils.isMsie()) { + this.$input.on("input.tt", this._compareQueryToInputValue); + } else { + this.$input.on("keydown.tt keypress.tt cut.tt paste.tt", function($e) { + if (that.specialKeyCodeMap[$e.which || $e.keyCode]) { + return; + } + utils.defer(that._compareQueryToInputValue); + }); + } + this.query = this.$input.val(); + this.$overflowHelper = buildOverflowHelper(this.$input); + } + utils.mixin(InputView.prototype, EventTarget, { + _handleFocus: function() { + this.trigger("focused"); + }, + _handleBlur: function() { + this.trigger("blured"); + }, + _handleSpecialKeyEvent: function($e) { + var keyName = this.specialKeyCodeMap[$e.which || $e.keyCode]; + keyName && this.trigger(keyName + "Keyed", $e); + }, + _compareQueryToInputValue: function() { + var inputValue = this.getInputValue(), isSameQuery = compareQueries(this.query, inputValue), isSameQueryExceptWhitespace = isSameQuery ? this.query.length !== inputValue.length : false; + if (isSameQueryExceptWhitespace) { + this.trigger("whitespaceChanged", { + value: this.query + }); + } else if (!isSameQuery) { + this.trigger("queryChanged", { + value: this.query = inputValue + }); + } + }, + destroy: function() { + this.$hint.off(".tt"); + this.$input.off(".tt"); + this.$hint = this.$input = this.$overflowHelper = null; + }, + focus: function() { + this.$input.focus(); + }, + blur: function() { + this.$input.blur(); + }, + getQuery: function() { + return this.query; + }, + setQuery: function(query) { + this.query = query; + }, + getInputValue: function() { + return this.$input.val(); + }, + setInputValue: function(value, silent) { + this.$input.val(value); + !silent && this._compareQueryToInputValue(); + }, + getHintValue: function() { + return this.$hint.val(); + }, + setHintValue: function(value) { + this.$hint.val(value); + }, + getLanguageDirection: function() { + return (this.$input.css("direction") || "ltr").toLowerCase(); + }, + isOverflow: function() { + this.$overflowHelper.text(this.getInputValue()); + return this.$overflowHelper.width() > this.$input.width(); + }, + isCursorAtEnd: function() { + var valueLength = this.$input.val().length, selectionStart = this.$input[0].selectionStart, range; + if (utils.isNumber(selectionStart)) { + return selectionStart === valueLength; + } else if (document.selection) { + range = document.selection.createRange(); + range.moveStart("character", -valueLength); + return valueLength === range.text.length; + } + return true; + } + }); + return InputView; + function buildOverflowHelper($input) { + return $("").css({ + position: "absolute", + left: "-9999px", + visibility: "hidden", + whiteSpace: "nowrap", + fontFamily: $input.css("font-family"), + fontSize: $input.css("font-size"), + fontStyle: $input.css("font-style"), + fontVariant: $input.css("font-variant"), + fontWeight: $input.css("font-weight"), + wordSpacing: $input.css("word-spacing"), + letterSpacing: $input.css("letter-spacing"), + textIndent: $input.css("text-indent"), + textRendering: $input.css("text-rendering"), + textTransform: $input.css("text-transform") + }).insertAfter($input); + } + function compareQueries(a, b) { + a = (a || "").replace(/^\s*/g, "").replace(/\s{2,}/g, " "); + b = (b || "").replace(/^\s*/g, "").replace(/\s{2,}/g, " "); + return a === b; + } + }(); + var DropdownView = function() { + var html = { + suggestionsList: '' + }, css = { + suggestionsList: { + display: "block" + }, + suggestion: { + whiteSpace: "nowrap", + cursor: "pointer" + }, + suggestionChild: { + whiteSpace: "normal" + } + }; + function DropdownView(o) { + utils.bindAll(this); + this.isOpen = false; + this.isEmpty = true; + this.isMouseOverDropdown = false; + this.$menu = $(o.menu).on("mouseenter.tt", this._handleMouseenter).on("mouseleave.tt", this._handleMouseleave).on("click.tt", ".tt-suggestion", this._handleSelection).on("mouseover.tt", ".tt-suggestion", this._handleMouseover); + } + utils.mixin(DropdownView.prototype, EventTarget, { + _handleMouseenter: function() { + this.isMouseOverDropdown = true; + }, + _handleMouseleave: function() { + this.isMouseOverDropdown = false; + }, + _handleMouseover: function($e) { + var $suggestion = $($e.currentTarget); + this._getSuggestions().removeClass("tt-is-under-cursor"); + $suggestion.addClass("tt-is-under-cursor"); + }, + _handleSelection: function($e) { + var $suggestion = $($e.currentTarget); + this.trigger("suggestionSelected", extractSuggestion($suggestion)); + }, + _show: function() { + this.$menu.css("display", "block"); + }, + _hide: function() { + this.$menu.hide(); + }, + _moveCursor: function(increment) { + var $suggestions, $cur, nextIndex, $underCursor; + if (!this.isVisible()) { + return; + } + $suggestions = this._getSuggestions(); + $cur = $suggestions.filter(".tt-is-under-cursor"); + $cur.removeClass("tt-is-under-cursor"); + nextIndex = $suggestions.index($cur) + increment; + nextIndex = (nextIndex + 1) % ($suggestions.length + 1) - 1; + if (nextIndex === -1) { + this.trigger("cursorRemoved"); + return; + } else if (nextIndex < -1) { + nextIndex = $suggestions.length - 1; + } + $underCursor = $suggestions.eq(nextIndex).addClass("tt-is-under-cursor"); + this._ensureVisibility($underCursor); + this.trigger("cursorMoved", extractSuggestion($underCursor)); + }, + _getSuggestions: function() { + return this.$menu.find(".tt-suggestions > .tt-suggestion"); + }, + _ensureVisibility: function($el) { + var menuHeight = this.$menu.height() + parseInt(this.$menu.css("paddingTop"), 10) + parseInt(this.$menu.css("paddingBottom"), 10), menuScrollTop = this.$menu.scrollTop(), elTop = $el.position().top, elBottom = elTop + $el.outerHeight(true); + if (elTop < 0) { + this.$menu.scrollTop(menuScrollTop + elTop); + } else if (menuHeight < elBottom) { + this.$menu.scrollTop(menuScrollTop + (elBottom - menuHeight)); + } + }, + destroy: function() { + this.$menu.off(".tt"); + this.$menu = null; + }, + isVisible: function() { + return this.isOpen && !this.isEmpty; + }, + closeUnlessMouseIsOverDropdown: function() { + if (!this.isMouseOverDropdown) { + this.close(); + } + }, + close: function() { + if (this.isOpen) { + this.isOpen = false; + this.isMouseOverDropdown = false; + this._hide(); + this.$menu.find(".tt-suggestions > .tt-suggestion").removeClass("tt-is-under-cursor"); + this.trigger("closed"); + } + }, + open: function() { + if (!this.isOpen) { + this.isOpen = true; + !this.isEmpty && this._show(); + this.trigger("opened"); + } + }, + setLanguageDirection: function(dir) { + var ltrCss = { + left: "0", + right: "auto" + }, rtlCss = { + left: "auto", + right: " 0" + }; + dir === "ltr" ? this.$menu.css(ltrCss) : this.$menu.css(rtlCss); + }, + moveCursorUp: function() { + this._moveCursor(-1); + }, + moveCursorDown: function() { + this._moveCursor(+1); + }, + getSuggestionUnderCursor: function() { + var $suggestion = this._getSuggestions().filter(".tt-is-under-cursor").first(); + return $suggestion.length > 0 ? extractSuggestion($suggestion) : null; + }, + getFirstSuggestion: function() { + var $suggestion = this._getSuggestions().first(); + return $suggestion.length > 0 ? extractSuggestion($suggestion) : null; + }, + renderSuggestions: function(dataset, suggestions) { + var datasetClassName = "tt-dataset-" + dataset.name, wrapper = '
    %body
    ', compiledHtml, $suggestionsList, $dataset = this.$menu.find("." + datasetClassName), elBuilder, fragment, $el; + if ($dataset.length === 0) { + $suggestionsList = $(html.suggestionsList).css(css.suggestionsList); + $dataset = $("
    ").addClass(datasetClassName).append(dataset.header).append($suggestionsList).append(dataset.footer).appendTo(this.$menu); + } + if (suggestions.length > 0) { + this.isEmpty = false; + this.isOpen && this._show(); + elBuilder = document.createElement("div"); + fragment = document.createDocumentFragment(); + utils.each(suggestions, function(i, suggestion) { + suggestion.dataset = dataset.name; + compiledHtml = dataset.template(suggestion.datum); + elBuilder.innerHTML = wrapper.replace("%body", compiledHtml); + $el = $(elBuilder.firstChild).css(css.suggestion).data("suggestion", suggestion); + $el.children().each(function() { + $(this).css(css.suggestionChild); + }); + fragment.appendChild($el[0]); + }); + $dataset.show().find(".tt-suggestions").html(fragment); + } else { + this.clearSuggestions(dataset.name); + } + this.trigger("suggestionsRendered"); + }, + clearSuggestions: function(datasetName) { + var $datasets = datasetName ? this.$menu.find(".tt-dataset-" + datasetName) : this.$menu.find('[class^="tt-dataset-"]'), $suggestions = $datasets.find(".tt-suggestions"); + $datasets.hide(); + $suggestions.empty(); + if (this._getSuggestions().length === 0) { + this.isEmpty = true; + this._hide(); + } + } + }); + return DropdownView; + function extractSuggestion($el) { + return $el.data("suggestion"); + } + }(); + var TypeaheadView = function() { + var html = { + wrapper: '', + hint: '', + dropdown: '' + }, css = { + wrapper: { + position: "relative", + display: "inline-block" + }, + hint: { + position: "absolute", + top: "0", + left: "0", + borderColor: "transparent", + boxShadow: "none" + }, + query: { + position: "relative", + verticalAlign: "top", + backgroundColor: "transparent" + }, + dropdown: { + position: "absolute", + top: "100%", + left: "0", + zIndex: "100", + display: "none" + } + }; + if (utils.isMsie()) { + utils.mixin(css.query, { + backgroundImage: "url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)" + }); + } + if (utils.isMsie() && utils.isMsie() <= 7) { + utils.mixin(css.wrapper, { + display: "inline", + zoom: "1" + }); + utils.mixin(css.query, { + marginTop: "-1px" + }); + } + function TypeaheadView(o) { + var $menu, $input, $hint; + utils.bindAll(this); + this.$node = buildDomStructure(o.input); + this.datasets = o.datasets; + this.dir = null; + this.eventBus = o.eventBus; + $menu = this.$node.find(".tt-dropdown-menu"); + $input = this.$node.find(".tt-query"); + $hint = this.$node.find(".tt-hint"); + this.dropdownView = new DropdownView({ + menu: $menu + }).on("suggestionSelected", this._handleSelection).on("cursorMoved", this._clearHint).on("cursorMoved", this._setInputValueToSuggestionUnderCursor).on("cursorRemoved", this._setInputValueToQuery).on("cursorRemoved", this._updateHint).on("suggestionsRendered", this._updateHint).on("opened", this._updateHint).on("closed", this._clearHint).on("opened closed", this._propagateEvent); + this.inputView = new InputView({ + input: $input, + hint: $hint + }).on("focused", this._openDropdown).on("blured", this._closeDropdown).on("blured", this._setInputValueToQuery).on("enterKeyed tabKeyed", this._handleSelection).on("queryChanged", this._clearHint).on("queryChanged", this._clearSuggestions).on("queryChanged", this._getSuggestions).on("whitespaceChanged", this._updateHint).on("queryChanged whitespaceChanged", this._openDropdown).on("queryChanged whitespaceChanged", this._setLanguageDirection).on("escKeyed", this._closeDropdown).on("escKeyed", this._setInputValueToQuery).on("tabKeyed upKeyed downKeyed", this._managePreventDefault).on("upKeyed downKeyed", this._moveDropdownCursor).on("upKeyed downKeyed", this._openDropdown).on("tabKeyed leftKeyed rightKeyed", this._autocomplete); + } + utils.mixin(TypeaheadView.prototype, EventTarget, { + _managePreventDefault: function(e) { + var $e = e.data, hint, inputValue, preventDefault = false; + switch (e.type) { + case "tabKeyed": + hint = this.inputView.getHintValue(); + inputValue = this.inputView.getInputValue(); + preventDefault = hint && hint !== inputValue; + break; + + case "upKeyed": + case "downKeyed": + preventDefault = !$e.shiftKey && !$e.ctrlKey && !$e.metaKey; + break; + } + preventDefault && $e.preventDefault(); + }, + _setLanguageDirection: function() { + var dir = this.inputView.getLanguageDirection(); + if (dir !== this.dir) { + this.dir = dir; + this.$node.css("direction", dir); + this.dropdownView.setLanguageDirection(dir); + } + }, + _updateHint: function() { + var suggestion = this.dropdownView.getFirstSuggestion(), hint = suggestion ? suggestion.value : null, dropdownIsVisible = this.dropdownView.isVisible(), inputHasOverflow = this.inputView.isOverflow(), inputValue, query, escapedQuery, beginsWithQuery, match; + if (hint && dropdownIsVisible && !inputHasOverflow) { + inputValue = this.inputView.getInputValue(); + query = inputValue.replace(/\s{2,}/g, " ").replace(/^\s+/g, ""); + escapedQuery = utils.escapeRegExChars(query); + beginsWithQuery = new RegExp("^(?:" + escapedQuery + ")(.*$)", "i"); + match = beginsWithQuery.exec(hint); + this.inputView.setHintValue(inputValue + (match ? match[1] : "")); + } + }, + _clearHint: function() { + this.inputView.setHintValue(""); + }, + _clearSuggestions: function() { + this.dropdownView.clearSuggestions(); + }, + _setInputValueToQuery: function() { + this.inputView.setInputValue(this.inputView.getQuery()); + }, + _setInputValueToSuggestionUnderCursor: function(e) { + var suggestion = e.data; + this.inputView.setInputValue(suggestion.value, true); + }, + _openDropdown: function() { + this.dropdownView.open(); + }, + _closeDropdown: function(e) { + this.dropdownView[e.type === "blured" ? "closeUnlessMouseIsOverDropdown" : "close"](); + }, + _moveDropdownCursor: function(e) { + var $e = e.data; + if (!$e.shiftKey && !$e.ctrlKey && !$e.metaKey) { + this.dropdownView[e.type === "upKeyed" ? "moveCursorUp" : "moveCursorDown"](); + } + }, + _handleSelection: function(e) { + var byClick = e.type === "suggestionSelected", suggestion = byClick ? e.data : this.dropdownView.getSuggestionUnderCursor(); + if (suggestion) { + this.inputView.setInputValue(suggestion.value); + byClick ? this.inputView.focus() : e.data.preventDefault(); + byClick && utils.isMsie() ? utils.defer(this.dropdownView.close) : this.dropdownView.close(); + this.eventBus.trigger("selected", suggestion.datum, suggestion.dataset); + } + }, + _getSuggestions: function() { + var that = this, query = this.inputView.getQuery(); + if (utils.isBlankString(query)) { + return; + } + utils.each(this.datasets, function(i, dataset) { + dataset.getSuggestions(query, function(suggestions) { + if (query === that.inputView.getQuery()) { + that.dropdownView.renderSuggestions(dataset, suggestions); + } + }); + }); + }, + _autocomplete: function(e) { + var isCursorAtEnd, ignoreEvent, query, hint, suggestion; + if (e.type === "rightKeyed" || e.type === "leftKeyed") { + isCursorAtEnd = this.inputView.isCursorAtEnd(); + ignoreEvent = this.inputView.getLanguageDirection() === "ltr" ? e.type === "leftKeyed" : e.type === "rightKeyed"; + if (!isCursorAtEnd || ignoreEvent) { + return; + } + } + query = this.inputView.getQuery(); + hint = this.inputView.getHintValue(); + if (hint !== "" && query !== hint) { + suggestion = this.dropdownView.getFirstSuggestion(); + this.inputView.setInputValue(suggestion.value); + this.eventBus.trigger("autocompleted", suggestion.datum, suggestion.dataset); + } + }, + _propagateEvent: function(e) { + this.eventBus.trigger(e.type); + }, + destroy: function() { + this.inputView.destroy(); + this.dropdownView.destroy(); + destroyDomStructure(this.$node); + this.$node = null; + }, + setQuery: function(query) { + this.inputView.setQuery(query); + this.inputView.setInputValue(query); + this._clearHint(); + this._clearSuggestions(); + this._getSuggestions(); + } + }); + return TypeaheadView; + function buildDomStructure(input) { + var $wrapper = $(html.wrapper), $dropdown = $(html.dropdown), $input = $(input), $hint = $(html.hint); + $wrapper = $wrapper.css(css.wrapper); + $dropdown = $dropdown.css(css.dropdown); + $hint.css(css.hint).css({ + backgroundAttachment: $input.css("background-attachment"), + backgroundClip: $input.css("background-clip"), + backgroundColor: $input.css("background-color"), + backgroundImage: $input.css("background-image"), + backgroundOrigin: $input.css("background-origin"), + backgroundPosition: $input.css("background-position"), + backgroundRepeat: $input.css("background-repeat"), + backgroundSize: $input.css("background-size") + }); + $input.data("ttAttrs", { + dir: $input.attr("dir"), + autocomplete: $input.attr("autocomplete"), + spellcheck: $input.attr("spellcheck"), + style: $input.attr("style") + }); + $input.addClass("tt-query").attr({ + autocomplete: "off", + spellcheck: false + }).css(css.query); + try { + !$input.attr("dir") && $input.attr("dir", "auto"); + } catch (e) {} + return $input.wrap($wrapper).parent().prepend($hint).append($dropdown); + } + function destroyDomStructure($node) { + var $input = $node.find(".tt-query"); + utils.each($input.data("ttAttrs"), function(key, val) { + utils.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val); + }); + $input.detach().removeData("ttAttrs").removeClass("tt-query").insertAfter($node); + $node.remove(); + } + }(); + (function() { + var cache = {}, viewKey = "ttView", methods; + methods = { + initialize: function(datasetDefs) { + var datasets; + datasetDefs = utils.isArray(datasetDefs) ? datasetDefs : [ datasetDefs ]; + if (datasetDefs.length === 0) { + $.error("no datasets provided"); + } + datasets = utils.map(datasetDefs, function(o) { + var dataset = cache[o.name] ? cache[o.name] : new Dataset(o); + if (o.name) { + cache[o.name] = dataset; + } + return dataset; + }); + return this.each(initialize); + function initialize() { + var $input = $(this), deferreds, eventBus = new EventBus({ + el: $input + }); + deferreds = utils.map(datasets, function(dataset) { + return dataset.initialize(); + }); + $input.data(viewKey, new TypeaheadView({ + input: $input, + eventBus: eventBus = new EventBus({ + el: $input + }), + datasets: datasets + })); + $.when.apply($, deferreds).always(function() { + utils.defer(function() { + eventBus.trigger("initialized"); + }); + }); + } + }, + destroy: function() { + return this.each(destroy); + function destroy() { + var $this = $(this), view = $this.data(viewKey); + if (view) { + view.destroy(); + $this.removeData(viewKey); + } + } + }, + setQuery: function(query) { + return this.each(setQuery); + function setQuery() { + var view = $(this).data(viewKey); + view && view.setQuery(query); + } + } + }; + jQuery.fn.typeahead = function(method) { + if (methods[method]) { + return methods[method].apply(this, [].slice.call(arguments, 1)); + } else { + return methods.initialize.apply(this, arguments); + } + }; + })(); +})(window.jQuery); \ No newline at end of file diff --git a/src/main/webapp/docs/ontology.jsp b/src/main/webapp/docs/ontology.jsp index 3200b96..976a167 100644 --- a/src/main/webapp/docs/ontology.jsp +++ b/src/main/webapp/docs/ontology.jsp @@ -328,7 +328,7 @@
  1. For resources, this means the global object query. For each individual answer to this query, new Item individuals will be created.
      -
    • For CSV resources, query is the combination of the column delimiter with the quotes delimiter and with the headers skip number (Ex: t|"|1) [1].
    • +
    • For CSV resources, query is the combination of the headers skip number with the quotes delimiter (Ex: 1|") [1].
    • For XML resources, query is the global XPath query (//entry).
    • diff --git a/src/main/webapp/index.jsp b/src/main/webapp/index.jsp index 20e6f68..ab1e907 100644 --- a/src/main/webapp/index.jsp +++ b/src/main/webapp/index.jsp @@ -23,7 +23,12 @@
    - +
    +

    SWAT4LS Workshop New!!

    +

    A COEUS Workshop/Tutorial will be presented in the next edition of SWAT4LS.

    +

    This workshop will be helded in Edinburgh, UK, December 9-12, 2013.

    +

    View more »

    +

    Hello, Semantic Web!

    diff --git a/src/main/webapp/layout/html.jsp b/src/main/webapp/layout/html.jsp index 0bf0509..dccc94a 100644 --- a/src/main/webapp/layout/html.jsp +++ b/src/main/webapp/layout/html.jsp @@ -32,6 +32,8 @@
  2. ">Science
  3. ">SPARQL
  4. + +
  5. ">Setup
  6. Contact
  7. @@ -49,7 +51,7 @@