From b55328110e79d43af78be1ce5c925cbd8baff026 Mon Sep 17 00:00:00 2001 From: Cody Hinchliff Date: Mon, 8 Sep 2014 15:52:45 -0400 Subject: [PATCH 01/13] new names for indexing plugin/services --- .../java/org/opentree/oti/plugins/index.java | 152 ++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 src/main/java/org/opentree/oti/plugins/index.java diff --git a/src/main/java/org/opentree/oti/plugins/index.java b/src/main/java/org/opentree/oti/plugins/index.java new file mode 100644 index 0000000..7e462bb --- /dev/null +++ b/src/main/java/org/opentree/oti/plugins/index.java @@ -0,0 +1,152 @@ +package org.opentree.oti.plugins; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.json.simple.JSONObject; +import org.json.simple.JSONArray; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.neo4j.graphdb.GraphDatabaseService; +import org.neo4j.graphdb.Node; +import org.neo4j.server.plugins.Description; +import org.neo4j.server.plugins.Parameter; +import org.neo4j.server.plugins.PluginTarget; +import org.neo4j.server.plugins.ServerPlugin; +import org.neo4j.server.plugins.Source; +import org.neo4j.server.rest.repr.ListRepresentation; +import org.neo4j.server.rest.repr.MappingRepresentation; +import org.neo4j.server.rest.repr.OTRepresentationConverter; +//import org.neo4j.server.rest.repr.OpentreeRepresentationConverter; +import org.neo4j.server.rest.repr.Representation; +import org.neo4j.server.rest.repr.ValueRepresentation; +import org.opentree.MessageLogger; +import org.opentree.graphdb.DatabaseUtils; +import org.opentree.nexson.io.NexsonReader; +import org.opentree.nexson.io.NexsonSource; +import org.opentree.oti.QueryRunner; +import org.opentree.oti.DatabaseManager; +import org.opentree.oti.indexproperties.IndexedPrimitiveProperties; +import org.opentree.properties.OTVocabularyPredicate; + +/** + * services for indexing. very preliminary, should probably be reorganized (later). + * + * @author cody + * + */ +public class index extends ServerPlugin { + + /** + * Index the nexson data accessible at the passed url(s). + * @param graphDb + * @param url + * @return + * @throws MalformedURLException + * @throws IOException + */ + @Description("Index the nexson data at the provided urls. If a nexson study to be indexed has an identical ot:studyId value to a " + + "previously indexed study, then the previous information for that study will be replaced by the incoming nexson. Returns an " + + "array containing the study ids for the studies that were successfully read and indexed.") + @PluginTarget(GraphDatabaseService.class) + public Representation add_nexsons(@Source GraphDatabaseService graphDb, + @Description("remote nexson urls") @Parameter(name = "urls", optional = false) String[] urls) throws MalformedURLException, IOException { + + if (urls.length < 1) { + throw new IllegalArgumentException("You must provide at least one url for a nexson document to be indexed."); + } + + ArrayList indexedIDs = new ArrayList(urls.length); + HashMap idsWithErrors = new HashMap(); + DatabaseManager manager = new DatabaseManager(graphDb); + for (int i = 0; i < urls.length; i++) { + try { + NexsonSource study = readRemoteNexson(urls[i]); +// if (study.getTrees().iterator().hasNext()) { + manager.addOrReplaceStudy(study); + indexedIDs.add(study.getId()); +// } + } catch (Exception ex) { + idsWithErrors.put(urls[i], ex.getMessage()); + } + } + HashMap results = new HashMap(); // will be converted to JSON object + results.put("indexed", indexedIDs); + results.put("errors", idsWithErrors); + return OTRepresentationConverter.convert(results); + + } + + + /** + * Remove nexson data (if found) by study id + * @param graphDb + * @param url + * @return + * @throws IOException + */ + @Description("Unindex (remove) the nexson data for these study ids. If no matching " + + "study is found, do nothing. Returns arrays containing the study ids for " + + "the studies that were successfully removed from the index, and those that could " + + "not be found (and throws exceptions for those whose removal failed.") + @PluginTarget(GraphDatabaseService.class) + public Representation remove_nexsons(@Source GraphDatabaseService graphDb, + @Description("doomed nexson ids") @Parameter(name = "ids", optional = false) String[] ids) throws IOException { + + if (ids.length < 1) { + throw new IllegalArgumentException("You must provide at least one id for a nexson document to be removed."); + } + + DatabaseManager manager = new DatabaseManager(graphDb); + + // record ids according the result of their attempted removal + ArrayList idsDeleted = new ArrayList(ids.length); + ArrayList idsNotFound = new ArrayList(ids.length); + HashMap idsWithErrors = new HashMap(); + for (String studyId : ids) { + + Node studyMeta = manager.getStudyMetaNodeForStudyId(studyId); + if (studyMeta == null) { + // could not find study with this id + idsNotFound.add(studyId); + + } else { + // found it. carry out the sentence + try { + manager.deleteSource(studyMeta); + idsDeleted.add(studyId); + } catch (Exception ex) { + idsWithErrors.put(studyId,ex.getMessage()); + } + } + } + + HashMap results = new HashMap(); // will be converted to JSON object + results.put("deleted", idsDeleted); + results.put("not_found", idsNotFound); + results.put("errors", idsWithErrors); + return OTRepresentationConverter.convert(results); + + } + + /** + * helper function for reading a nexson from a url + * + * @param url + * @return Jade trees from nexson + * @throws MalformedURLException + * @throws IOException + */ + private NexsonSource readRemoteNexson(String url) throws MalformedURLException, IOException { + BufferedReader nexson = new BufferedReader(new InputStreamReader(new URL(url).openStream())); + return new NexsonSource(nexson); + } +} From 08c3556b25aa0de86e21a0ae14b81e7cbf2d9dee Mon Sep 17 00:00:00 2001 From: Cody Hinchliff Date: Mon, 8 Sep 2014 15:53:38 -0400 Subject: [PATCH 02/13] deprecating old indexing class/methods --- src/main/java/org/opentree/oti/plugins/IndexServices.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/org/opentree/oti/plugins/IndexServices.java b/src/main/java/org/opentree/oti/plugins/IndexServices.java index d9d82e1..59e12b1 100644 --- a/src/main/java/org/opentree/oti/plugins/IndexServices.java +++ b/src/main/java/org/opentree/oti/plugins/IndexServices.java @@ -43,6 +43,7 @@ * @author cody * */ +@Deprecated public class IndexServices extends ServerPlugin { /** @@ -80,6 +81,7 @@ public Representation indexSingleNexson(@Source GraphDatabaseService graphDb, "previously indexed study, then the previous information for that study will be replaced by the incoming nexson. Returns an " + "array containing the study ids for the studies that were successfully read and indexed.") @PluginTarget(GraphDatabaseService.class) + @Deprecated public Representation indexNexsons(@Source GraphDatabaseService graphDb, @Description("remote nexson urls") @Parameter(name = "urls", optional = false) String[] urls) throws MalformedURLException, IOException { @@ -121,6 +123,7 @@ public Representation indexNexsons(@Source GraphDatabaseService graphDb, "the studies that were successfully removed from the index, and those that could " + "not be found (and throws exceptions for those whose removal failed.") @PluginTarget(GraphDatabaseService.class) + @Deprecated public Representation unindexNexsons(@Source GraphDatabaseService graphDb, @Description("doomed nexson ids") @Parameter(name = "ids", optional = false) String[] ids) throws IOException { From a9d0aa244dabf410bf0699138eb48b14b9111987 Mon Sep 17 00:00:00 2001 From: Cody Hinchliff Date: Mon, 8 Sep 2014 15:56:21 -0400 Subject: [PATCH 03/13] removing unused plugin class --- .../opentree/oti/plugins/NexsonServices.java | 87 ------------------- 1 file changed, 87 deletions(-) delete mode 100644 src/main/java/org/opentree/oti/plugins/NexsonServices.java diff --git a/src/main/java/org/opentree/oti/plugins/NexsonServices.java b/src/main/java/org/opentree/oti/plugins/NexsonServices.java deleted file mode 100644 index 8f0d80e..0000000 --- a/src/main/java/org/opentree/oti/plugins/NexsonServices.java +++ /dev/null @@ -1,87 +0,0 @@ -package org.opentree.oti.plugins; - - -/** - * Space for other services, such as getting information about nexson properties, etc. Currently not necessary. - * @author cody - * - */ -public class NexsonServices { - - /* - - /** - * @param nodeId - * @return - * @throws NoSuchTreeException - * - @Description( "Get the neo4j root node for a given tree id" ) - @PluginTarget( GraphDatabaseService.class ) - public Long getRootNodeIdForTreeId(@Source GraphDatabaseService graphDb, - @Description( "The id of the tree to be found.") - @Parameter(name = "treeId", optional = false) String treeId) throws TreeNotFoundException { - - QueryRunner queryRunner = new QueryRunner(graphDb); - - // TODO: add check for whether tree is imported. If not then return this information - -// Node rootNode = queryRunner.getTreeRootNode(treeId); -// return rootNode.getId(); - - return Long.valueOf(-999); // placeholder for unimplemented method return - } - - /** - * @param nodeId - * @return - * - @Description( "Return a string containing a JSON string for the subtree below the indicated tree node" ) - @PluginTarget( GraphDatabaseService.class ) - public Representation getTreeJson(@Source GraphDatabaseService graphDb, - @Description( "The Neo4j node id of the node to be used as the root for the tree (can be used to extract subtrees as well).") - @Parameter(name = "nodeId", optional = false) Long nodeId) { -// DatabaseBrowser browser = new DatabaseBrowser(graphDb); - - // TODO: add check for whether tree is imported. If not then return error instead of just empty tree - Node rootNode = graphDb.getNodeById(nodeId); - JadeTree jadeTree = QueryRunner.getJadeTreeForGraphNode(rootNode, 300); - - return OTRepresentationConverter.convert(jadeTree); -// return t.getRoot().getJSON(false); - } - - @Description( "Get tree metadata" ) - @PluginTarget( GraphDatabaseService.class ) - public Representation getTreeMetaData(@Source GraphDatabaseService graphDb, - @Description( "The database tree id for the tree") - @Parameter(name = "treeId", optional = false) String treeId) { - - QueryRunner browser = new QueryRunner(graphDb); - Node root = browser.getTreeRootNode(treeId, browser.LOCAL_LOCATION); - return OTRepresentationConverter.convert(browser.getMetadataForTree(root)); - } - - @Description( "Get the id for the source associated with the specified tree id" ) - @PluginTarget( GraphDatabaseService.class ) - public String getSourceIdForTreeId(@Source GraphDatabaseService graphDb, - @Description( "The tree id to use") - @Parameter(name = "treeId", optional = false) String treeId) { - - QueryRunner browser = new QueryRunner(graphDb); - - Node treeRoot = browser.getTreeRootNode(treeId, browser.LOCAL_LOCATION); - Node sourceMeta = treeRoot.getSingleRelationship(OTIRelType.METADATAFOR, Direction.INCOMING).getStartNode(); - - return (String) sourceMeta.getProperty(OTINodeProperty.STUDY_ID.propertyName()); - } - - @Description("Get OTU metadata. Currently not used because we get all this infor from the getTreeJSON service") - @PluginTarget(Node.class) - @Deprecated - public Representation getOTUMetaData(@Source Node node) { - - QueryRunner browser = new QueryRunner(node.getGraphDatabase()); - return OTRepresentationConverter.convert(browser.getMetadataForOTU(node)); - } - */ -} From 17df1666eeb9dccb5876752544e17d545cdc6f49 Mon Sep 17 00:00:00 2001 From: Cody Hinchliff Date: Mon, 8 Sep 2014 15:57:42 -0400 Subject: [PATCH 04/13] removing taxonomy services -- taxonomy must be pre-existing in the db --- .../oti/plugins/ConfigurationServices.java | 98 ------------------- 1 file changed, 98 deletions(-) delete mode 100644 src/main/java/org/opentree/oti/plugins/ConfigurationServices.java diff --git a/src/main/java/org/opentree/oti/plugins/ConfigurationServices.java b/src/main/java/org/opentree/oti/plugins/ConfigurationServices.java deleted file mode 100644 index 2e1b78c..0000000 --- a/src/main/java/org/opentree/oti/plugins/ConfigurationServices.java +++ /dev/null @@ -1,98 +0,0 @@ -package org.opentree.oti.plugins; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.neo4j.graphdb.Direction; -import org.neo4j.graphdb.GraphDatabaseService; -import org.neo4j.graphdb.Node; -import org.neo4j.graphdb.Transaction; -import org.neo4j.server.plugins.Description; -import org.neo4j.server.plugins.Parameter; -import org.neo4j.server.plugins.PluginTarget; -import org.neo4j.server.plugins.ServerPlugin; -import org.neo4j.server.plugins.Source; -import org.neo4j.server.rest.repr.OTRepresentationConverter; -import org.neo4j.server.rest.repr.Representation; -import org.opentree.graphdb.DatabaseUtils; -import org.opentree.graphdb.GraphDatabaseAgent; -import org.opentree.oti.DatabaseBrowser; -import org.opentree.oti.DatabaseManager; -import org.opentree.oti.constants.OTIGraphProperty; -import org.opentree.oti.constants.OTIRelType; -import org.opentree.taxonomy.TaxonomyLoaderOTT; - -/** - * services for indexing. very preliminary, should probably be reorganized (later). - * - * @author cody - * - */ -public class ConfigurationServices extends ServerPlugin { - - @Description( "Install the OTT taxonomy" ) - @PluginTarget( GraphDatabaseService.class ) - public Representation installOTT(@Source GraphDatabaseService graphDb, - @Description( "Taxonomy file") - @Parameter(name = "taxonomyFile", optional = false) String taxonomyFile, - @Description( "Synonym file") - @Parameter(name = "synonymFile", optional = true) String synonymFile) { - - GraphDatabaseAgent gdb = new GraphDatabaseAgent(graphDb); - gdb.setGraphProperty(OTIGraphProperty.TAXONOMY_IS_LOADING.propertyName(), true); - - TaxonomyLoaderOTT loader = new TaxonomyLoaderOTT(graphDb); - - // turn off unnecessary features - loader.setAddSynonyms(synonymFile == null ? false : true); - loader.setAddBarrierNodes(false); - loader.setbuildPreferredIndexes(false); - loader.setbuildPreferredRels(false); - - // make sure we build the optional ott id index - loader.setCreateOTTIdIndexes(true); - - // load the taxonomy - loader.loadOTTIntoGraph("ott", taxonomyFile, synonymFile == null ? "" : synonymFile); - - gdb.setGraphProperty(OTIGraphProperty.HAS_TAXONOMY.propertyName(), true); - gdb.removeGraphProperty(OTIGraphProperty.TAXONOMY_IS_LOADING); - - Map results = new HashMap(); - results.put("event", "success"); - return OTRepresentationConverter.convert(results); - } - - @Description( "Connect the OTT taxonomy to all terminal tree nodes with mapped ott ids in all indexed trees" ) - @PluginTarget( GraphDatabaseService.class ) - public Representation connectAllTreesToOTT(@Source GraphDatabaseService graphDb) { - - DatabaseBrowser browser = new DatabaseBrowser(graphDb); - DatabaseManager manager = new DatabaseManager(graphDb); - - List localSourceIds = browser.getSourceIds(); - - Transaction tx = graphDb.beginTx(); - try { - for (String sourceId : localSourceIds) { - for (String treeId : browser.getTreeIdsForSourceId(sourceId)) { - Node root = browser.getTreeRootNode(treeId); - for (Node otu : DatabaseUtils.descendantTipTraversal(OTIRelType.CHILDOF, Direction.INCOMING).traverse(root).nodes()) { - manager.connectTreeNodeToTaxonomy(otu); - } - } - } - tx.success(); - - } finally { - tx.finish(); - } - - Map result = new HashMap(); - result.put("event", "success"); - return OTRepresentationConverter.convert(result); - } - - -} From b5add195f5295becbb71aaebbfb99c9d5c48d385 Mon Sep 17 00:00:00 2001 From: Cody Hinchliff Date: Mon, 8 Sep 2014 16:17:16 -0400 Subject: [PATCH 05/13] new names and consolidation of search methods --- .../org/opentree/oti/plugins/studies.java | 132 ++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 src/main/java/org/opentree/oti/plugins/studies.java diff --git a/src/main/java/org/opentree/oti/plugins/studies.java b/src/main/java/org/opentree/oti/plugins/studies.java new file mode 100644 index 0000000..87e8a0c --- /dev/null +++ b/src/main/java/org/opentree/oti/plugins/studies.java @@ -0,0 +1,132 @@ +package org.opentree.oti.plugins; + +import java.util.HashMap; +import java.util.HashSet; +import org.opentree.oti.QueryRunner; +import org.opentree.oti.indexproperties.OTIProperties; +import org.apache.lucene.queryParser.ParseException; +import org.apache.lucene.search.MatchAllDocsQuery; +import org.neo4j.graphdb.GraphDatabaseService; +import org.neo4j.server.plugins.*; +import org.neo4j.server.rest.repr.OTRepresentationConverter; +import org.neo4j.server.rest.repr.Representation; +import org.opentree.properties.OTPropertyPredicate; + +/** + * Search services for the oti nexson database. + * @author cody + * + */ +public class studies extends ServerPlugin { + + /** + * Perform a simple search for studies + * @param graphDb + * @param propertyName + * @param value + * @return + * @throws ParseException + */ + @Description("Perform a simple search for indexed studies. To find all studies, omit both the property and the value from your query.") + @PluginTarget(GraphDatabaseService.class) + public Representation find_studies(@Source GraphDatabaseService graphDb, + @Description("The property to be searched on. A list of searchable properties is available from the getSearchablePropertiesForStudies service." + + "To find all studies, omit both the property and the value from your query.") + @Parameter(name = "property", optional = true) String property, + @Description("The value to be searched. This must be passed as a string, but will be converted to the datatype corresponding to the " + + "specified searchable value. To find all studies, omit both the property and the value from your query.") + @Parameter(name = "value", optional = true) String value, + @Description("Whether to perform exact matching ONLY. Defaults to false, i.e. fuzzy matching is enabled. Fuzzy matching is only applicable for some string properties.") + @Parameter(name="exact", optional = true) Boolean checkExactOnly, + @Description("Whether or not to include all metadata. By default, only the nexson ids of elements will be returned.") + @Parameter(name = "verbose", optional = true) Boolean verbose) throws ParseException { + + // set null optional parameters to default values + verbose = verbose == null ? false : verbose; + boolean doFuzzyMatching = checkExactOnly == null ? true : ! checkExactOnly; + + // prepare for search + HashMap results = new HashMap(); + QueryRunner runner = new QueryRunner(graphDb); + + if (property == null && value == null) { + // no property specified, find all studies + results.put("matched_studies", runner.doBasicSearchForTrees(new MatchAllDocsQuery(), null, verbose)); + + } else if ((property == null && value != null) || (property != null && value == null)) { + // property or value specified but not both, return error + results.put("error", "You either specified a property but not a value, or a value but not a property. " + + "If you specify a property or a value, you must specify both. You may alternatively specify " + + "neither to find all studies."); + + } else { // user specified a property and a value, attempt to search + + HashSet searchProperties = new OTIProperties().getIndexedStudyProperties().get(property); + + if (searchProperties != null) { + results.put("matched_studies", runner.doBasicSearchForStudies(searchProperties, value, doFuzzyMatching, verbose)); + } else { + results.put("error", "unrecognized property: " + property); + } + } + + return OTRepresentationConverter.convert(results); + } + + /** + * Perform a simple search for trees + * @param graphDb + * @param propertyName + * @param value + * @return + */ + @Description("Perform a simple search for trees in indexed studies") + @PluginTarget(GraphDatabaseService.class) + public Representation find_trees(@Source GraphDatabaseService graphDb, + @Description("The property to be searched on. A list of searchable properties is available from the getSearchablePropertiesForTrees service.") + @Parameter(name = "property", optional = false) String property, + @Description("The value to be searched. This must be passed as a string, but will be converted to the datatype corresponding to the " + + "specified searchable value.") @Parameter(name = "value", optional = false) String value, + @Description("Whether to perform exact matching ONLY. Defaults to false, i.e. fuzzy matching is enabled. Only applicable for some string properties.") + @Parameter(name="exact", optional = true) Boolean checkExactOnly, + @Description("Whether or not to include all metadata. By default, only the nexson ids of elements will be returned.") + @Parameter(name = "verbose", optional = true) Boolean verbose) { + + // set null optional parameters to default values + verbose = verbose == null ? false : verbose; + boolean doFuzzyMatching = checkExactOnly == null ? true : ! checkExactOnly; + + HashSet searchProperties = new OTIProperties().getIndexedTreeProperties().get(property); + HashMap results = new HashMap(); + + if (searchProperties != null) { + QueryRunner runner = new QueryRunner(graphDb); + results.put("matched_studies", runner.doBasicSearchForTrees(searchProperties, value, doFuzzyMatching, verbose)); + } else { + results.put("error", "unrecognized property: " + property); + } + + return OTRepresentationConverter.convert(results); + + } + + /** + * Return a map containing available property names and the names of the SearchableProperty enum elements they + * correspond to. + * + * @param graphDb + * @return + */ + @Description("Get a list of properties that can be used to search for studies and trees.") + @PluginTarget(GraphDatabaseService.class) + public Representation properties (@Source GraphDatabaseService graphDb) { + + HashMap results = new HashMap(); + + OTIProperties properties = new OTIProperties(); + results.put("study_properties", properties.getIndexedStudyProperties().keySet()); + results.put("tree_properties", properties.getIndexedStudyProperties().keySet()); + + return OTRepresentationConverter.convert(results); + } +} From 44c4004144ca2aa17cecb0091ee60669d8b23123 Mon Sep 17 00:00:00 2001 From: Cody Hinchliff Date: Mon, 8 Sep 2014 16:35:19 -0400 Subject: [PATCH 06/13] combine indexing and searching methods in single plugin --- .../java/org/opentree/oti/plugins/index.java | 152 ------------------ .../org/opentree/oti/plugins/studies.java | 115 +++++++++++++ .../org.neo4j.server.plugins.ServerPlugin | 3 +- 3 files changed, 116 insertions(+), 154 deletions(-) delete mode 100644 src/main/java/org/opentree/oti/plugins/index.java diff --git a/src/main/java/org/opentree/oti/plugins/index.java b/src/main/java/org/opentree/oti/plugins/index.java deleted file mode 100644 index 7e462bb..0000000 --- a/src/main/java/org/opentree/oti/plugins/index.java +++ /dev/null @@ -1,152 +0,0 @@ -package org.opentree.oti.plugins; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import org.json.simple.JSONObject; -import org.json.simple.JSONArray; -import org.json.simple.parser.JSONParser; -import org.json.simple.parser.ParseException; -import org.neo4j.graphdb.GraphDatabaseService; -import org.neo4j.graphdb.Node; -import org.neo4j.server.plugins.Description; -import org.neo4j.server.plugins.Parameter; -import org.neo4j.server.plugins.PluginTarget; -import org.neo4j.server.plugins.ServerPlugin; -import org.neo4j.server.plugins.Source; -import org.neo4j.server.rest.repr.ListRepresentation; -import org.neo4j.server.rest.repr.MappingRepresentation; -import org.neo4j.server.rest.repr.OTRepresentationConverter; -//import org.neo4j.server.rest.repr.OpentreeRepresentationConverter; -import org.neo4j.server.rest.repr.Representation; -import org.neo4j.server.rest.repr.ValueRepresentation; -import org.opentree.MessageLogger; -import org.opentree.graphdb.DatabaseUtils; -import org.opentree.nexson.io.NexsonReader; -import org.opentree.nexson.io.NexsonSource; -import org.opentree.oti.QueryRunner; -import org.opentree.oti.DatabaseManager; -import org.opentree.oti.indexproperties.IndexedPrimitiveProperties; -import org.opentree.properties.OTVocabularyPredicate; - -/** - * services for indexing. very preliminary, should probably be reorganized (later). - * - * @author cody - * - */ -public class index extends ServerPlugin { - - /** - * Index the nexson data accessible at the passed url(s). - * @param graphDb - * @param url - * @return - * @throws MalformedURLException - * @throws IOException - */ - @Description("Index the nexson data at the provided urls. If a nexson study to be indexed has an identical ot:studyId value to a " + - "previously indexed study, then the previous information for that study will be replaced by the incoming nexson. Returns an " + - "array containing the study ids for the studies that were successfully read and indexed.") - @PluginTarget(GraphDatabaseService.class) - public Representation add_nexsons(@Source GraphDatabaseService graphDb, - @Description("remote nexson urls") @Parameter(name = "urls", optional = false) String[] urls) throws MalformedURLException, IOException { - - if (urls.length < 1) { - throw new IllegalArgumentException("You must provide at least one url for a nexson document to be indexed."); - } - - ArrayList indexedIDs = new ArrayList(urls.length); - HashMap idsWithErrors = new HashMap(); - DatabaseManager manager = new DatabaseManager(graphDb); - for (int i = 0; i < urls.length; i++) { - try { - NexsonSource study = readRemoteNexson(urls[i]); -// if (study.getTrees().iterator().hasNext()) { - manager.addOrReplaceStudy(study); - indexedIDs.add(study.getId()); -// } - } catch (Exception ex) { - idsWithErrors.put(urls[i], ex.getMessage()); - } - } - HashMap results = new HashMap(); // will be converted to JSON object - results.put("indexed", indexedIDs); - results.put("errors", idsWithErrors); - return OTRepresentationConverter.convert(results); - - } - - - /** - * Remove nexson data (if found) by study id - * @param graphDb - * @param url - * @return - * @throws IOException - */ - @Description("Unindex (remove) the nexson data for these study ids. If no matching " + - "study is found, do nothing. Returns arrays containing the study ids for " + - "the studies that were successfully removed from the index, and those that could " + - "not be found (and throws exceptions for those whose removal failed.") - @PluginTarget(GraphDatabaseService.class) - public Representation remove_nexsons(@Source GraphDatabaseService graphDb, - @Description("doomed nexson ids") @Parameter(name = "ids", optional = false) String[] ids) throws IOException { - - if (ids.length < 1) { - throw new IllegalArgumentException("You must provide at least one id for a nexson document to be removed."); - } - - DatabaseManager manager = new DatabaseManager(graphDb); - - // record ids according the result of their attempted removal - ArrayList idsDeleted = new ArrayList(ids.length); - ArrayList idsNotFound = new ArrayList(ids.length); - HashMap idsWithErrors = new HashMap(); - for (String studyId : ids) { - - Node studyMeta = manager.getStudyMetaNodeForStudyId(studyId); - if (studyMeta == null) { - // could not find study with this id - idsNotFound.add(studyId); - - } else { - // found it. carry out the sentence - try { - manager.deleteSource(studyMeta); - idsDeleted.add(studyId); - } catch (Exception ex) { - idsWithErrors.put(studyId,ex.getMessage()); - } - } - } - - HashMap results = new HashMap(); // will be converted to JSON object - results.put("deleted", idsDeleted); - results.put("not_found", idsNotFound); - results.put("errors", idsWithErrors); - return OTRepresentationConverter.convert(results); - - } - - /** - * helper function for reading a nexson from a url - * - * @param url - * @return Jade trees from nexson - * @throws MalformedURLException - * @throws IOException - */ - private NexsonSource readRemoteNexson(String url) throws MalformedURLException, IOException { - BufferedReader nexson = new BufferedReader(new InputStreamReader(new URL(url).openStream())); - return new NexsonSource(nexson); - } -} diff --git a/src/main/java/org/opentree/oti/plugins/studies.java b/src/main/java/org/opentree/oti/plugins/studies.java index 87e8a0c..d3c2545 100644 --- a/src/main/java/org/opentree/oti/plugins/studies.java +++ b/src/main/java/org/opentree/oti/plugins/studies.java @@ -1,12 +1,22 @@ package org.opentree.oti.plugins; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; + +import org.opentree.nexson.io.NexsonSource; +import org.opentree.oti.DatabaseManager; import org.opentree.oti.QueryRunner; import org.opentree.oti.indexproperties.OTIProperties; import org.apache.lucene.queryParser.ParseException; import org.apache.lucene.search.MatchAllDocsQuery; import org.neo4j.graphdb.GraphDatabaseService; +import org.neo4j.graphdb.Node; import org.neo4j.server.plugins.*; import org.neo4j.server.rest.repr.OTRepresentationConverter; import org.neo4j.server.rest.repr.Representation; @@ -129,4 +139,109 @@ public Representation properties (@Source GraphDatabaseService graphDb) { return OTRepresentationConverter.convert(results); } + + /** + * Index the nexson data accessible at the passed url(s). + * @param graphDb + * @param url + * @return + * @throws MalformedURLException + * @throws IOException + */ + @Description("Index the nexson data at the provided urls. If a nexson study to be indexed has an identical ot:studyId value to a " + + "previously indexed study, then the previous information for that study will be replaced by the incoming nexson. Returns an " + + "array containing the study ids for the studies that were successfully read and indexed.") + @PluginTarget(GraphDatabaseService.class) + public Representation index_studies(@Source GraphDatabaseService graphDb, + @Description("remote nexson urls") @Parameter(name = "urls", optional = false) String[] urls) throws MalformedURLException, IOException { + + if (urls.length < 1) { + throw new IllegalArgumentException("You must provide at least one url for a nexson document to be indexed."); + } + + ArrayList indexedIDs = new ArrayList(urls.length); + HashMap idsWithErrors = new HashMap(); + DatabaseManager manager = new DatabaseManager(graphDb); + for (int i = 0; i < urls.length; i++) { + try { + NexsonSource study = readRemoteNexson(urls[i]); +// if (study.getTrees().iterator().hasNext()) { + manager.addOrReplaceStudy(study); + indexedIDs.add(study.getId()); +// } + } catch (Exception ex) { + idsWithErrors.put(urls[i], ex.getMessage()); + } + } + HashMap results = new HashMap(); // will be converted to JSON object + results.put("indexed", indexedIDs); + results.put("errors", idsWithErrors); + return OTRepresentationConverter.convert(results); + + } + + + /** + * Remove nexson data (if found) by study id + * @param graphDb + * @param url + * @return + * @throws IOException + */ + @Description("Unindex (remove) the nexson data for these study ids. If no matching " + + "study is found, do nothing. Returns arrays containing the study ids for " + + "the studies that were successfully removed from the index, and those that could " + + "not be found (and throws exceptions for those whose removal failed.") + @PluginTarget(GraphDatabaseService.class) + public Representation unindex_studies(@Source GraphDatabaseService graphDb, + @Description("doomed nexson ids") @Parameter(name = "ids", optional = false) String[] ids) throws IOException { + + if (ids.length < 1) { + throw new IllegalArgumentException("You must provide at least one id for a nexson document to be removed."); + } + + DatabaseManager manager = new DatabaseManager(graphDb); + + // record ids according the result of their attempted removal + ArrayList idsDeleted = new ArrayList(ids.length); + ArrayList idsNotFound = new ArrayList(ids.length); + HashMap idsWithErrors = new HashMap(); + for (String studyId : ids) { + + Node studyMeta = manager.getStudyMetaNodeForStudyId(studyId); + if (studyMeta == null) { + // could not find study with this id + idsNotFound.add(studyId); + + } else { + // found it. carry out the sentence + try { + manager.deleteSource(studyMeta); + idsDeleted.add(studyId); + } catch (Exception ex) { + idsWithErrors.put(studyId,ex.getMessage()); + } + } + } + + HashMap results = new HashMap(); // will be converted to JSON object + results.put("deleted", idsDeleted); + results.put("not_found", idsNotFound); + results.put("errors", idsWithErrors); + return OTRepresentationConverter.convert(results); + + } + + /** + * helper function for reading a nexson from a url + * + * @param url + * @return Jade trees from nexson + * @throws MalformedURLException + * @throws IOException + */ + private NexsonSource readRemoteNexson(String url) throws MalformedURLException, IOException { + BufferedReader nexson = new BufferedReader(new InputStreamReader(new URL(url).openStream())); + return new NexsonSource(nexson); + } } diff --git a/src/main/resources/archive-files/services/org.neo4j.server.plugins.ServerPlugin b/src/main/resources/archive-files/services/org.neo4j.server.plugins.ServerPlugin index 153f656..c07f0e8 100644 --- a/src/main/resources/archive-files/services/org.neo4j.server.plugins.ServerPlugin +++ b/src/main/resources/archive-files/services/org.neo4j.server.plugins.ServerPlugin @@ -1,4 +1,3 @@ org.opentree.oti.plugins.IndexServices org.opentree.oti.plugins.QueryServices -org.opentree.oti.plugins.NexsonServices -org.opentree.oti.plugins.ConfigurationServices \ No newline at end of file +org.opentree.oti.plugins.studies \ No newline at end of file From c4bf7a3fabb08917fce36d918979499581e544c5 Mon Sep 17 00:00:00 2001 From: Cody Hinchliff Date: Mon, 8 Sep 2014 16:49:38 -0400 Subject: [PATCH 07/13] adding tests info --- TESTS.md | 64 +++++++++++++++++++ .../org/opentree/oti/plugins/studies.java | 2 +- 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 TESTS.md diff --git a/TESTS.md b/TESTS.md new file mode 100644 index 0000000..7895b67 --- /dev/null +++ b/TESTS.md @@ -0,0 +1,64 @@ +Currently, there are no automated test procedures for OTI. You can however, fairly thoroughly test the performance manually. Run the following command to index the current phylesystem repo on devapi.opentreeoflife.org: + +``bash +./index_current_repo.py http://localhost:7474/db/data http://devapi.opentreeoflife.org/api +``` + +And then (assuming indexing worked), query the database to test it. Here are some example queries using cURL, and their expected results. + +### Return a list of all studies: + +```bash +curl -X POST http://localhost:7474/db/data/ext/studies/graphdb/find_studies +``` + +```json +{ + "matched_studies" : [ { + "ot:studyId" : "1354" + }, { + "ot:studyId" : "2189" + }, # snipped + { + "ot:studyId" : "2326" + }, { + "ot:studyId" : "1827" + } ] +} + +### Search for studies with trees spanning the taxon with name "Annona glabra": + +```bash +curl -X POST http://localhost:7474/db/data/ext/studies/graphdb/find_trees -H "content-type: application/json" -d '{"property":"ot:ottTaxonName","value":"Annona glabra"}' +``` + +```json +{ + "matched_studies" : [ { + "matched_trees" : [ { + "nexson_id" : "tree3008", + "oti_tree_id" : "1495_tree3008" + }, { + "nexson_id" : "tree3009", + "oti_tree_id" : "1495_tree3009" + }, { + "nexson_id" : "tree3010", + "oti_tree_id" : "1495_tree3010" + } ], + "ot:studyId" : "1495" + } ] +} +``` + +### Get a list of properties available for searching studies and trees: + +```bash +curl -X POST http://localhost:7474/db/data/ext/studies/graphdb/properties +``` + +```json +{ + "tree_properties" : [ "ot:studyPublicationReference", "is_deprecated", "ot:focalCladeOTTTaxonName", "ot:studyLastEditor", "ot:studyModified", "ot:studyLabel", "ot:comment", "ot:studyId", "ot:dataDeposit", "ot:authorContributed", "ot:studyUploaded", "ot:studyYear", "ot:focalCladeTaxonName", "ot:tag", "ot:curatorName", "ot:studyPublication", "ot:focalCladeOTTId", "ot:focalClade" ], + "study_properties" : [ "ot:studyPublicationReference", "is_deprecated", "ot:focalCladeOTTTaxonName", "ot:studyLastEditor", "ot:studyModified", "ot:studyLabel", "ot:comment", "ot:studyId", "ot:dataDeposit", "ot:authorContributed", "ot:studyUploaded", "ot:studyYear", "ot:focalCladeTaxonName", "ot:tag", "ot:curatorName", "ot:studyPublication", "ot:focalCladeOTTId", "ot:focalClade" ] +} +``` \ No newline at end of file diff --git a/src/main/java/org/opentree/oti/plugins/studies.java b/src/main/java/org/opentree/oti/plugins/studies.java index d3c2545..94b06c6 100644 --- a/src/main/java/org/opentree/oti/plugins/studies.java +++ b/src/main/java/org/opentree/oti/plugins/studies.java @@ -61,7 +61,7 @@ public Representation find_studies(@Source GraphDatabaseService graphDb, if (property == null && value == null) { // no property specified, find all studies - results.put("matched_studies", runner.doBasicSearchForTrees(new MatchAllDocsQuery(), null, verbose)); + results.put("matched_studies", runner.doBasicSearchForStudies(new MatchAllDocsQuery(), null, verbose)); } else if ((property == null && value != null) || (property != null && value == null)) { // property or value specified but not both, return error From 3cdf68f6e28cc92100c009999906d2efe4b1a260 Mon Sep 17 00:00:00 2001 From: Cody Hinchliff Date: Mon, 8 Sep 2014 17:10:28 -0400 Subject: [PATCH 08/13] fixing service name --- index_current_repo.py | 56 +++---------------------------------------- 1 file changed, 3 insertions(+), 53 deletions(-) diff --git a/index_current_repo.py b/index_current_repo.py index 67bc896..0885ac7 100755 --- a/index_current_repo.py +++ b/index_current_repo.py @@ -3,7 +3,6 @@ # Command line arguments: # - URL prefix for communicating with the OTI neo4j server # - URL prefix for phylesystem API methods (not including 'v1/') -# - (future: URL for OTT tarball ?) import json, os, requests, sys, tarfile, urllib2 @@ -15,7 +14,8 @@ def get_download_dir(): def submit_indexing_request(data): '''Send a request to oti to index a single study. URL is set to default neo4j location''' - url = oti_url + "ext/IndexServices/graphdb/indexNexsons" +# url = oti_url + "ext/IndexServices/graphdb/indexNexsons" + url = oti_url + "ext/studies/graphdb/index_studies" print 'Calling "{}" with data="{}"'.format(url, repr(data)) r = requests.post(url, data=json.dumps(data), @@ -25,53 +25,12 @@ def submit_indexing_request(data): r.raise_for_status() return r.json() -def load_taxonomy(): - '''Install ott... Currently not used, we just supply a pre-built taxonomy database.''' - - # setup stuff for the download - download_dir = get_download_dir() - ott_filename = ott_file_url.rsplit("/",1)[1] - ott_save_path = os.path.join(download_dir,ott_filename) - - # download the taxonomy if necessary - if not os.path.exists(ott_save_path): - print("Downloading ott from " + ott_file_url + ".\nThis could take a while...") - req = urllib2.Request(ott_file_url) - f = urllib2.urlopen(req) - - # write the taxonomy into the file - ottfile = file(ott_save_path, 'wb') - while True: - chunk = f.read(1000000) - if not chunk: break - ottfile.write (chunk) - ottfile.close() - - # extract the taxonomy if necessary - tax_file_path = os.path.join(download_dir,"ott","taxonomy.tsv") - syn_file_path = os.path.join(download_dir,"ott","synonyms.tsv") - if not os.path.exists(tax_file_path) or not os.path.exists(syn_file_path): - os.chdir(download_dir) - tar = tarfile.open(ott_save_path) - tar.extractall() - tar.close() - - # call the taxonomy loading routines - url = oti_url + "ext/ConfigurationServices/graphdb/installOTT" - data='{"taxonomyFile":"'+tax_file_path+'","synonymFile":"'+syn_file_path+'"}' - print('Calling "{}" with data="{}"'.format(url, repr(data))) - r = requests.post(url, data, headers={'Content-type': 'application/json'}); - - # We don't really need any data out of r. - # But do raise an error if something went wrong. - r.raise_for_status() - # default args if len(sys.argv) > 1: oti_url = sys.argv[1].rstrip("/") + "/" # local oti url (example): http://localhost:7474/db/data/ else: - print("usage (with defaults): index_current_repo.py [](==http://localhost/api/) [](==http://files.opentreeoflife.org/ott/ott2.8draft3.tgz)") + print("usage (with defaults): index_current_repo.py [](==http://localhost/api/)") sys.exit(0) print("Using the oti instance at: " + oti_url) @@ -82,12 +41,6 @@ def load_taxonomy(): #files_base_url = "https://raw.github.com/OpenTreeOfLife/%s/master"%(oti_repo) print("Using the studies from: " + api_url) -if len(sys.argv) > 3: - ott_file_url = sys.argv[3] -else: - ott_file_url = "http://files.opentreeoflife.org/ott/ott2.8draft3.tgz" -#print("Using the ott taxonomy at: " + ott_file_url) - # Ignoring oti_mode for now, since we're using the local API to retrieve study # ids and NexSON in the required format. # @@ -109,9 +62,6 @@ def load_taxonomy(): # PROBLEM: URL formation are rules in the two cases. # right now we are not loading the taxonomy, any taxonomy must be provided as a pre-built database -load_taxonomy = False -if load_taxonomy: - load_taxonomy() # retrieve the study list r = requests.get(api_url + "study_list") From 074e8dfa77cd9867ed81cc3dad331068292735ea Mon Sep 17 00:00:00 2001 From: Cody Hinchliff Date: Mon, 8 Sep 2014 17:28:38 -0400 Subject: [PATCH 09/13] reflect devapi url in tests --- TESTS.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/TESTS.md b/TESTS.md index 7895b67..bf5a89e 100644 --- a/TESTS.md +++ b/TESTS.md @@ -1,7 +1,7 @@ Currently, there are no automated test procedures for OTI. You can however, fairly thoroughly test the performance manually. Run the following command to index the current phylesystem repo on devapi.opentreeoflife.org: ``bash -./index_current_repo.py http://localhost:7474/db/data http://devapi.opentreeoflife.org/api +./index_current_repo.py http://devapi.opentreeoflife.org/oti http://devapi.opentreeoflife.org/api ``` And then (assuming indexing worked), query the database to test it. Here are some example queries using cURL, and their expected results. @@ -9,7 +9,7 @@ And then (assuming indexing worked), query the database to test it. Here are som ### Return a list of all studies: ```bash -curl -X POST http://localhost:7474/db/data/ext/studies/graphdb/find_studies +curl -X POST http://devapi.opentreeoflife.org/oti/ext/studies/graphdb/find_studies ``` ```json @@ -29,7 +29,7 @@ curl -X POST http://localhost:7474/db/data/ext/studies/graphdb/find_studies ### Search for studies with trees spanning the taxon with name "Annona glabra": ```bash -curl -X POST http://localhost:7474/db/data/ext/studies/graphdb/find_trees -H "content-type: application/json" -d '{"property":"ot:ottTaxonName","value":"Annona glabra"}' +curl -X POST http://devapi.opentreeoflife.org/ext/studies/graphdb/find_trees -H "content-type: application/json" -d '{"property":"ot:ottTaxonName","value":"Annona glabra"}' ``` ```json @@ -53,7 +53,7 @@ curl -X POST http://localhost:7474/db/data/ext/studies/graphdb/find_trees -H "co ### Get a list of properties available for searching studies and trees: ```bash -curl -X POST http://localhost:7474/db/data/ext/studies/graphdb/properties +curl -X POST http://devapi.opentreeolife.org/ext/studies/graphdb/properties ``` ```json From cf6f374c822913bd93ff8e7d6a259a08334f2dfd Mon Sep 17 00:00:00 2001 From: Cody Hinchliff Date: Mon, 8 Sep 2014 17:29:51 -0400 Subject: [PATCH 10/13] fix markdown errors --- TESTS.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/TESTS.md b/TESTS.md index bf5a89e..26789d0 100644 --- a/TESTS.md +++ b/TESTS.md @@ -1,6 +1,6 @@ Currently, there are no automated test procedures for OTI. You can however, fairly thoroughly test the performance manually. Run the following command to index the current phylesystem repo on devapi.opentreeoflife.org: -``bash +```bash ./index_current_repo.py http://devapi.opentreeoflife.org/oti http://devapi.opentreeoflife.org/api ``` @@ -25,6 +25,7 @@ curl -X POST http://devapi.opentreeoflife.org/oti/ext/studies/graphdb/find_studi "ot:studyId" : "1827" } ] } +``` ### Search for studies with trees spanning the taxon with name "Annona glabra": From 4e9b624e4f006869440f6aefeed54807b14ad0a8 Mon Sep 17 00:00:00 2001 From: Jim Allman Date: Wed, 10 Sep 2014 16:38:53 -0400 Subject: [PATCH 11/13] Fixes for cURL tests (to match current apache setup) --- TESTS.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/TESTS.md b/TESTS.md index 26789d0..920fe0e 100644 --- a/TESTS.md +++ b/TESTS.md @@ -30,7 +30,7 @@ curl -X POST http://devapi.opentreeoflife.org/oti/ext/studies/graphdb/find_studi ### Search for studies with trees spanning the taxon with name "Annona glabra": ```bash -curl -X POST http://devapi.opentreeoflife.org/ext/studies/graphdb/find_trees -H "content-type: application/json" -d '{"property":"ot:ottTaxonName","value":"Annona glabra"}' +curl -X POST http://devapi.opentreeoflife.org/oti/ext/studies/graphdb/find_trees -H "content-type: application/json" -d '{"property":"ot:ottTaxonName","value":"Annona glabra"}' ``` ```json @@ -54,7 +54,7 @@ curl -X POST http://devapi.opentreeoflife.org/ext/studies/graphdb/find_trees -H ### Get a list of properties available for searching studies and trees: ```bash -curl -X POST http://devapi.opentreeolife.org/ext/studies/graphdb/properties +curl -X POST http://devapi.opentreeoflife.org/oti/ext/studies/graphdb/properties ``` ```json @@ -62,4 +62,4 @@ curl -X POST http://devapi.opentreeolife.org/ext/studies/graphdb/properties "tree_properties" : [ "ot:studyPublicationReference", "is_deprecated", "ot:focalCladeOTTTaxonName", "ot:studyLastEditor", "ot:studyModified", "ot:studyLabel", "ot:comment", "ot:studyId", "ot:dataDeposit", "ot:authorContributed", "ot:studyUploaded", "ot:studyYear", "ot:focalCladeTaxonName", "ot:tag", "ot:curatorName", "ot:studyPublication", "ot:focalCladeOTTId", "ot:focalClade" ], "study_properties" : [ "ot:studyPublicationReference", "is_deprecated", "ot:focalCladeOTTTaxonName", "ot:studyLastEditor", "ot:studyModified", "ot:studyLabel", "ot:comment", "ot:studyId", "ot:dataDeposit", "ot:authorContributed", "ot:studyUploaded", "ot:studyYear", "ot:focalCladeTaxonName", "ot:tag", "ot:curatorName", "ot:studyPublication", "ot:focalCladeOTTId", "ot:focalClade" ] } -``` \ No newline at end of file +``` From d074445eb8338c3327d545d5eafa99d571807ac9 Mon Sep 17 00:00:00 2001 From: Cody Hinchliff Date: Wed, 10 Sep 2014 21:40:28 -0400 Subject: [PATCH 12/13] doc improvements and code cleanup --- .../org/opentree/oti/plugins/studies.java | 63 ++++++++++++------- 1 file changed, 41 insertions(+), 22 deletions(-) diff --git a/src/main/java/org/opentree/oti/plugins/studies.java b/src/main/java/org/opentree/oti/plugins/studies.java index 94b06c6..9e538d7 100644 --- a/src/main/java/org/opentree/oti/plugins/studies.java +++ b/src/main/java/org/opentree/oti/plugins/studies.java @@ -40,16 +40,25 @@ public class studies extends ServerPlugin { @Description("Perform a simple search for indexed studies. To find all studies, omit both the property and the value from your query.") @PluginTarget(GraphDatabaseService.class) public Representation find_studies(@Source GraphDatabaseService graphDb, - @Description("The property to be searched on. A list of searchable properties is available from the getSearchablePropertiesForStudies service." - + "To find all studies, omit both the property and the value from your query.") - @Parameter(name = "property", optional = true) String property, - @Description("The value to be searched. This must be passed as a string, but will be converted to the datatype corresponding to the " - + "specified searchable value. To find all studies, omit both the property and the value from your query.") - @Parameter(name = "value", optional = true) String value, - @Description("Whether to perform exact matching ONLY. Defaults to false, i.e. fuzzy matching is enabled. Fuzzy matching is only applicable for some string properties.") - @Parameter(name="exact", optional = true) Boolean checkExactOnly, + @Description("The property to be searched on. A list of searchable properties is available from the " + + "[properties](#properties) service. To find all studies, omit both the property and the value from your query.") + @Parameter(name = "property", optional = true) + String property, + + @Description("The value to be searched. This must be passed as a string, but will be converted to the datatype " + + "corresponding to the specified searchable value. To find all studies, omit both the property and the " + + "value from your query.") + @Parameter(name = "value", optional = true) + String value, + + @Description("Whether to perform exact matching ONLY. Defaults to false, i.e. fuzzy matching is enabled. Fuzzy" + + "matching is only available for some string properties.") + @Parameter(name="exact", optional = true) + Boolean checkExactOnly, + @Description("Whether or not to include all metadata. By default, only the nexson ids of elements will be returned.") - @Parameter(name = "verbose", optional = true) Boolean verbose) throws ParseException { + @Parameter(name = "verbose", optional = true) + Boolean verbose) throws ParseException { // set null optional parameters to default values verbose = verbose == null ? false : verbose; @@ -90,17 +99,27 @@ public Representation find_studies(@Source GraphDatabaseService graphDb, * @param value * @return */ - @Description("Perform a simple search for trees in indexed studies") + @Description("Perform a simple search for trees in indexed studies.") @PluginTarget(GraphDatabaseService.class) public Representation find_trees(@Source GraphDatabaseService graphDb, - @Description("The property to be searched on. A list of searchable properties is available from the getSearchablePropertiesForTrees service.") - @Parameter(name = "property", optional = false) String property, - @Description("The value to be searched. This must be passed as a string, but will be converted to the datatype corresponding to the " - + "specified searchable value.") @Parameter(name = "value", optional = false) String value, - @Description("Whether to perform exact matching ONLY. Defaults to false, i.e. fuzzy matching is enabled. Only applicable for some string properties.") - @Parameter(name="exact", optional = true) Boolean checkExactOnly, + @Description("The property to be searched on. A list of searchable properties is available from the " + + "[properties](#properties) service.") + @Parameter(name = "property", optional = false) + String property, + + @Description("The value to be searched. This must be passed as a string, but will be converted to the datatype " + + "corresponding to the specified searchable value.") + @Parameter(name = "value", optional = false) + String value, + + @Description("Whether to perform exact matching ONLY. Defaults to false, i.e. fuzzy matching is enabled. Only " + + "applicable for some string properties.") + @Parameter(name="exact", optional = true) + Boolean checkExactOnly, + @Description("Whether or not to include all metadata. By default, only the nexson ids of elements will be returned.") - @Parameter(name = "verbose", optional = true) Boolean verbose) { + @Parameter(name = "verbose", optional = true) + Boolean verbose) { // set null optional parameters to default values verbose = verbose == null ? false : verbose; @@ -153,7 +172,9 @@ public Representation properties (@Source GraphDatabaseService graphDb) { "array containing the study ids for the studies that were successfully read and indexed.") @PluginTarget(GraphDatabaseService.class) public Representation index_studies(@Source GraphDatabaseService graphDb, - @Description("remote nexson urls") @Parameter(name = "urls", optional = false) String[] urls) throws MalformedURLException, IOException { + @Description("remote nexson urls") + @Parameter(name = "urls", optional = false) + String[] urls) throws MalformedURLException, IOException { if (urls.length < 1) { throw new IllegalArgumentException("You must provide at least one url for a nexson document to be indexed."); @@ -165,10 +186,8 @@ public Representation index_studies(@Source GraphDatabaseService graphDb, for (int i = 0; i < urls.length; i++) { try { NexsonSource study = readRemoteNexson(urls[i]); -// if (study.getTrees().iterator().hasNext()) { - manager.addOrReplaceStudy(study); - indexedIDs.add(study.getId()); -// } + manager.addOrReplaceStudy(study); + indexedIDs.add(study.getId()); } catch (Exception ex) { idsWithErrors.put(urls[i], ex.getMessage()); } From 745b777e6a8658aada8016680afb9fa14b538965 Mon Sep 17 00:00:00 2001 From: Cody Hinchliff Date: Wed, 10 Sep 2014 22:09:23 -0400 Subject: [PATCH 13/13] minor doc edits --- src/main/java/org/opentree/oti/plugins/studies.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/opentree/oti/plugins/studies.java b/src/main/java/org/opentree/oti/plugins/studies.java index 9e538d7..0bdb4ed 100644 --- a/src/main/java/org/opentree/oti/plugins/studies.java +++ b/src/main/java/org/opentree/oti/plugins/studies.java @@ -51,7 +51,7 @@ public Representation find_studies(@Source GraphDatabaseService graphDb, @Parameter(name = "value", optional = true) String value, - @Description("Whether to perform exact matching ONLY. Defaults to false, i.e. fuzzy matching is enabled. Fuzzy" + @Description("Whether to perform exact matching ONLY. Defaults to false, i.e. fuzzy matching is enabled. Fuzzy " + "matching is only available for some string properties.") @Parameter(name="exact", optional = true) Boolean checkExactOnly, @@ -112,8 +112,8 @@ public Representation find_trees(@Source GraphDatabaseService graphDb, @Parameter(name = "value", optional = false) String value, - @Description("Whether to perform exact matching ONLY. Defaults to false, i.e. fuzzy matching is enabled. Only " - + "applicable for some string properties.") + @Description("Whether to perform exact matching ONLY. Defaults to false, i.e. fuzzy matching is enabled. Fuzzy " + + "matching is only available for some string properties.") @Parameter(name="exact", optional = true) Boolean checkExactOnly,