diff --git a/julielab-neo4j-plugins-concepts-representation/pom.xml b/julielab-neo4j-plugins-concepts-representation/pom.xml index 04283ee..4c47711 100644 --- a/julielab-neo4j-plugins-concepts-representation/pom.xml +++ b/julielab-neo4j-plugins-concepts-representation/pom.xml @@ -4,7 +4,7 @@ de.julielab julielab-neo4j-server-plugins - 2.1.0-SNAPSHOT + 2.1.0 julielab-neo4j-plugins-concepts-representation @@ -20,7 +20,7 @@ com.fasterxml.jackson.datatype jackson-datatype-jdk8 - ${jackson-release-version} + 2.9.9 \ No newline at end of file diff --git a/julielab-neo4j-plugins-concepts-representation/src/main/java/de/julielab/neo4j/plugins/datarepresentation/ConceptCoordinates.java b/julielab-neo4j-plugins-concepts-representation/src/main/java/de/julielab/neo4j/plugins/datarepresentation/ConceptCoordinates.java index e5e33f5..f1f0222 100644 --- a/julielab-neo4j-plugins-concepts-representation/src/main/java/de/julielab/neo4j/plugins/datarepresentation/ConceptCoordinates.java +++ b/julielab-neo4j-plugins-concepts-representation/src/main/java/de/julielab/neo4j/plugins/datarepresentation/ConceptCoordinates.java @@ -1,11 +1,5 @@ package de.julielab.neo4j.plugins.datarepresentation; -import org.neo4j.shell.util.json.JSONException; -import org.neo4j.shell.util.json.JSONObject; - -import de.julielab.neo4j.plugins.auxiliaries.JSON; -import de.julielab.neo4j.plugins.datarepresentation.constants.CoordinateConstants; - public class ConceptCoordinates implements Cloneable { public String sourceId; @@ -48,30 +42,6 @@ public ConceptCoordinates(String id, String source, CoordinateType src) { } } - public ConceptCoordinates(JSONObject jsonObject) throws JSONException { - this(jsonObject, true); - } - - public ConceptCoordinates(JSONObject jsonObject, boolean checkConsistency) throws JSONException { - sourceId = JSON.getString(jsonObject, CoordinateConstants.SOURCE_ID); - source = JSON.getString(jsonObject, CoordinateConstants.SOURCE); - originalId = JSON.getString(jsonObject, CoordinateConstants.ORIGINAL_ID); - originalSource = JSON.getString(jsonObject, CoordinateConstants.ORIGINAL_SOURCE); - uniqueSourceId = JSON.getBoolean(jsonObject, CoordinateConstants.UNIQUE_SOURCE_ID); - - if (checkConsistency) { - if (sourceId == null && source == null && originalId == null && originalSource == null) - throw new CoordinatesInvalidException( - "The passed concept coordinates JSON object did not specify any IDs or sources"); - - if (originalId == null ^ originalSource == null) - throw new CoordinatesInvalidException( - "Coordinates JSON specifies originalId / original source of (" + originalId + ", " - + originalSource + ") but when one is not null, the other must be given, too."); - } - } - - public ConceptCoordinates(ConceptCoordinates coordinates) { this.originalId = coordinates.originalId; diff --git a/julielab-neo4j-plugins-concepts-representation/src/main/java/de/julielab/neo4j/plugins/datarepresentation/ImportConcept.java b/julielab-neo4j-plugins-concepts-representation/src/main/java/de/julielab/neo4j/plugins/datarepresentation/ImportConcept.java index 1eefee6..a54ce1d 100644 --- a/julielab-neo4j-plugins-concepts-representation/src/main/java/de/julielab/neo4j/plugins/datarepresentation/ImportConcept.java +++ b/julielab-neo4j-plugins-concepts-representation/src/main/java/de/julielab/neo4j/plugins/datarepresentation/ImportConcept.java @@ -7,190 +7,193 @@ public class ImportConcept { - public ImportConcept(String preferredName, ConceptCoordinates coordinates) { - prefName = preferredName; - this.coordinates = coordinates; - } - - public ImportConcept(String preferredName, String description, ConceptCoordinates coordinates) { - this(preferredName, coordinates); - this.descriptions = Arrays.asList(description); - } - - public ImportConcept(String preferredName, List synonyms, ConceptCoordinates coordinates) { - this(preferredName, coordinates); - this.synonyms = synonyms; - } - - public ImportConcept(String preferredName, List synonyms, String description, - ConceptCoordinates coordinates) { - this(preferredName, synonyms, coordinates); - this.descriptions = Arrays.asList(description); - } - - public ImportConcept(String preferredName, List synonyms, String description, - ConceptCoordinates coordinates, ConceptCoordinates parentCoordinates) { - this(preferredName, synonyms, Arrays.asList(description), coordinates, Arrays.asList(parentCoordinates)); - } - - public ImportConcept(String preferredName, List synonyms, String description, - ConceptCoordinates coordinates, List parentCoordinates) { - this(preferredName, synonyms, Arrays.asList(description), coordinates, parentCoordinates); - } - - public ImportConcept(String preferredName, List synonyms, List descriptions, - ConceptCoordinates coordinates) { - this(preferredName, synonyms, coordinates); - this.descriptions = descriptions; - } - - public ImportConcept(String preferredName, List synonyms, List descriptions, - ConceptCoordinates coordinates, ConceptCoordinates parentCoordinates) { - this(preferredName, synonyms, descriptions, coordinates); + @JsonProperty(ConceptConstants.PROP_PREF_NAME) + public String prefName; + @JsonProperty(ConceptConstants.PROP_DESCRIPTIONS) + public List descriptions = Collections.emptyList(); + @JsonProperty(ConceptConstants.PROP_SYNONYMS) + public List synonyms = Collections.emptyList(); + @JsonProperty(ConceptConstants.PROP_WRITING_VARIANTS) + public List writingVariants = Collections.emptyList(); + @JsonProperty(ConceptConstants.COORDINATES) + public ConceptCoordinates coordinates; + @JsonProperty(ConceptConstants.PARENT_COORDINATES) + public List parentCoordinates = Collections.emptyList(); + @JsonProperty(ConceptConstants.RELATIONSHIPS) + public List relationships = Collections.emptyList(); + @JsonProperty(ConceptConstants.PROP_LABELS) + public List generalLabels = Collections.emptyList(); + @JsonProperty(ConceptConstants.PROP_DISPLAY_NAME) + public String displayName; + @JsonProperty(ConceptConstants.PROP_QUALIFIERS) + public List qualifiers = Collections.emptyList(); + // ------------- for aggregates ----------------- + @JsonProperty(ConceptConstants.AGGREGATE) + public boolean aggregate; + @JsonProperty(ConceptConstants.ELEMENT_COORDINATES) + public List elementCoordinates = Collections.emptyList(); + @JsonProperty(ConceptConstants.PROP_COPY_PROPERTIES) + public List copyProperties = Collections.emptyList(); + @JsonProperty(ConceptConstants.AGGREGATE_INCLUDE_IN_HIERARCHY) + public boolean aggregateIncludeInHierarchy; + + public ImportConcept(String preferredName, ConceptCoordinates coordinates) { + prefName = preferredName; + this.coordinates = coordinates; + } + + public ImportConcept(String preferredName, String description, ConceptCoordinates coordinates) { + this(preferredName, coordinates); + if (description != null) + this.descriptions = Arrays.asList(description); + } + + public ImportConcept(String preferredName, List synonyms, ConceptCoordinates coordinates) { + this(preferredName, coordinates); + this.synonyms = synonyms; + } + + public ImportConcept(String preferredName, List synonyms, String description, + ConceptCoordinates coordinates) { + this(preferredName, synonyms, coordinates); + if (description != null) + this.descriptions = Arrays.asList(description); + } + + public ImportConcept(String preferredName, List synonyms, String description, + ConceptCoordinates coordinates, ConceptCoordinates parentCoordinates) { + this(preferredName, synonyms, Arrays.asList(description), coordinates, Arrays.asList(parentCoordinates)); + } + + public ImportConcept(String preferredName, List synonyms, String description, + ConceptCoordinates coordinates, List parentCoordinates) { + this(preferredName, synonyms, Arrays.asList(description), coordinates, parentCoordinates); + } + + public ImportConcept(String preferredName, List synonyms, List descriptions, + ConceptCoordinates coordinates) { + this(preferredName, synonyms, coordinates); + this.descriptions = descriptions; + } + + public ImportConcept(String preferredName, List synonyms, List descriptions, + ConceptCoordinates coordinates, ConceptCoordinates parentCoordinates) { + this(preferredName, synonyms, descriptions, coordinates); if (parentCoordinates == null) throw new IllegalArgumentException("The passed parent coordinates are null which is invalid (pass an empty list instead)."); - this.parentCoordinates = Arrays.asList(parentCoordinates); - } + if (parentCoordinates != null) + this.parentCoordinates = Arrays.asList(parentCoordinates); + } - public ImportConcept(String preferredName, List synonyms, List descriptions, - ConceptCoordinates coordinates, List parentCoordinates) { - this(preferredName, synonyms, descriptions, coordinates); + public ImportConcept(String preferredName, List synonyms, List descriptions, + ConceptCoordinates coordinates, List parentCoordinates) { + this(preferredName, synonyms, descriptions, coordinates); if (parentCoordinates == null) throw new IllegalArgumentException("The passed parent coordinates are null which is invalid (pass an empty list instead)."); - this.parentCoordinates = parentCoordinates; - } + if (parentCoordinates != null) + this.parentCoordinates = parentCoordinates; + } - public ImportConcept(String preferredName, ConceptCoordinates coordinates, ConceptCoordinates parentCoordinates) { - this(preferredName, coordinates); + public ImportConcept(String preferredName, ConceptCoordinates coordinates, ConceptCoordinates parentCoordinates) { + this(preferredName, coordinates); if (parentCoordinates == null) throw new IllegalArgumentException("The passed parent coordinates are null which is invalid (pass an empty list instead)."); - this.parentCoordinates = Arrays.asList(parentCoordinates); - } - - public ImportConcept(String preferredName, ConceptCoordinates coordinates, - List parentCoordinates) { - this(preferredName, coordinates); - if (parentCoordinates == null) - throw new IllegalArgumentException("The passed parent coordinates are null which is invalid (pass an empty list instead)."); - this.parentCoordinates = parentCoordinates; - } - - /** - * Constructor for aggregate terms. - * - * @param elementCoords - * Coordinates of the elements to be aggregated. - * @param copyProperties - * The properties that should be copied from elements to the - * aggregates. - */ - public ImportConcept(List elementCoords, List copyProperties) { - this.elementCoordinates = elementCoords; - this.copyProperties = copyProperties; - this.aggregate = true; - } - - public ImportConcept(ConceptCoordinates conceptCoordinates) { - coordinates = conceptCoordinates; - } - - public ImportConcept() { - } - - @JsonProperty(ConceptConstants.PROP_PREF_NAME) - public String prefName; - @JsonProperty(ConceptConstants.PROP_DESCRIPTIONS) - public List descriptions = Collections.emptyList(); - @JsonProperty(ConceptConstants.PROP_SYNONYMS) - public List synonyms = Collections.emptyList(); - @JsonProperty(ConceptConstants.PROP_WRITING_VARIANTS) - public List writingVariants = Collections.emptyList(); - @JsonProperty(ConceptConstants.COORDINATES) - public ConceptCoordinates coordinates; - @JsonProperty(ConceptConstants.PARENT_COORDINATES) - public List parentCoordinates = Collections.emptyList(); - @JsonProperty(ConceptConstants.RELATIONSHIPS) - public List relationships = Collections.emptyList(); - @JsonProperty(ConceptConstants.PROP_LABELS) - public List generalLabels = Collections.emptyList(); - @JsonProperty(ConceptConstants.PROP_DISPLAY_NAME) - public String displayName; - @JsonProperty(ConceptConstants.PROP_QUALIFIERS) - public List qualifiers = Collections.emptyList(); - - // ------------- for aggregates ----------------- - @JsonProperty(ConceptConstants.AGGREGATE) - public Boolean aggregate; - @JsonProperty(ConceptConstants.ELEMENT_COORDINATES) - public List elementCoordinates = Collections.emptyList(); - @JsonProperty(ConceptConstants.PROP_COPY_PROPERTIES) - public List copyProperties = Collections.emptyList(); - @JsonProperty(ConceptConstants.AGGREGATE_INCLUDE_IN_HIERARCHY) - public Boolean aggregateIncludeInHierarchy; - - public void addRelationship(ImportConceptRelationship relationship) { - if (relationships.isEmpty()) - relationships = new ArrayList<>(); - relationships.add(relationship); - } - - public void addGeneralLabel(String... labels) { - if (generalLabels.isEmpty()) - generalLabels = new ArrayList<>(); - try { - for (int i = 0; i < labels.length; i++) { - String label = labels[i]; - generalLabels.add(label); - } - } catch (java.lang.UnsupportedOperationException e) { - generalLabels = new ArrayList<>(generalLabels); - addGeneralLabel(labels); - } - } - - public void addCopyProperty(String property) { - if (copyProperties.isEmpty()) - copyProperties = new ArrayList<>(); - copyProperties.add(property); - } - - public void addQualifier(String speciesQualifier) { - if (qualifiers.isEmpty()) - qualifiers = new ArrayList<>(); - qualifiers.add(speciesQualifier); - } - - public void removeGeneralLabel(String... labels) { - if (generalLabels.isEmpty()) - return; - Set removeLabels = new HashSet<>(labels.length); - for (int i = 0; i < labels.length; i++) { - String label = labels[i]; - removeLabels.add(label); - } - Iterator existingLabels = generalLabels.iterator(); - while (existingLabels.hasNext()) { - String existingLabel = existingLabels.next(); - if (removeLabels.contains(existingLabel)) - existingLabels.remove(); - } - - } - - public void addParent(ConceptCoordinates parentCoordinates) { - if (this.parentCoordinates.isEmpty()) - this.parentCoordinates = new ArrayList<>(); - this.parentCoordinates.add(parentCoordinates); - } - - public void addParentIfNotExists(ConceptCoordinates parentCoordinates) { - if (this.parentCoordinates.isEmpty() || !this.parentCoordinates.contains(parentCoordinates)) - addParent(parentCoordinates); - } - - public boolean hasParents() { - return !parentCoordinates.isEmpty(); - } - - + if (parentCoordinates != null) + this.parentCoordinates = Arrays.asList(parentCoordinates); + } + + public ImportConcept(String preferredName, ConceptCoordinates coordinates, + List parentCoordinates) { + this(preferredName, coordinates); + if (parentCoordinates == null) + throw new IllegalArgumentException("The passed parent coordinates are null which is invalid (pass an empty list instead)."); + if (parentCoordinates != null) + this.parentCoordinates = parentCoordinates; + } + + /** + * Constructor for aggregate terms. + * + * @param elementCoords Coordinates of the elements to be aggregated. + * @param copyProperties The properties that should be copied from elements to the + * aggregates. + */ + public ImportConcept(List elementCoords, List copyProperties) { + this.elementCoordinates = elementCoords; + this.copyProperties = copyProperties; + this.aggregate = true; + } + + public ImportConcept(ConceptCoordinates conceptCoordinates) { + coordinates = conceptCoordinates; + } + + public ImportConcept() { + } + + public void addRelationship(ImportConceptRelationship relationship) { + if (relationships.isEmpty()) + relationships = new ArrayList<>(); + relationships.add(relationship); + } + + public void addGeneralLabel(String... labels) { + if (generalLabels.isEmpty()) + generalLabels = new ArrayList<>(); + try { + for (int i = 0; i < labels.length; i++) { + String label = labels[i]; + generalLabels.add(label); + } + } catch (java.lang.UnsupportedOperationException e) { + generalLabels = new ArrayList<>(generalLabels); + addGeneralLabel(labels); + } + } + + public void addCopyProperty(String property) { + if (copyProperties.isEmpty()) + copyProperties = new ArrayList<>(); + copyProperties.add(property); + } + + public void addQualifier(String speciesQualifier) { + if (qualifiers.isEmpty()) + qualifiers = new ArrayList<>(); + qualifiers.add(speciesQualifier); + } + + public void removeGeneralLabel(String... labels) { + if (generalLabels.isEmpty()) + return; + Set removeLabels = new HashSet<>(labels.length); + for (int i = 0; i < labels.length; i++) { + String label = labels[i]; + removeLabels.add(label); + } + Iterator existingLabels = generalLabels.iterator(); + while (existingLabels.hasNext()) { + String existingLabel = existingLabels.next(); + if (removeLabels.contains(existingLabel)) + existingLabels.remove(); + } + + } + + public void addParent(ConceptCoordinates parentCoordinates) { + if (this.parentCoordinates.isEmpty()) + this.parentCoordinates = new ArrayList<>(); + this.parentCoordinates.add(parentCoordinates); + } + + public void addParentIfNotExists(ConceptCoordinates parentCoordinates) { + if (this.parentCoordinates.isEmpty() || !this.parentCoordinates.contains(parentCoordinates)) + addParent(parentCoordinates); + } + + public boolean hasParents() { + return !parentCoordinates.isEmpty(); + } + + } diff --git a/julielab-neo4j-plugins-concepts-representation/src/main/java/de/julielab/neo4j/plugins/datarepresentation/ImportConceptRelationship.java b/julielab-neo4j-plugins-concepts-representation/src/main/java/de/julielab/neo4j/plugins/datarepresentation/ImportConceptRelationship.java index c083790..b8bca00 100644 --- a/julielab-neo4j-plugins-concepts-representation/src/main/java/de/julielab/neo4j/plugins/datarepresentation/ImportConceptRelationship.java +++ b/julielab-neo4j-plugins-concepts-representation/src/main/java/de/julielab/neo4j/plugins/datarepresentation/ImportConceptRelationship.java @@ -20,6 +20,9 @@ public class ImportConceptRelationship { @JsonProperty(ConceptConstants.RS_PROPS) public Map properties; + public ImportConceptRelationship() { + } + public ImportConceptRelationship(ConceptCoordinates targetCoordinates, String relationType) { this.targetCoordinates = targetCoordinates; this.type = relationType; diff --git a/julielab-neo4j-plugins-concepts-representation/src/main/java/de/julielab/neo4j/plugins/datarepresentation/ImportConcepts.java b/julielab-neo4j-plugins-concepts-representation/src/main/java/de/julielab/neo4j/plugins/datarepresentation/ImportConcepts.java index 382ade3..e01473c 100644 --- a/julielab-neo4j-plugins-concepts-representation/src/main/java/de/julielab/neo4j/plugins/datarepresentation/ImportConcepts.java +++ b/julielab-neo4j-plugins-concepts-representation/src/main/java/de/julielab/neo4j/plugins/datarepresentation/ImportConcepts.java @@ -1,27 +1,25 @@ package de.julielab.neo4j.plugins.datarepresentation; -import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; -import com.fasterxml.jackson.annotation.JsonIgnore; - public class ImportConcepts { - private Stream concepts; - private List conceptsAsList; + private List concepts; private ImportFacet facet; private ImportOptions importOptions; + public ImportConcepts(){} + public ImportConcepts(ImportFacet facet) { this.facet = facet; } public ImportConcepts(Stream termList, ImportFacet facet) { - this.concepts = termList; - this.facet = facet; + this(termList != null ? termList.collect(Collectors.toList()) : Collections.emptyList(), facet); } public ImportConcepts(Stream termList, ImportFacet importFacet, ImportOptions importOptions) { @@ -29,9 +27,10 @@ public ImportConcepts(Stream termList, ImportFacet importFacet, I this.importOptions = importOptions; } + /** * Constructor for an already existing list of concepts. The list will directly - * be used for {@link #getConcepts()} and {@link #getConceptsAsList()}; + * be used for {@link #getConcepts()} and {@link #getConcepts()}; * * @param concepts * The list of concepts. @@ -39,13 +38,13 @@ public ImportConcepts(Stream termList, ImportFacet importFacet, I * The facet to add the concepts to. */ public ImportConcepts(List concepts, ImportFacet importFacet) { - this((Stream) null, importFacet); - this.conceptsAsList = concepts; + this.concepts = concepts; + this.facet = importFacet; } /** * Constructor for an already existing list of concepts. The list will directly - * be used for {@link #getConcepts()} and {@link #getConceptsAsList()}; + * be used for {@link #getConcepts()} and {@link #getConcepts()}; * * @param concepts * The list of concepts. @@ -56,46 +55,21 @@ public ImportConcepts(List concepts, ImportFacet importFacet) { */ public ImportConcepts(List concepts, ImportFacet importFacet, ImportOptions importOptions) { this((Stream) null, importFacet, importOptions); - this.conceptsAsList = concepts; } /** * Returns the concepts as a stream. This may be the single, original stream * given to the constructor, or a stream derived from a underlying list in case * a list of concepts was passed to a constructor or - * {@link #getConceptsAsList()} was called at least once. + * {@link #getConcepts()} was called at least once. * * @return The concepts as a stream. */ - public Stream getConcepts() { - if (conceptsAsList != null) - return conceptsAsList.stream(); + public List getConcepts() { return concepts; } - /** - *

- * If index-based access to the concepts is required, this method can be called. - * If one of the constructors was called taking a stream of ImportConcepts, this - * causes the concept stream to be collected into a list. Starting from the - * first call of this method, only the list representation will then be used. - * Even {@link #getConcepts()} will return a new stream created from the list. - * Thus, this method comes with a - possibly minor - performance penalty. - *

- *

- * In case that one of the constructors taking a list of concepts was used, this - * is the method to go. - *

- * - * @return The concepts as list. - */ - @JsonIgnore - public List getConceptsAsList() { - if (conceptsAsList == null) { - conceptsAsList = concepts.collect(Collectors.toCollection(ArrayList::new)); - } - return conceptsAsList; - } + public ImportFacet getFacet() { return facet; @@ -105,7 +79,7 @@ public ImportOptions getImportOptions() { return importOptions; } - public void setConcepts(Stream concepts) { + public void setConcepts(List concepts) { this.concepts = concepts; } diff --git a/julielab-neo4j-plugins-concepts-representation/src/main/java/de/julielab/neo4j/plugins/datarepresentation/ImportFacet.java b/julielab-neo4j-plugins-concepts-representation/src/main/java/de/julielab/neo4j/plugins/datarepresentation/ImportFacet.java index 00bb973..22fd362 100644 --- a/julielab-neo4j-plugins-concepts-representation/src/main/java/de/julielab/neo4j/plugins/datarepresentation/ImportFacet.java +++ b/julielab-neo4j-plugins-concepts-representation/src/main/java/de/julielab/neo4j/plugins/datarepresentation/ImportFacet.java @@ -1,16 +1,15 @@ package de.julielab.neo4j.plugins.datarepresentation; -import static de.julielab.neo4j.plugins.datarepresentation.constants.FacetConstants.FACET_GROUP; -import static de.julielab.neo4j.plugins.datarepresentation.constants.FacetConstants.PROP_SOURCE_TYPE; -import static de.julielab.neo4j.plugins.datarepresentation.constants.NodeConstants.PROP_LABELS; -import static de.julielab.neo4j.plugins.datarepresentation.constants.NodeConstants.PROP_NAME; +import com.fasterxml.jackson.annotation.JsonProperty; +import de.julielab.neo4j.plugins.datarepresentation.constants.FacetConstants; import java.util.ArrayList; import java.util.Collection; -import com.fasterxml.jackson.annotation.JsonProperty; - -import de.julielab.neo4j.plugins.datarepresentation.constants.FacetConstants; +import static de.julielab.neo4j.plugins.datarepresentation.constants.FacetConstants.FACET_GROUP; +import static de.julielab.neo4j.plugins.datarepresentation.constants.FacetConstants.PROP_SOURCE_TYPE; +import static de.julielab.neo4j.plugins.datarepresentation.constants.NodeConstants.PROP_LABELS; +import static de.julielab.neo4j.plugins.datarepresentation.constants.NodeConstants.PROP_NAME; public class ImportFacet { /** @@ -42,7 +41,24 @@ public class ImportFacet { protected String shortName; @JsonProperty(PROP_SOURCE_TYPE) protected String sourceType; - /** + + public ImportFacet(){} + + @Override + public String toString() { + return "ImportFacet{" + + "customId='" + customId + '\'' + + ", facetGroup=" + facetGroup + + ", id='" + id + '\'' + + ", labels=" + labels + + ", name='" + name + '\'' + + ", noFacet=" + noFacet + + ", shortName='" + shortName + '\'' + + ", sourceType='" + sourceType + '\'' + + '}'; + } + + /** * Constructor eligible for creating new facets in the database. * * @param facetGroup diff --git a/julielab-neo4j-plugins-concepts-representation/src/main/java/de/julielab/neo4j/plugins/datarepresentation/ImportFacetGroup.java b/julielab-neo4j-plugins-concepts-representation/src/main/java/de/julielab/neo4j/plugins/datarepresentation/ImportFacetGroup.java index ffcb7fb..bc61dda 100644 --- a/julielab-neo4j-plugins-concepts-representation/src/main/java/de/julielab/neo4j/plugins/datarepresentation/ImportFacetGroup.java +++ b/julielab-neo4j-plugins-concepts-representation/src/main/java/de/julielab/neo4j/plugins/datarepresentation/ImportFacetGroup.java @@ -1,11 +1,10 @@ package de.julielab.neo4j.plugins.datarepresentation; -import java.util.List; - import com.fasterxml.jackson.annotation.JsonProperty; - import de.julielab.neo4j.plugins.datarepresentation.constants.FacetGroupConstants; +import java.util.List; + public class ImportFacetGroup { public ImportFacetGroup(String name, int position, List generalLabels) { this.name = name; @@ -13,7 +12,18 @@ public ImportFacetGroup(String name, int position, List generalLabels) { this.labels = generalLabels; } - public ImportFacetGroup(String name) { + public ImportFacetGroup(){} + + @Override + public String toString() { + return "ImportFacetGroup{" + + "name='" + name + '\'' + + ", labels=" + labels + + ", type='" + type + '\'' + + '}'; + } + + public ImportFacetGroup(String name) { this.name = name; } diff --git a/julielab-neo4j-plugins-concepts-representation/src/main/java/de/julielab/neo4j/plugins/datarepresentation/constants/ConceptConstants.java b/julielab-neo4j-plugins-concepts-representation/src/main/java/de/julielab/neo4j/plugins/datarepresentation/constants/ConceptConstants.java index a5056ed..9459f98 100644 --- a/julielab-neo4j-plugins-concepts-representation/src/main/java/de/julielab/neo4j/plugins/datarepresentation/constants/ConceptConstants.java +++ b/julielab-neo4j-plugins-concepts-representation/src/main/java/de/julielab/neo4j/plugins/datarepresentation/constants/ConceptConstants.java @@ -1,7 +1,5 @@ package de.julielab.neo4j.plugins.datarepresentation.constants; -import de.julielab.neo4j.plugins.datarepresentation.ConceptCoordinates; - public class ConceptConstants extends NodeConstants { diff --git a/julielab-neo4j-plugins-concepts-representation/src/main/java/de/julielab/neo4j/plugins/datarepresentation/util/ConceptsJsonSerializer.java b/julielab-neo4j-plugins-concepts-representation/src/main/java/de/julielab/neo4j/plugins/datarepresentation/util/ConceptsJsonSerializer.java index 73eaef1..d2a43ce 100644 --- a/julielab-neo4j-plugins-concepts-representation/src/main/java/de/julielab/neo4j/plugins/datarepresentation/util/ConceptsJsonSerializer.java +++ b/julielab-neo4j-plugins-concepts-representation/src/main/java/de/julielab/neo4j/plugins/datarepresentation/util/ConceptsJsonSerializer.java @@ -2,9 +2,12 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; +import java.io.IOException; + public class ConceptsJsonSerializer { private ConceptsJsonSerializer() { } @@ -22,4 +25,12 @@ public static synchronized String toJson(Object serializable) { throw new UncheckedJsonProcessingException(e); } } + + public static synchronized T fromJson(String json, Class cls) throws IOException { + return mapper.readValue(json, cls); + } + + public static synchronized T fromJson(String json, TypeReference ref) throws IOException { + return mapper.readValue(json, ref); + } } diff --git a/julielab-neo4j-plugins-concepts/.gitignore b/julielab-neo4j-plugins-concepts/.gitignore index 23c8321..6f610d6 100644 --- a/julielab-neo4j-plugins-concepts/.gitignore +++ b/julielab-neo4j-plugins-concepts/.gitignore @@ -3,3 +3,4 @@ /.project /.settings/ /src/test/resources/graph.db/ +/.idea \ No newline at end of file diff --git a/julielab-neo4j-plugins-concepts/pom.xml b/julielab-neo4j-plugins-concepts/pom.xml index 55a3eb5..8bf04e8 100644 --- a/julielab-neo4j-plugins-concepts/pom.xml +++ b/julielab-neo4j-plugins-concepts/pom.xml @@ -4,7 +4,7 @@ de.julielab julielab-neo4j-server-plugins - 2.1.0-SNAPSHOT + 2.1.0 .. julielab-neo4j-plugins-concepts diff --git a/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/ConceptManager.java b/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/ConceptManager.java index 37bc99a..4d4eab7 100644 --- a/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/ConceptManager.java +++ b/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/ConceptManager.java @@ -1,20 +1,19 @@ package de.julielab.neo4j.plugins; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.Sets; import com.google.gson.Gson; import com.google.gson.stream.JsonReader; import de.julielab.neo4j.plugins.FacetManager.FacetLabel; -import de.julielab.neo4j.plugins.auxiliaries.JSON; import de.julielab.neo4j.plugins.auxiliaries.PropertyUtilities; import de.julielab.neo4j.plugins.auxiliaries.semedico.*; import de.julielab.neo4j.plugins.auxiliaries.semedico.ConceptAggregateBuilder.CopyAggregatePropertiesStatistics; import de.julielab.neo4j.plugins.constants.semedico.SequenceConstants; -import de.julielab.neo4j.plugins.datarepresentation.AddToNonFacetGroupCommand; -import de.julielab.neo4j.plugins.datarepresentation.ConceptCoordinates; -import de.julielab.neo4j.plugins.datarepresentation.ImportOptions; -import de.julielab.neo4j.plugins.datarepresentation.PushConceptsToSetCommand; +import de.julielab.neo4j.plugins.datarepresentation.*; import de.julielab.neo4j.plugins.datarepresentation.PushConceptsToSetCommand.ConceptSelectionDefinition; import de.julielab.neo4j.plugins.datarepresentation.constants.*; +import de.julielab.neo4j.plugins.datarepresentation.util.ConceptsJsonSerializer; import de.julielab.neo4j.plugins.util.AggregateConceptInsertionException; import de.julielab.neo4j.plugins.util.ConceptInsertionException; import org.apache.commons.lang.StringUtils; @@ -30,9 +29,6 @@ import org.neo4j.server.rest.repr.MappingRepresentation; import org.neo4j.server.rest.repr.RecursiveMappingRepresentation; import org.neo4j.server.rest.repr.Representation; -import org.neo4j.shell.util.json.JSONArray; -import org.neo4j.shell.util.json.JSONException; -import org.neo4j.shell.util.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -142,11 +138,12 @@ public void buildAggregatesByMappings(@Source GraphDatabaseService graphDb, + " can be aggregate concepts (with the label AGGREGATE) or just plain concepts" + " (with the label CONCEPT) that are not an element of an aggregate.") @Parameter(name = KEY_AGGREGATED_LABEL) String aggregatedConceptsLabelString, @Description("Label to restrict the concepts to that are considered for aggregation creation.") @Parameter(name = KEY_LABEL, optional = true) String allowedConceptLabelString) - throws JSONException { - JSONArray allowedMappingTypesJson = new JSONArray(allowedMappingTypesArray); + throws IOException { + ObjectMapper om = new ObjectMapper(); + final String[] allowedMappingTypesJson = om.readValue(allowedMappingTypesArray, String[].class); Set allowedMappingTypes = new HashSet<>(); - for (int i = 0; i < allowedMappingTypesJson.length(); i++) { - allowedMappingTypes.add(allowedMappingTypesJson.getString(i)); + for (int i = 0; i < allowedMappingTypesJson.length; i++) { + allowedMappingTypes.add(allowedMappingTypesJson[i]); } Label aggregatedConceptsLabel = Label.label(aggregatedConceptsLabelString); Label allowedConceptLabel = StringUtils.isBlank(allowedConceptLabelString) ? null @@ -163,8 +160,7 @@ public void buildAggregatesByMappings(@Source GraphDatabaseService graphDb, public void deleteAggregatesByMappigs(@Source GraphDatabaseService graphDb, @Description("Label for concepts that have been processed by the aggregation algorithm. Such concepts" + " can be aggregate concepts (with the label AGGREGATE) or just plain concepts" - + " (with the label CONCEPT) that are not an element of an aggregate.") @Parameter(name = KEY_AGGREGATED_LABEL) String aggregatedConceptsLabelString) - throws JSONException { + + " (with the label CONCEPT) that are not an element of an aggregate.") @Parameter(name = KEY_AGGREGATED_LABEL) String aggregatedConceptsLabelString) { Label aggregatedConceptsLabel = Label.label(aggregatedConceptsLabelString); ConceptAggregateBuilder.deleteAggregates(graphDb, aggregatedConceptsLabel); } @@ -175,9 +171,9 @@ public void deleteAggregatesByMappigs(@Source GraphDatabaseService graphDb, @PluginTarget(GraphDatabaseService.class) public void buildAggregatesByNameAndSynonyms(@Source GraphDatabaseService graphDb, @Description("TODO") @Parameter(name = KEY_CONCEPT_PROP_KEY) String conceptPropertyKey, - @Description("TODO") @Parameter(name = KEY_CONCEPT_PROP_VALUES) String propertyValues) - throws JSONException { - JSONArray jsonPropertyValues = new JSONArray(propertyValues); + @Description("TODO") @Parameter(name = KEY_CONCEPT_PROP_VALUES) String propertyValues) throws IOException { + final ObjectMapper om = new ObjectMapper(); + final String[] jsonPropertyValues = om.readValue(propertyValues, String[].class); ConceptAggregateBuilder.buildAggregatesForEqualNames(graphDb, conceptPropertyKey, jsonPropertyValues); } @@ -226,9 +222,8 @@ private int copyAggregatePropertiesRecursively(Node aggregate, CopyAggregateProp return alreadySeen.size(); } - private void createRelationships(GraphDatabaseService graphDb, JSONArray jsonConcepts, Node facet, - CoordinatesMap nodesByCoordinates, ImportOptions importOptions, InsertionReport insertionReport) - throws JSONException { + private void createRelationships(GraphDatabaseService graphDb, List jsonConcepts, Node facet, + CoordinatesMap nodesByCoordinates, ImportOptions importOptions, InsertionReport insertionReport) { log.info("Creating relationship between inserted concepts."); Index idIndex = graphDb.index().forNodes(ConceptConstants.INDEX_NAME); String facetId = null; @@ -239,21 +234,21 @@ private void createRelationships(GraphDatabaseService graphDb, JSONArray jsonCon relBroaderThanInFacet = RelationshipType.withName(EdgeTypes.IS_BROADER_THAN.toString() + "_" + facetId); AddToNonFacetGroupCommand noFacetCmd = importOptions.noFacetCmd; Node noFacet = null; - int quarter = jsonConcepts.length() / 4; + int quarter = jsonConcepts.size() / 4; int numQuarter = 1; long totalTime = 0; long relCreationTime = 0; - for (int i = 0; i < jsonConcepts.length(); i++) { + for (int i = 0; i < jsonConcepts.size(); i++) { long time = System.currentTimeMillis(); - JSONObject jsonConcept = jsonConcepts.getJSONObject(i); + ImportConcept jsonConcept = jsonConcepts.get(i); // aggregates may be included into the taxonomy, but by default they // are not - if (JSON.getBoolean(jsonConcept, ConceptConstants.AGGREGATE) - && !JSON.getBoolean(jsonConcept, ConceptConstants.AGGREGATE_INCLUDE_IN_HIERARCHY)) + if (jsonConcept.aggregate + && !jsonConcept.aggregateIncludeInHierarchy) continue; - JSONObject coordinates = jsonConcept.getJSONObject(COORDINATES); + ConceptCoordinates coordinates = jsonConcept.coordinates; // Every concept must have a source ID... - String srcId = coordinates.getString(CoordinateConstants.SOURCE_ID); + String srcId = coordinates.sourceId; // ...but it is not required to have a parent in its source. // Then, it's a facet root. Node concept = nodesByCoordinates.get(new ConceptCoordinates(coordinates)); @@ -266,11 +261,9 @@ private void createRelationships(GraphDatabaseService graphDb, JSONArray jsonCon } // Default-relationships (taxonomical). { - if (jsonConcept.has(PARENT_COORDINATES) && jsonConcept.getJSONArray(PARENT_COORDINATES).length() > 0) { - JSONArray parentCoordinateArray = jsonConcept.getJSONArray(PARENT_COORDINATES); - for (int j = 0; j < parentCoordinateArray.length(); j++) { - ConceptCoordinates parentCoordinates = new ConceptCoordinates( - parentCoordinateArray.getJSONObject(j)); + final List parentCoordinateList = jsonConcept.parentCoordinates; + if (parentCoordinateList != null && !parentCoordinateList.isEmpty()) { + for (ConceptCoordinates parentCoordinates : parentCoordinateList) { String parentSrcId = parentCoordinates.sourceId; if (importOptions.cutParents.contains(parentSrcId)) { @@ -405,14 +398,11 @@ private void createRelationships(GraphDatabaseService graphDb, JSONArray jsonCon // is-mapped-to, // whatever...) { - if (jsonConcept.has(ConceptConstants.RELATIONSHIPS)) { + if (jsonConcept.relationships != null) { log.info("Adding explicitly specified relationships"); - JSONArray jsonRelationships = jsonConcept.getJSONArray(ConceptConstants.RELATIONSHIPS); - for (int j = 0; j < jsonRelationships.length(); j++) { - JSONObject jsonRelationship = jsonRelationships.getJSONObject(j); - String rsTypeStr = jsonRelationship.getString(ConceptConstants.RS_TYPE); - final JSONObject targetCoordinateJson = jsonRelationship.getJSONObject(ConceptConstants.RS_TARGET_COORDINATES); - final ConceptCoordinates targetCoordinates = new ConceptCoordinates(targetCoordinateJson); + for (ImportConceptRelationship jsonRelationship : jsonConcept.relationships) { + String rsTypeStr = jsonRelationship.type; + final ConceptCoordinates targetCoordinates = jsonRelationship.targetCoordinates; Node target = lookupConcept(targetCoordinates, idIndex); if (null == target) { log.debug("Creating hollow relationship target with orig Id/orig source " + targetCoordinates); @@ -420,15 +410,15 @@ private void createRelationships(GraphDatabaseService graphDb, JSONArray jsonCon } EdgeTypes type = EdgeTypes.valueOf(rsTypeStr); Object[] properties = null; - if (jsonRelationship.has(ConceptConstants.RS_PROPS)) { - JSONObject relProps = jsonRelationship.getJSONObject(ConceptConstants.RS_PROPS); - JSONArray propNames = relProps.names(); - properties = new Object[propNames.length() * 2]; - for (int k = 0; k < propNames.length(); ++k) { - String propName = propNames.getString(k); - Object propValue = relProps.get(propName); + if (jsonRelationship.properties != null) { + Set propNames = jsonRelationship.properties.keySet(); + properties = new Object[propNames.size() * 2]; + int k = 0; + for (String propName : propNames) { + Object propValue = jsonRelationship.properties.get(propName); properties[2 * k] = propName; properties[2 * k + 1] = propValue; + ++k; } } createRelationShipIfNotExists(concept, target, type, insertionReport, Direction.OUTGOING, @@ -582,18 +572,18 @@ public void createSchemaIndexes(@Source GraphDatabaseService graphDb) { @PluginTarget(GraphDatabaseService.class) public MappingRepresentation getChildrenOfConcepts(@Source GraphDatabaseService graphDb, @Description("JSON array of concept IDs for which to return their children.") @Parameter(name = KEY_CONCEPT_IDS) String conceptIdArray, - @Description("The label agsinst which the given concept IDs are resolved. Defaults to 'CONCEPT'.") @Parameter(name = KEY_LABEL, optional = true) String labelString) - throws JSONException { + @Description("The label agsinst which the given concept IDs are resolved. Defaults to 'CONCEPT'.") @Parameter(name = KEY_LABEL, optional = true) String labelString) throws IOException { Label label = ConceptLabel.CONCEPT; if (!StringUtils.isBlank(labelString)) label = Label.label(labelString); - JSONArray conceptIds = new JSONArray(conceptIdArray); + final ObjectMapper om = new ObjectMapper(); + final String[] conceptIds = om.readValue(conceptIdArray, String[].class); try (Transaction tx = graphDb.beginTx()) { Map childrenByConceptId = new HashMap<>(); - for (int i = 0; i < conceptIds.length(); i++) { + for (int i = 0; i < conceptIds.length; i++) { Map> reltypesByNodeId = new HashMap<>(); Set childList = new HashSet<>(); - String conceptId = conceptIds.getString(i); + String conceptId = conceptIds[i]; Node concept = NodeUtilities.findSingleNodeByLabelAndProperty(graphDb, label, PROP_ID, conceptId); if (null != concept) { Iterator rels = concept.getRelationships(Direction.OUTGOING).iterator(); @@ -648,30 +638,26 @@ public Representation getPathsFromFacetroots(@Source GraphDatabaseService graphD @Description("TODO") @Parameter(name = KEY_CONCEPT_IDS) String conceptIdsJsonString, @Description("TODO") @Parameter(name = KEY_ID_TYPE) String idType, @Description("TODO") @Parameter(name = KEY_SORT_RESULT) boolean sort, - @Description("TODO") @Parameter(name = KEY_FACET_ID) final String facetId) throws JSONException { - JSONArray conceptIds = new JSONArray(conceptIdsJsonString); - - Evaluator rootConceptEvaluator = new Evaluator() { - - @Override - public Evaluation evaluate(Path path) { - Node endNode = path.endNode(); - - Iterator iterator = endNode.getRelationships(EdgeTypes.HAS_ROOT_CONCEPT).iterator(); - if (iterator.hasNext()) { - if (StringUtils.isBlank(facetId)) { - return Evaluation.INCLUDE_AND_CONTINUE; - } else { - String[] facetIds = (String[]) endNode.getProperty(PROP_FACETS); - for (String facetIdOfRootNode : facetIds) { - if (facetIdOfRootNode.equals(facetId)) - return Evaluation.INCLUDE_AND_CONTINUE; - } + @Description("TODO") @Parameter(name = KEY_FACET_ID) final String facetId) throws IOException { + final ObjectMapper om = new ObjectMapper(); + final String[] conceptIds = om.readValue(conceptIdsJsonString, String[].class); + + Evaluator rootConceptEvaluator = path -> { + Node endNode = path.endNode(); + + Iterator iterator = endNode.getRelationships(EdgeTypes.HAS_ROOT_CONCEPT).iterator(); + if (iterator.hasNext()) { + if (StringUtils.isBlank(facetId)) { + return Evaluation.INCLUDE_AND_CONTINUE; + } else { + String[] facetIds = (String[]) endNode.getProperty(PROP_FACETS); + for (String facetIdOfRootNode : facetIds) { + if (facetIdOfRootNode.equals(facetId)) + return Evaluation.INCLUDE_AND_CONTINUE; } } - return Evaluation.EXCLUDE_AND_CONTINUE; } - + return Evaluation.EXCLUDE_AND_CONTINUE; }; RelationshipType relType = StringUtils.isBlank(facetId) ? ConceptManager.EdgeTypes.IS_BROADER_THAN : RelationshipType.withName(ConceptManager.EdgeTypes.IS_BROADER_THAN.name() + "_" + facetId); @@ -680,12 +666,12 @@ public Evaluation evaluate(Path path) { try (Transaction tx = graphDb.beginTx()) { StringBuilder sb = new StringBuilder(); - for (int i = 0; i < conceptIds.length(); i++) { - String conceptId = conceptIds.getString(i); + for (int i = 0; i < conceptIds.length; i++) { + String conceptId = conceptIds[i]; // escape the conceptId for the Lucene lookup conceptId = QueryParser.escape(conceptId); sb.append(idType).append(":").append(conceptId); - if (i < conceptIds.length() - 1) + if (i < conceptIds.length - 1) sb.append(" "); } String conceptQuery = sb.toString(); @@ -771,24 +757,23 @@ public int compare(String[] o1, String[] o2) { * @param insertionReport * @param importOptions * @return - * @throws JSONException * @throws AggregateConceptInsertionException */ - private void insertAggregateConcept(GraphDatabaseService graphDb, Index conceptIndex, JSONObject jsonConcept, + private void insertAggregateConcept(GraphDatabaseService graphDb, Index conceptIndex, ImportConcept jsonConcept, CoordinatesMap nodesByCoordinates, InsertionReport insertionReport, ImportOptions importOptions) throws AggregateConceptInsertionException { try { - JSONObject aggCoordinates = jsonConcept.has(COORDINATES) ? jsonConcept.getJSONObject(COORDINATES) - : new JSONObject(); - String aggOrgId = JSON.getString(aggCoordinates, CoordinateConstants.ORIGINAL_ID); - String aggOrgSource = JSON.getString(aggCoordinates, CoordinateConstants.ORIGINAL_SOURCE); - String aggSrcId = JSON.getString(aggCoordinates, CoordinateConstants.SOURCE_ID); - String aggSource = JSON.getString(aggCoordinates, CoordinateConstants.SOURCE); + ConceptCoordinates aggCoordinates = jsonConcept.coordinates != null ? jsonConcept.coordinates + : new ConceptCoordinates(); + String aggOrgId = aggCoordinates.originalId; + String aggOrgSource = aggCoordinates.originalSource; + String aggSrcId = aggCoordinates.sourceId; + String aggSource = aggCoordinates.source; if (null == aggSource) aggSource = UNKNOWN_CONCEPT_SOURCE; log.trace("Looking up aggregate ({}, {}) / ({}, {}), original/source coordinates.", aggOrgId, aggOrgSource, aggSrcId, aggSource); - Node aggregate = lookupConcept(new ConceptCoordinates(aggCoordinates, false), conceptIndex); + Node aggregate = lookupConcept(aggCoordinates, conceptIndex); if (null != aggregate) { String isHollowMessage = ""; if (aggregate.hasLabel(ConceptLabel.HOLLOW)) @@ -805,17 +790,14 @@ private void insertAggregateConcept(GraphDatabaseService graphDb, Index co log.trace(" aggregate is being created"); aggregate = graphDb.createNode(ConceptLabel.AGGREGATE); } - boolean includeAggreationInHierarchy = jsonConcept.has(AGGREGATE_INCLUDE_IN_HIERARCHY) - && jsonConcept.getBoolean(AGGREGATE_INCLUDE_IN_HIERARCHY); + boolean includeAggreationInHierarchy = jsonConcept.aggregateIncludeInHierarchy; // If the aggregate is to be included into the hierarchy, it also should // be a CONCEPT for path creation if (includeAggreationInHierarchy) aggregate.addLabel(ConceptLabel.CONCEPT); - JSONArray elementCoords = jsonConcept.getJSONArray(ConceptConstants.ELEMENT_COORDINATES); + List elementCoords = jsonConcept.elementCoordinates; log.trace(" looking up aggregate elements"); - for (int i = 0; i < elementCoords.length(); i++) { - JSONObject elementCoord = elementCoords.getJSONObject(i); - final ConceptCoordinates elementCoordinates = new ConceptCoordinates(elementCoord); + for (ConceptCoordinates elementCoordinates : elementCoords) { String elementSource = elementCoordinates.source; if (null == elementCoordinates.source) elementSource = UNKNOWN_CONCEPT_SOURCE; @@ -869,13 +851,13 @@ private void insertAggregateConcept(GraphDatabaseService graphDb, Index co aggregate.setProperty(PROP_ORG_ID, aggOrgId); if (null != aggOrgSource) aggregate.setProperty(PROP_ORG_SRC, aggOrgSource); - JSONArray copyProperties = JSON.getJSONArray(jsonConcept, ConceptConstants.PROP_COPY_PROPERTIES); - if (null != copyProperties && copyProperties.length() > 0) - aggregate.setProperty(ConceptConstants.PROP_COPY_PROPERTIES, JSON.json2JavaArray(copyProperties)); + List copyProperties = jsonConcept.copyProperties; + if (null != copyProperties && !copyProperties.isEmpty()) + aggregate.setProperty(ConceptConstants.PROP_COPY_PROPERTIES, copyProperties.toArray(new String[0])); - JSONArray generalLabels = JSON.getJSONArray(jsonConcept, ConceptConstants.PROP_LABELS); - for (int i = 0; null != generalLabels && i < generalLabels.length(); i++) { - aggregate.addLabel(Label.label(generalLabels.getString(i))); + List generalLabels = jsonConcept.generalLabels; + for (int i = 0; null != generalLabels && i < generalLabels.size(); i++) { + aggregate.addLabel(Label.label(generalLabels.get(i))); } String aggregateId = NodeIDPrefixConstants.AGGREGATE_TERM @@ -891,31 +873,31 @@ private void insertAggregateConcept(GraphDatabaseService graphDb, Index co } private void insertConcept(GraphDatabaseService graphDb, String facetId, Index conceptIndex, - JSONObject jsonConcept, CoordinatesMap nodesByCoordinates, InsertionReport insertionReport, - ImportOptions importOptions) throws JSONException { + ImportConcept jsonConcept, CoordinatesMap nodesByCoordinates, InsertionReport insertionReport, + ImportOptions importOptions) { // Name is mandatory, thus we don't use the // null-convenience method here. - String prefName = JSON.getString(jsonConcept, PROP_PREF_NAME); - JSONArray synonyms = JSON.getJSONArray(jsonConcept, PROP_SYNONYMS); - JSONArray generalLabels = JSON.getJSONArray(jsonConcept, ConceptConstants.PROP_LABELS); + String prefName = jsonConcept.prefName; + List synonyms = jsonConcept.synonyms; + List generalLabels = jsonConcept.generalLabels; - JSONObject coordinatesJson = jsonConcept.getJSONObject(COORDINATES); - ConceptCoordinates coordinates = new ConceptCoordinates(coordinatesJson); + ConceptCoordinates coordinates = jsonConcept.coordinates; - if (!jsonConcept.has(COORDINATES) || coordinatesJson.length() == 0) + if (coordinates == null) throw new IllegalArgumentException( - "The concept " + jsonConcept.toString(2) + " does not specify coordinates."); + "The concept " + jsonConcept + " does not specify coordinates."); // Source ID is mandatory if we have a real concept import and not just a // merging operation. - String srcId = importOptions.merge ? JSON.getString(coordinatesJson, CoordinateConstants.SOURCE_ID) - : coordinatesJson.getString(CoordinateConstants.SOURCE_ID); + if (!importOptions.merge && coordinates.sourceId == null) + throw new IllegalArgumentException("The concept " + jsonConcept + " does not specify a source ID."); // The other properties may have values or not, make it // null-proof. - String orgId = JSON.getString(coordinatesJson, CoordinateConstants.ORIGINAL_ID); - String source = JSON.getString(coordinatesJson, CoordinateConstants.SOURCE); - String orgSource = JSON.getString(coordinatesJson, CoordinateConstants.ORIGINAL_SOURCE); - boolean uniqueSourceId = JSON.getBoolean(coordinatesJson, CoordinateConstants.UNIQUE_SOURCE_ID, false); + String srcId = coordinates.sourceId; + String orgId = coordinates.originalId; + String source = coordinates.source; + String orgSource = coordinates.originalSource; + boolean uniqueSourceId = coordinates.uniqueSourceId; boolean srcIduniqueMarkerChanged = false; @@ -932,7 +914,7 @@ private void insertConcept(GraphDatabaseService graphDb, String facetId, Index relationships = concept.getRelationships(EdgeTypes.HAS_ROOT_CONCEPT); @@ -987,9 +969,17 @@ else if (concept == null) concept.setProperty(PROP_ORG_SRC, coordinates.originalSource); } - PropertyUtilities.mergeJSONObjectIntoPropertyContainer(jsonConcept, concept, ConceptConstants.PROP_LABELS, - PROP_SRC_IDS, PROP_SOURCES, PROP_SYNONYMS, COORDINATES, PARENT_COORDINATES, - ConceptConstants.RELATIONSHIPS); + // PropertyUtilities.mergeObjectIntoPropertyContainer(jsonConcept, concept, ConceptConstants.PROP_LABELS, + // PROP_SRC_IDS, PROP_SOURCES, PROP_SYNONYMS, COORDINATES, PARENT_COORDINATES, + // ConceptConstants.RELATIONSHIPS); + + PropertyUtilities.setNonNullNodeProperty(concept, PROP_PREF_NAME, jsonConcept.prefName); + PropertyUtilities.mergeArrayProperty(concept, PROP_DESCRIPTIONS, () -> jsonConcept.descriptions.toArray(new String[0])); + PropertyUtilities.mergeArrayProperty(concept, PROP_WRITING_VARIANTS, () -> jsonConcept.writingVariants.toArray(new String[0])); + PropertyUtilities.mergeArrayProperty(concept, PROP_COPY_PROPERTIES, () -> jsonConcept.copyProperties.toArray(new String[0])); + mergeArrayProperty(concept, ConceptConstants.PROP_SYNONYMS, synonyms.stream().filter(s -> !s.equals(prefName)).toArray()); + addToArrayProperty(concept, PROP_FACETS, facetId); + // There could be multiple sources containing a concept. For // now, we just note that facet (if these sources give the same original // ID, otherwise we won't notice) but don't do anything about @@ -1013,11 +1003,9 @@ else if (concept == null) addToArrayProperty(concept, PROP_SOURCES, source, true); addToArrayProperty(concept, PROP_UNIQUE_SRC_ID, uniqueSourceId, true); } - mergeArrayProperty(concept, ConceptConstants.PROP_SYNONYMS, JSON.json2JavaArray(synonyms, prefName)); - addToArrayProperty(concept, PROP_FACETS, facetId); - for (int i = 0; null != generalLabels && i < generalLabels.length(); i++) { - concept.addLabel(Label.label(generalLabels.getString(i))); + for (int i = 0; null != generalLabels && i < generalLabels.size(); i++) { + concept.addLabel(Label.label(generalLabels.get(i))); } if (srcIduniqueMarkerChanged) { @@ -1103,134 +1091,126 @@ private boolean checkUniqueIdMarkerClash(Node conceptNode, String srcId, boolean * @param nodesByCoordinates * @param importOptions * @return - * @throws JSONException * @throws AggregateConceptInsertionException */ - private InsertionReport insertConcepts(GraphDatabaseService graphDb, JSONArray jsonConcepts, String facetId, + private InsertionReport insertConcepts(GraphDatabaseService graphDb, List jsonConcepts, String facetId, CoordinatesMap nodesByCoordinates, ImportOptions importOptions) throws ConceptInsertionException { - try { - long time = System.currentTimeMillis(); - InsertionReport insertionReport = new InsertionReport(); - // Idea: First create all nodes and just store which Node has which - // parent. Then, after all nodes have been created, do the actual - // connection. - Index conceptIndex = null; - IndexManager indexManager = graphDb.index(); - conceptIndex = indexManager.forNodes(INDEX_NAME); - - // this MUST be a TreeSort or at least some collection using the - // Comparable interface because ConceptCoordinates are rather - // complicated regarding equality - CoordinatesSet toBeCreated = new CoordinatesSet(); - // First, iterate through all concepts and check if their parents - // already exist, before any nodes are created (for more efficient - // relationship creation). - - // When merging, we don't care about parents. - if (!importOptions.merge) { - for (int i = 0; i < jsonConcepts.length(); i++) { - JSONObject jsonConcept = jsonConcepts.getJSONObject(i); - if (jsonConcept.has(PARENT_COORDINATES) && jsonConcept.getJSONArray(PARENT_COORDINATES).length() > 0) { - JSONArray parentCoordinatesArray = jsonConcept.getJSONArray(PARENT_COORDINATES); - for (int j = 0; j < parentCoordinatesArray.length(); j++) { - ConceptCoordinates parentCoordinates = new ConceptCoordinates( - parentCoordinatesArray.getJSONObject(j)); - Node parentNode = lookupConcept(parentCoordinates, conceptIndex); - if (parentNode != null) { - insertionReport.addExistingConcept(parentNode); - nodesByCoordinates.put(parentCoordinates, parentNode); - } else { - toBeCreated.add(parentCoordinates); - } + long time = System.currentTimeMillis(); + InsertionReport insertionReport = new InsertionReport(); + // Idea: First create all nodes and just store which Node has which + // parent. Then, after all nodes have been created, do the actual + // connection. + Index conceptIndex = null; + IndexManager indexManager = graphDb.index(); + conceptIndex = indexManager.forNodes(INDEX_NAME); + + // this MUST be a TreeSort or at least some collection using the + // Comparable interface because ConceptCoordinates are rather + // complicated regarding equality + CoordinatesSet toBeCreated = new CoordinatesSet(); + // First, iterate through all concepts and check if their parents + // already exist, before any nodes are created (for more efficient + // relationship creation). + + // When merging, we don't care about parents. + if (!importOptions.merge) { + for (int i = 0; i < jsonConcepts.size(); i++) { + ImportConcept jsonConcept = jsonConcepts.get(i); + if (jsonConcept.parentCoordinates != null) { + for (ConceptCoordinates parentCoordinates : jsonConcept.parentCoordinates) { + Node parentNode = lookupConcept(parentCoordinates, conceptIndex); + if (parentNode != null) { + insertionReport.addExistingConcept(parentNode); + nodesByCoordinates.put(parentCoordinates, parentNode); + } else { + toBeCreated.add(parentCoordinates); } } } } - // Finished finding parents - - // When merging, we remove those import concepts that are not known in - // the database from the input data - List importConceptsToRemove = new ArrayList<>(); - // Second, iterate through all concepts to be imported and check if - // they already exist themselves or not. Not existing nodes will be - // created as - // HOLLOW nodes. - // The following methods can then just access the nodes by their source - // Id which ought to be unique for each import. - for (int i = 0; i < jsonConcepts.length(); i++) { - JSONObject jsonConcept = jsonConcepts.getJSONObject(i); - ConceptCoordinates coordinates; - if (jsonConcept.has(ConceptConstants.COORDINATES)) { - coordinates = new ConceptCoordinates(jsonConcept.getJSONObject(ConceptConstants.COORDINATES)); - insertionReport.addImportedCoordinates(coordinates); - } else if (!JSON.getBoolean(jsonConcept, ConceptConstants.AGGREGATE)) { - throw new IllegalArgumentException("Concept " + jsonConcept + " does not define concept coordinates."); - } else { - continue; - } - // many nodes will actually already have been seen as parents - // above - if (nodesByCoordinates.containsKey(coordinates) || toBeCreated.contains(coordinates, true)) - continue; - Node conceptNode = lookupConcept(coordinates, conceptIndex); - if (conceptNode != null) { - insertionReport.addExistingConcept(conceptNode); - nodesByCoordinates.put(coordinates, conceptNode); - } else if (!importOptions.merge) { - // When merging, we don't create new concepts - - // The concept coordinates are not yet known, create an - // empty - // concept node with its coordinates. - // Node newConcept = registerNewHollowConceptNode(graphDb, - // coordinates, conceptIndex); - toBeCreated.add(coordinates); - - // conceptNode = newConcept; - } else { - // We are in merging mode and requested concept is not in the - // database; mark it for removal from the input data and - // continue - importConceptsToRemove.add(i); - continue; - } - + } + // Finished finding parents + + // When merging, we remove those import concepts that are not known in + // the database from the input data + List importConceptsToRemove = new ArrayList<>(); + // Second, iterate through all concepts to be imported and check if + // they already exist themselves or not. Not existing nodes will be + // created as + // HOLLOW nodes. + // The following methods can then just access the nodes by their source + // Id which ought to be unique for each import. + for (int i = 0; i < jsonConcepts.size(); i++) { + ImportConcept jsonConcept = jsonConcepts.get(i); + ConceptCoordinates coordinates; + if (jsonConcept.coordinates != null) { + coordinates = jsonConcept.coordinates; + insertionReport.addImportedCoordinates(coordinates); + } else if (!jsonConcept.aggregate) { + throw new IllegalArgumentException("Concept " + jsonConcept + " does not define concept coordinates."); + } else { + continue; } - // Finished getting existing nodes and creating HOLLOW nodes + // many nodes will actually already have been seen as parents + // above + if (nodesByCoordinates.containsKey(coordinates) || toBeCreated.contains(coordinates, true)) + continue; + Node conceptNode = lookupConcept(coordinates, conceptIndex); + if (conceptNode != null) { + insertionReport.addExistingConcept(conceptNode); + nodesByCoordinates.put(coordinates, conceptNode); + } else if (!importOptions.merge) { + // When merging, we don't create new concepts - for (ConceptCoordinates coordinates : toBeCreated) { - Node conceptNode = registerNewHollowConceptNode(graphDb, coordinates, conceptIndex); - ++insertionReport.numConcepts; + // The concept coordinates are not yet known, create an + // empty + // concept node with its coordinates. + // Node newConcept = registerNewHollowConceptNode(graphDb, + // coordinates, conceptIndex); + toBeCreated.add(coordinates); - nodesByCoordinates.put(coordinates, conceptNode); + // conceptNode = newConcept; + } else { + // We are in merging mode and requested concept is not in the + // database; mark it for removal from the input data and + // continue + importConceptsToRemove.add(i); + continue; } - log.info("removing " + importConceptsToRemove.size() - + " input concepts that should be omitted because we are merging and don't have them in the database"); - for (int index = importConceptsToRemove.size() - 1; index >= 0; --index) - jsonConcepts.remove(importConceptsToRemove.get(index)); - - log.info("Starting to insert " + jsonConcepts.length() + " concepts."); - for (int i = 0; i < jsonConcepts.length(); i++) { - JSONObject jsonConcept = jsonConcepts.getJSONObject(i); - boolean isAggregate = JSON.getBoolean(jsonConcept, ConceptConstants.AGGREGATE); - if (isAggregate) { - insertAggregateConcept(graphDb, conceptIndex, jsonConcept, nodesByCoordinates, insertionReport, - importOptions); - } else { - insertConcept(graphDb, facetId, conceptIndex, jsonConcept, nodesByCoordinates, insertionReport, - importOptions); - } + } + // Finished getting existing nodes and creating HOLLOW nodes + + for (ConceptCoordinates coordinates : toBeCreated) { + Node conceptNode = registerNewHollowConceptNode(graphDb, coordinates, conceptIndex); + ++insertionReport.numConcepts; + + nodesByCoordinates.put(coordinates, conceptNode); + } + + log.info("removing " + importConceptsToRemove.size() + + " input concepts that should be omitted because we are merging and don't have them in the database"); + for (int index = importConceptsToRemove.size() - 1; index >= 0; --index) + jsonConcepts.remove(importConceptsToRemove.get(index)); + + log.info("Starting to insert " + jsonConcepts.size() + " concepts."); + for (int i = 0; i < jsonConcepts.size(); i++) { + ImportConcept jsonConcept = jsonConcepts.get(i); + boolean isAggregate = jsonConcept.aggregate; + if (isAggregate) { + insertAggregateConcept(graphDb, conceptIndex, jsonConcept, nodesByCoordinates, insertionReport, + importOptions); + } else { + insertConcept(graphDb, facetId, conceptIndex, jsonConcept, nodesByCoordinates, insertionReport, + importOptions); } - log.debug(jsonConcepts.length() + " concepts inserted."); - time = System.currentTimeMillis() - time; - log.info(insertionReport.numConcepts - + " new concepts - but not yet relationships - have been inserted. This took " + time + " ms (" - + (time / 1000) + " s)"); - return insertionReport; - } catch (JSONException e) { - throw new ConceptInsertionException(e); } + log.debug(jsonConcepts.size() + " concepts inserted."); + time = System.currentTimeMillis() - time; + log.info(insertionReport.numConcepts + + " new concepts - but not yet relationships - have been inserted. This took " + time + " ms (" + + (time / 1000) + " s)"); + return insertionReport; } /** @@ -1266,13 +1246,14 @@ private Node registerNewHollowConceptNode(GraphDatabaseService graphDb, ConceptC return node; } - public Representation insertConcepts(GraphDatabaseService graphDb, String conceptsWithFacet) throws JSONException, ConceptInsertionException { - JSONObject input = new JSONObject(conceptsWithFacet); - JSONObject jsonFacet = JSON.getJSONObject(input, KEY_FACET); - JSONArray jsonConcepts = input.getJSONArray(KEY_CONCEPTS); - JSONObject importOptionsJson = JSON.getJSONObject(input, KEY_IMPORT_OPTIONS); - return insertConcepts(graphDb, jsonFacet != null ? jsonFacet.toString() : null, jsonConcepts.toString(), - importOptionsJson != null ? importOptionsJson.toString() : null); + public Representation insertConcepts(GraphDatabaseService graphDb, String conceptsWithFacet) throws ConceptInsertionException, IOException { + final ObjectMapper om = new ObjectMapper(); + final ImportConcepts importConcepts = ConceptsJsonSerializer.fromJson(conceptsWithFacet, ImportConcepts.class); + ImportFacet jsonFacet = importConcepts.getFacet(); + List jsonConcepts = importConcepts.getConcepts(); + ImportOptions importOptionsJson = importConcepts.getImportOptions(); + return insertConcepts(graphDb, jsonFacet != null ? om.writeValueAsString(jsonFacet) : null, om.writeValueAsString(jsonConcepts), + importOptionsJson != null ? om.writeValueAsString(importOptionsJson) : null); } @Name(INSERT_CONCEPTS) @@ -1283,26 +1264,25 @@ public Representation insertConcepts(@Source GraphDatabaseService graphDb, @Description("TODO") @Parameter(name = KEY_FACET, optional = true) String facetJson, @Description("TODO") @Parameter(name = KEY_CONCEPTS, optional = true) String conceptsJson, @Description("TODO") @Parameter(name = KEY_IMPORT_OPTIONS, optional = true) String importOptionsJsonString) - throws JSONException, ConceptInsertionException { + throws ConceptInsertionException, IOException { log.info("{} was called", INSERT_CONCEPTS); long time = System.currentTimeMillis(); - Gson gson = new Gson(); + final ObjectMapper om = new ObjectMapper(); log.debug("Parsing input."); - JSONObject jsonFacet = null; - JSONArray jsonConcepts = null; - JSONObject importOptionsJson = null; - jsonFacet = !StringUtils.isEmpty(facetJson) ? new JSONObject(facetJson) : null; + ImportFacet jsonFacet = null; + List jsonConcepts = null; + jsonFacet = !StringUtils.isEmpty(facetJson) ? om.readValue(facetJson, ImportFacet.class) : null; if (null != conceptsJson) { - jsonConcepts = new JSONArray(conceptsJson); - log.info("Got {} input concepts for import.", jsonConcepts.length()); + jsonConcepts = om.readValue(conceptsJson, new TypeReference>() { + }); + log.info("Got {} input concepts for import.", jsonConcepts.size()); } else { log.info("Got 0 input concepts for import."); } ImportOptions importOptions; if (null != importOptionsJsonString) { - importOptionsJson = new JSONObject(importOptionsJsonString); - importOptions = gson.fromJson(importOptionsJson.toString(), ImportOptions.class); + importOptions = om.readValue(importOptionsJsonString, ImportOptions.class); } else { importOptions = new ImportOptions(); } @@ -1316,10 +1296,10 @@ public Representation insertConcepts(@Source GraphDatabaseService graphDb, // The facet Id will be added to the facets-property of the concept // nodes. log.debug("Handling import of facet."); - if (null != jsonFacet && jsonFacet.has(PROP_ID)) { - facetId = jsonFacet.getString(PROP_ID); + if (null != jsonFacet && jsonFacet.getId() != null) { + facetId = jsonFacet.getId(); log.info("Facet ID {} has been given to add the concepts to.", facetId); - boolean isNoFacet = JSON.getBoolean(jsonFacet, FacetConstants.NO_FACET); + boolean isNoFacet = jsonFacet.isNoFacet(); if (isNoFacet) facet = FacetManager.getNoFacet(graphDb, facetId); else @@ -1327,12 +1307,12 @@ public Representation insertConcepts(@Source GraphDatabaseService graphDb, if (null == facet) throw new IllegalArgumentException("The facet with ID \"" + facetId + "\" was not found. You must pass the ID of an existing facet or deliver all information required to create the facet from scratch. Then, the facetId must not be included in the request, it will be created dynamically."); - } else if (null != jsonFacet && jsonFacet.has(FacetConstants.PROP_NAME)) { + } else if (null != jsonFacet && jsonFacet.getName() != null) { ResourceIterator facetIterator = graphDb.findNodes(FacetLabel.FACET); while (facetIterator.hasNext()) { facet = facetIterator.next(); if (facet.getProperty(FacetConstants.PROP_NAME) - .equals(jsonFacet.getString(FacetConstants.PROP_NAME))) + .equals(jsonFacet.getName())) break; facet = null; } @@ -1363,16 +1343,16 @@ public Representation insertConcepts(@Source GraphDatabaseService graphDb, insertionReport); else log.info("This is a property merging import, no relationships are created."); - time = System.currentTimeMillis() - time; report.put(RET_KEY_NUM_CREATED_CONCEPTS, insertionReport.numConcepts); report.put(RET_KEY_NUM_CREATED_RELS, insertionReport.numRelationships); - report.put(KEY_FACET_ID, facetId); - report.put(KEY_TIME, time); log.debug("Done creating concepts and relationships."); } else { log.info("No concepts were included in the request."); } + time = System.currentTimeMillis() - time; + report.put(KEY_TIME, time); + report.put(KEY_FACET_ID, facetId); tx.success(); } log.info("Concept insertion complete."); @@ -1693,7 +1673,7 @@ else if (facetsContainingChildren.size() > 0) @Name("include_concepts") @Description("This is only a remedy for a problem we shouldnt have, delete in the future.") @PluginTarget(GraphDatabaseService.class) - public void includeConcepts(@Source GraphDatabaseService graphDb) throws JSONException { + public void includeConcepts(@Source GraphDatabaseService graphDb) { Label includeLabel = Label.label("INCLUDE"); try (Transaction tx = graphDb.beginTx()) { ResourceIterable concepts = () -> graphDb.findNodes(includeLabel); @@ -1737,7 +1717,7 @@ public void includeConcepts(@Source GraphDatabaseService graphDb) throws JSONExc @Name("exclude_concepts") @Description("This is only a remedy for a problem we shouldnt have, delete in the future.") @PluginTarget(GraphDatabaseService.class) - public void excludeConcepts(@Source GraphDatabaseService graphDb) throws JSONException { + public void excludeConcepts(@Source GraphDatabaseService graphDb) { Label includeLabel = Label.label("INCLUDE"); Label excludeLabel = Label.label("EXCLUDE"); Label mappingAggregateLabel = Label.label("MAPPING_AGGREGATE"); @@ -1775,20 +1755,21 @@ public void excludeConcepts(@Source GraphDatabaseService graphDb) throws JSONExc + " but that reading commands don't care about the relationship direction.") @PluginTarget(GraphDatabaseService.class) public int insertMappings(@Source GraphDatabaseService graphDb, - @Description("An array of mappings in JSON format. Each mapping is an object with the keys for \"id1\", \"id2\" and \"mappingType\", respectively.") @Parameter(name = KEY_MAPPINGS) String mappingsJson) - throws JSONException { - JSONArray mappings = new JSONArray(mappingsJson); - log.info("Starting to insert " + mappings.length() + " mappings."); + @Description("An array of mappings in JSON format. Each mapping is an object with the keys for \"id1\", \"id2\" and \"mappingType\", respectively.") @Parameter(name = KEY_MAPPINGS) String mappingsJson) throws IOException { + final ObjectMapper om = new ObjectMapper(); + final List> mappings = om.readValue(mappingsJson, new TypeReference>>() { + }); + log.info("Starting to insert " + mappings.size() + " mappings."); try (Transaction tx = graphDb.beginTx()) { Index conceptIndex = graphDb.index().forNodes(ConceptConstants.INDEX_NAME); - Map nodesBySrcId = new HashMap<>(mappings.length()); + Map nodesBySrcId = new HashMap<>(mappings.size()); InsertionReport insertionReport = new InsertionReport(); - for (int i = 0; i < mappings.length(); i++) { - JSONObject mapping = mappings.getJSONObject(i); - String id1 = mapping.getString("id1"); - String id2 = mapping.getString("id2"); - String mappingType = mapping.getString("mappingType"); + for (int i = 0; i < mappings.size(); i++) { + Map mapping = mappings.get(i); + String id1 = mapping.get("id1"); + String id2 = mapping.get("id2"); + String mappingType = mapping.get("mappingType"); log.debug("Inserting mapping " + id1 + " -" + mappingType + "- " + id2); @@ -1857,7 +1838,7 @@ public int insertMappings(@Source GraphDatabaseService graphDb, ConceptRelationConstants.PROP_MAPPING_TYPE, new String[]{mappingType}); } tx.success(); - log.info(insertionReport.numRelationships + " of " + mappings.length() + log.info(insertionReport.numRelationships + " of " + mappings.size() + " new mappings successfully added."); return insertionReport.numRelationships; } @@ -1869,26 +1850,25 @@ public int insertMappings(@Source GraphDatabaseService graphDb, public MappingRepresentation getFacetRoots(@Source GraphDatabaseService graphDb, @Description("An array of facet IDs in JSON format.") @Parameter(name = KEY_FACET_IDS) String facetIdsJson, @Description("An array of concept IDs to restrict the retrieval to.") @Parameter(name = KEY_CONCEPT_IDS, optional = true) String conceptIdsJson, - @Description("Restricts the facets to those that have at most the specified number of roots.") @Parameter(name = KEY_MAX_ROOTS, optional = true) long maxRoots) - throws JSONException { + @Description("Restricts the facets to those that have at most the specified number of roots.") @Parameter(name = KEY_MAX_ROOTS, optional = true) long maxRoots) throws IOException { + final ObjectMapper om = new ObjectMapper(); Map facetRoots = new HashMap<>(); - JSONArray facetIdsArray = new JSONArray(facetIdsJson); + String[] facetIdsArray = om.readValue(facetIdsJson, String[].class); Set requestedFacetIds = new HashSet<>(); - for (int i = 0; i < facetIdsArray.length(); i++) - requestedFacetIds.add(facetIdsArray.getString(i)); + for (int i = 0; i < facetIdsArray.length; i++) + requestedFacetIds.add(facetIdsArray[i]); Map> requestedConceptIds = null; if (!StringUtils.isBlank(conceptIdsJson) && !conceptIdsJson.equals("null")) { - JSONObject conceptIdsObject = new JSONObject(conceptIdsJson); + Map conceptIdsObject = om.readValue(conceptIdsJson, new TypeReference>() { + }); requestedConceptIds = new HashMap<>(); - JSONArray facetIds = conceptIdsObject.names(); - for (int i = 0; null != facetIds && i < facetIds.length(); i++) { - String facetId = facetIds.getString(i); - JSONArray requestedRootIdsForFacet = conceptIdsObject.getJSONArray(facetId); + for (String facetId : conceptIdsObject.keySet()) { + String[] requestedRootIdsForFacet = conceptIdsObject.get(facetId); Set idSet = new HashSet<>(); - for (int j = 0; j < requestedRootIdsForFacet.length(); j++) - idSet.add(requestedRootIdsForFacet.getString(j)); + for (int j = 0; j < requestedRootIdsForFacet.length; j++) + idSet.add(requestedRootIdsForFacet[j]); requestedConceptIds.put(facetId, idSet); } } @@ -1944,8 +1924,7 @@ public MappingRepresentation getFacetRoots(@Source GraphDatabaseService graphDb, @PluginTarget(GraphDatabaseService.class) public void addWritingVariants(@Source GraphDatabaseService graphDb, @Description("A JSON object mapping concept IDs to an array of writing variants to add to the existing writing variants.") @Parameter(name = KEY_CONCEPT_TERMS, optional = true) String conceptVariants, - @Description("A JSON object mapping concept IDs to an array of acronyms to add to the existing concept acronyms.") @Parameter(name = KEY_CONCEPT_ACRONYMS, optional = true) String conceptAcronyms) - throws JSONException { + @Description("A JSON object mapping concept IDs to an array of acronyms to add to the existing concept acronyms.") @Parameter(name = KEY_CONCEPT_ACRONYMS, optional = true) String conceptAcronyms) { if (null != conceptVariants) addConceptVariant(graphDb, conceptVariants, "writingVariants"); if (null != conceptAcronyms) @@ -2132,7 +2111,7 @@ private void addConceptVariant(GraphDatabaseService graphDb, String conceptVaria } } - public static enum EdgeTypes implements RelationshipType { + public enum EdgeTypes implements RelationshipType { /** * Relationship type for connecting aggregate classes with their element * concepts. @@ -2156,7 +2135,7 @@ public static enum EdgeTypes implements RelationshipType { HAS_VARIANTS, HAS_ACRONYMS } - public static enum ConceptLabel implements Label { + public enum ConceptLabel implements Label { /** * Label to indicate a node is not an actual concept but an aggregate concept. * Such concepts have {@link EdgeTypes#HAS_ELEMENT} relationships to concepts, @@ -2180,7 +2159,7 @@ public static enum ConceptLabel implements Label { /** * Labels for nodes representing lexico-morphological variations of concepts. */ - public static enum MorphoLabel implements Label { + public enum MorphoLabel implements Label { WRITING_VARIANTS, ACRONYMS, WRITING_VARIANT, ACRONYM } diff --git a/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/Export.java b/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/Export.java index f27f3ba..c4c458b 100644 --- a/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/Export.java +++ b/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/Export.java @@ -1,51 +1,9 @@ package de.julielab.neo4j.plugins; -import static de.julielab.neo4j.plugins.datarepresentation.constants.ConceptConstants.PROP_FACETS; -import static de.julielab.neo4j.plugins.datarepresentation.constants.ConceptConstants.PROP_PREF_NAME; -import static de.julielab.neo4j.plugins.datarepresentation.constants.ConceptConstants.PROP_SYNONYMS; -import static de.julielab.neo4j.plugins.datarepresentation.constants.NodeConstants.PROP_ID; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.logging.Logger; -import java.util.zip.GZIPOutputStream; - -import javax.xml.bind.DatatypeConverter; - -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.StringUtils; -import org.neo4j.graphdb.Direction; -import org.neo4j.graphdb.GraphDatabaseService; -import org.neo4j.graphdb.Label; -import org.neo4j.graphdb.Node; -import org.neo4j.graphdb.Path; -import org.neo4j.graphdb.Relationship; -import org.neo4j.graphdb.RelationshipType; -import org.neo4j.graphdb.ResourceIterable; -import org.neo4j.graphdb.ResourceIterator; -import org.neo4j.graphdb.Transaction; -import org.neo4j.graphdb.traversal.TraversalDescription; -import org.neo4j.graphdb.traversal.Traverser; -import org.neo4j.server.plugins.Description; -import org.neo4j.server.plugins.Name; -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.RecursiveMappingRepresentation; -import org.neo4j.server.rest.repr.Representation; -import org.neo4j.shell.util.json.JSONArray; -import org.neo4j.shell.util.json.JSONException; - -import de.julielab.neo4j.plugins.ConceptManager.EdgeTypes; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.ObjectMapper; import de.julielab.neo4j.plugins.ConceptManager.ConceptLabel; +import de.julielab.neo4j.plugins.ConceptManager.EdgeTypes; import de.julielab.neo4j.plugins.auxiliaries.JulieNeo4jUtilities; import de.julielab.neo4j.plugins.auxiliaries.NodeUtilities; import de.julielab.neo4j.plugins.auxiliaries.PropertyUtilities; @@ -53,6 +11,24 @@ import de.julielab.neo4j.plugins.datarepresentation.constants.ConceptConstants; import de.julielab.neo4j.plugins.datarepresentation.constants.FacetConstants; import de.julielab.neo4j.plugins.datarepresentation.constants.MorphoConstants; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.neo4j.graphdb.*; +import org.neo4j.graphdb.traversal.TraversalDescription; +import org.neo4j.graphdb.traversal.Traverser; +import org.neo4j.server.plugins.*; +import org.neo4j.server.rest.repr.RecursiveMappingRepresentation; +import org.neo4j.server.rest.repr.Representation; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.*; +import java.util.logging.Logger; +import java.util.zip.GZIPOutputStream; + +import static de.julielab.neo4j.plugins.datarepresentation.constants.ConceptConstants.*; +import static de.julielab.neo4j.plugins.datarepresentation.constants.NodeConstants.PROP_ID; public class Export extends ServerPlugin { @@ -91,8 +67,9 @@ public class Export extends ServerPlugin { public Representation exportIdMapping(@Source GraphDatabaseService graphDb, @Parameter(name = PARAM_ID_PROPERTY) @Description("TODO") String idProperty, @Parameter(name = PARAM_LABELS) @Description("TODO") String labelStrings) throws Exception { + final ObjectMapper om = new ObjectMapper(); log.info("Exporting ID mapping data."); - JSONArray labelsArray = null != labelStrings ? new JSONArray(labelStrings) : null; + String[] labelsArray = null != labelStrings ? om.readValue(labelStrings, String[].class) : null; log.info("Creating mapping file content for property \"" + idProperty + "\" and facets " + labelsArray); ByteArrayOutputStream gzipBytes = createIdMapping(graphDb, idProperty, labelsArray); byte[] bytes = gzipBytes.toByteArray(); @@ -102,13 +79,13 @@ public Representation exportIdMapping(@Source GraphDatabaseService graphDb, } private ByteArrayOutputStream createIdMapping(GraphDatabaseService graphDb, String idProperty, - JSONArray labelsArray) throws Exception { + String[] labelsArray) throws Exception { ByteArrayOutputStream baos = new ByteArrayOutputStream(OUTPUTSTREAM_INIT_SIZE); try (GZIPOutputStream os = new GZIPOutputStream(baos)) { try (Transaction tx = graphDb.beginTx()) { int numWritten = 0; - for (int i = 0; i < labelsArray.length(); i++) { - String labelString = labelsArray.getString(i); + for (int i = 0; i < labelsArray.length; i++) { + String labelString = labelsArray[i]; Label label = Label.label(labelString); for (ResourceIterator terms = graphDb.findNodes(label); terms.hasNext();) { Node term = terms.next(); @@ -149,7 +126,8 @@ public Representation exportHypernyms(@Source GraphDatabaseService graphDb, @Description("The facet labels indicating for which facets to create the hypernyms file") @Parameter(name = PARAM_LABELS, optional = true) String facetLabelStrings, @Description("A label restricting hypernym generation to terms with this label.") @Parameter(name = PARAM_LABEL, optional = true) String termLabel) throws Exception { - JSONArray labelsArray = null != facetLabelStrings ? new JSONArray(facetLabelStrings) : null; + ObjectMapper om = new ObjectMapper(); + String[] labelsArray = null != facetLabelStrings ? om.readValue(facetLabelStrings, String[].class) : null; if (null == labelsArray) log.info("Exporting hypernyms dictionary data for all facets."); else @@ -162,13 +140,12 @@ public Representation exportHypernyms(@Source GraphDatabaseService graphDb, return RecursiveMappingRepresentation.getObjectRepresentation(bytes); } - private ByteArrayOutputStream writeHypernymList(GraphDatabaseService graphDb, JSONArray labelsArray, - String termLabelString, int cacheSize) throws IOException, JSONException { + private ByteArrayOutputStream writeHypernymList(GraphDatabaseService graphDb, String[] labelsArray, + String termLabelString, int cacheSize) throws IOException{ - JSONArray labels = labelsArray; + String[] labels = labelsArray; if (null == labels) { - labels = new JSONArray(); - labels.put(FacetManager.FacetLabel.FACET.name()); + labels = new String[]{FacetManager.FacetLabel.FACET.name()}; } Label termLabel = null; if (!StringUtils.isBlank(termLabelString)) @@ -189,9 +166,9 @@ private ByteArrayOutputStream writeHypernymList(GraphDatabaseService graphDb, JS List relationshipTypeList = new ArrayList<>(); // Only create the specific facet IDs set when we have not just // all facets - if (labels.length() > 1 || !labels.getString(0).equals(FacetManager.FacetLabel.FACET.name())) { - for (int i = 0; i < labels.length(); i++) { - String labelString = labels.getString(i); + if (labels.length > 1 || !labels[0].equals(FacetManager.FacetLabel.FACET.name())) { + for (int i = 0; i < labels.length; i++) { + String labelString = labels[i]; Label label = Label.label(labelString); ResourceIterable facets = () -> graphDb.findNodes(label); for (Node facet : facets) { @@ -209,8 +186,8 @@ private ByteArrayOutputStream writeHypernymList(GraphDatabaseService graphDb, JS relationshipTypeList.add(ConceptManager.EdgeTypes.IS_BROADER_THAN); } - for (int i = 0; i < labels.length(); i++) { - String labelString = labels.getString(i); + for (int i = 0; i < labels.length; i++) { + String labelString = labels[i]; Label label = Label.label(labelString); log.info("Now creating hypernyms for facets with label " + label); ResourceIterable facets = () -> graphDb.findNodes(label); @@ -315,14 +292,15 @@ public String exportLingpipeDictionary(@Source GraphDatabaseService graphDb, } Label[] exclusionLabels = null; if (!StringUtils.isBlank(exclusionLabelString)) { - try { - JSONArray exclusionLabelsJson = new JSONArray(exclusionLabelString); - exclusionLabels = new Label[exclusionLabelsJson.length()]; - for (int i = 0; i < exclusionLabelsJson.length(); i++) { - String string = exclusionLabelsJson.getString(i); + final ObjectMapper om = new ObjectMapper(); + try { + String[] exclusionLabelsJson = om.readValue(exclusionLabelString, String[].class); + exclusionLabels = new Label[exclusionLabelsJson.length]; + for (int i = 0; i < exclusionLabelsJson.length; i++) { + String string = exclusionLabelsJson[i]; exclusionLabels[i] = Label.label(string); } - } catch (JSONException e) { + } catch (JsonParseException e) { Label exclusionLabel = Label.label(exclusionLabelString); exclusionLabels = new Label[] { exclusionLabel }; } @@ -426,7 +404,7 @@ public String exportLingpipeDictionary(@Source GraphDatabaseService graphDb, } log.info("Done exporting Lingpipe term dictionary."); byte[] bytes = baos.toByteArray(); - String encoded = DatatypeConverter.printBase64Binary(bytes); + String encoded = Base64.getEncoder().encodeToString(bytes); return encoded; } @@ -480,13 +458,14 @@ public static Representation exportTermFacetMapping(@Source GraphDatabaseService public String exportElementToAggregateIdMapping(@Source GraphDatabaseService graphDb, @Parameter(name = PARAM_LABELS) @Description("The aggregate labels for which to create the mapping") String aggLabelStrings) throws Exception { + ObjectMapper om = new ObjectMapper(); log.info("Exporting element-aggregate ID mapping data."); - JSONArray labelsArray = new JSONArray(aggLabelStrings); + String[] labelsArray = om.readValue(aggLabelStrings, String[].class); log.info("Creating element-aggregate ID mapping file content for aggregate labels \"" + labelsArray + "\""); ByteArrayOutputStream gzipBytes = createElementAggregateIdMapping(graphDb, labelsArray); byte[] bytes = gzipBytes.toByteArray(); log.info("Sending all " + bytes.length + " bytes of GZIPed ID element-aggregate ID mapping file data."); - String encoded = DatatypeConverter.printBase64Binary(bytes); + String encoded = Base64.getEncoder().encodeToString(bytes); log.info("Done exporting element-aggregate ID mapping data."); return encoded; } @@ -501,17 +480,16 @@ public String exportElementToAggregateIdMapping(@Source GraphDatabaseService gra * @param aggLabelsArray * @return * @throws IOException - * @throws JSONException */ private ByteArrayOutputStream createElementAggregateIdMapping(GraphDatabaseService graphDb, - JSONArray aggLabelsArray) throws IOException, JSONException { + String[] aggLabelsArray) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(OUTPUTSTREAM_INIT_SIZE); try (GZIPOutputStream os = new GZIPOutputStream(baos)) { try (Transaction tx = graphDb.beginTx()) { Map ele2Agg = new HashMap<>(); Set visitedAggregates = new HashSet<>(); - for (int i = 0; i < aggLabelsArray.length(); ++i) { - Label label = Label.label(aggLabelsArray.getString(i)); + for (int i = 0; i < aggLabelsArray.length; ++i) { + Label label = Label.label(aggLabelsArray[i]); ResourceIterator aggregates = graphDb.findNodes(label); TraversalDescription td = PredefinedTraversals.getNonAggregateAggregateElements(graphDb); while (aggregates.hasNext()) { diff --git a/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/FacetManager.java b/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/FacetManager.java index 3cb0b2b..0c3abf1 100644 --- a/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/FacetManager.java +++ b/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/FacetManager.java @@ -1,12 +1,15 @@ package de.julielab.neo4j.plugins; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; import de.julielab.neo4j.plugins.ConceptManager.ConceptLabel; -import de.julielab.neo4j.plugins.auxiliaries.JSON; import de.julielab.neo4j.plugins.auxiliaries.NodeUtilities; import de.julielab.neo4j.plugins.auxiliaries.PropertyUtilities; import de.julielab.neo4j.plugins.auxiliaries.semedico.PredefinedTraversals; import de.julielab.neo4j.plugins.auxiliaries.semedico.SequenceManager; import de.julielab.neo4j.plugins.constants.semedico.SequenceConstants; +import de.julielab.neo4j.plugins.datarepresentation.ImportFacet; +import de.julielab.neo4j.plugins.datarepresentation.ImportFacetGroup; import de.julielab.neo4j.plugins.datarepresentation.constants.FacetConstants; import de.julielab.neo4j.plugins.datarepresentation.constants.FacetGroupConstants; import de.julielab.neo4j.plugins.datarepresentation.constants.NodeConstants; @@ -21,10 +24,8 @@ import org.neo4j.server.rest.repr.MappingRepresentation; import org.neo4j.server.rest.repr.RecursiveMappingRepresentation; import org.neo4j.server.rest.repr.Representation; -import org.neo4j.shell.util.json.JSONArray; -import org.neo4j.shell.util.json.JSONException; -import org.neo4j.shell.util.json.JSONObject; +import java.io.IOException; import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; @@ -37,365 +38,371 @@ @Description("This plugin offers access to facets for Semedico.") public class FacetManager extends ServerPlugin { - /** - * Key of the map to send to the {@link #INSERT_FACETS} endpoint. - */ - public static final String KEY_FACETS = "facets"; - public static final String KEY_ID = "id"; - public static final String GET_FACETS = "get_facets"; - public static final String INSERT_FACETS = "insert_facets"; - public static final String GET_FACET_SIZE = "get_facet_size"; - public static final String PARAM_RETURN_HOLLOW_FACETS = "returnHollowFacets"; - private static final Logger log = Logger.getLogger(FacetManager.class.getName()); - - public static enum EdgeTypes implements RelationshipType { - HAS_FACET_GROUP, HAS_FACET - } - - public static enum FacetLabel implements Label { - FACET, NO_FACET - } - - @Name(GET_FACET_SIZE) - @Description("Returns the size of a facet by counting all the related children") - @PluginTarget(GraphDatabaseService.class) - public int getFacetSize(@Source GraphDatabaseService graphDb, - @Description("TODO") @Parameter(name = KEY_ID) String fid) throws JSONException { - return countFacetChildren(graphDb, fid); - } - - @Name(INSERT_FACETS) - // TODO - @Description("TODO") - @PluginTarget(GraphDatabaseService.class) - public ListRepresentation insertFacets(@Source GraphDatabaseService graphDb, - @Description("TODO") @Parameter(name = KEY_FACETS) String facetList) throws JSONException { - JSONArray input = new JSONArray(new String(facetList)); - List facets = new ArrayList(); - for (int i = 0; i < input.length(); i++) { - JSONObject jsonFacet = input.getJSONObject(i); - Node facet = createFacet(graphDb, jsonFacet); - facets.add(facet); - } - - try (Transaction tx = graphDb.beginTx()) { - // The response is a list - according to the input order - where for - // each facet is shown its name and which ID it received. - List facetRepList = new ArrayList(); - for (Node facet : facets) { - Map map = new HashMap(); - map.put(PROP_NAME, facet.getProperty(PROP_NAME)); - map.put(PROP_ID, facet.getProperty(PROP_ID)); - RecursiveMappingRepresentation facetResponseRep = new RecursiveMappingRepresentation(Representation.MAP, - map); - facetRepList.add(facetResponseRep); - } - ListRepresentation listRep = new ListRepresentation(Representation.MAP, facetRepList); - tx.success(); - return listRep; - } - - } - - @SuppressWarnings("unchecked") - @Name(GET_FACETS) - // TODO - @Description("TODO") - @PluginTarget(GraphDatabaseService.class) - public MappingRepresentation getFacets(@Source GraphDatabaseService graphDb, - @Description("TODO") @Parameter(name = PARAM_RETURN_HOLLOW_FACETS, optional = true) Boolean returnHollowfacets) - throws JSONException { - // As of Neo4j 2.0, read operations are required to be inside a - // transaction. - RecursiveMappingRepresentation facetGroupsRep; - try (Transaction tx = graphDb.beginTx()) { - Node facetGroupsNode = getFacetGroupsNode(graphDb); - TraversalDescription td = PredefinedTraversals.getFacetTraversal(graphDb); - Traverser traverse = td.traverse(facetGroupsNode); - - Map facetsByFacetGroupName = new HashMap(); - Map facetGroupsMap = new HashMap(); - List> facetGroupsWithFacetsList = new ArrayList>(); - - // First build intermediate maps where the facet group nodes and - // facets - // are - // organized by facet group name. - for (Path facetPath : traverse) { - Node facet = facetPath.endNode(); - Object sourceType = facet.getProperty(FacetConstants.PROP_SOURCE_TYPE); - boolean isFacetWithoutPredefinedRoots = !sourceType.equals(FacetConstants.SRC_TYPE_HIERARCHICAL); - - // For string-sourced facets it doesn't make sense to check - // their roots since they have none in the - // database anyway. Same with flat facets that don't have a - // hierarchic structure. - if (!isFacetWithoutPredefinedRoots) { - // Leave out facets without any root terms (this may happen - // by some weird BioPortal ontologies). - Iterator rootIt = facet.getRelationships(ConceptManager.EdgeTypes.HAS_ROOT_CONCEPT) - .iterator(); - if (!rootIt.hasNext()) - continue; - // Also leave out facets that only have Hollow root terms - // (happens with BioPortal ontology IMMDIS - // for - // example since all classes there seem to be subclasses of - // classes that are not defined anywhere). - if (!returnHollowfacets) { - boolean onlyHollowRoots = true; - while (rootIt.hasNext() && onlyHollowRoots) { - Node rootTerm = rootIt.next().getEndNode(); - boolean isHollow = false; - for (Label label : rootTerm.getLabels()) { - if (label.equals(ConceptLabel.HOLLOW)) { - isHollow = true; - break; - } - } - if (!isHollow) - onlyHollowRoots = false; - } - if (onlyHollowRoots) - continue; - } - } - - Iterable facetRels = facet.getRelationships(Direction.INCOMING, EdgeTypes.HAS_FACET); - for (Relationship facetRel : facetRels) { - Node facetGroupNode = facetRel.getStartNode(); - String facetGroupName = (String) facetGroupNode.getProperty(PROP_NAME); - - facetGroupsMap.put(facetGroupName, facetGroupNode); - - List facets = (List) facetsByFacetGroupName.get(facetGroupName); - if (facets == null) { - facets = new ArrayList(); - facetsByFacetGroupName.put(facetGroupName, facets); - } - facets.add(facet); - } - - } - - // Now connect the intermediate maps into a final list of facet - // groups - // where each facet group contains the facets belonging to it. - for (String facetGroupName : facetsByFacetGroupName.keySet()) { - Node facetGroupNode = facetGroupsMap.get(facetGroupName); - Object facets = facetsByFacetGroupName.get(facetGroupName); - - Map facetGroupMap = new HashMap(); - for (String propKey : facetGroupNode.getPropertyKeys()) - facetGroupMap.put(propKey, facetGroupNode.getProperty(propKey)); - List facetGroupLabels = new ArrayList<>(); - for (Label label : facetGroupNode.getLabels()) - facetGroupLabels.add(label.name()); - facetGroupMap.put(FacetGroupConstants.KEY_LABELS, facetGroupLabels); - facetGroupMap.put(KEY_FACETS, facets); - - facetGroupsWithFacetsList.add(facetGroupMap); - } - Map ret = new HashMap(); - ret.put("facetGroups", facetGroupsWithFacetsList); - facetGroupsRep = new RecursiveMappingRepresentation(Representation.MAP, ret); - tx.success(); - } - - return facetGroupsRep; - } - - public static Node createFacet(GraphDatabaseService graphDb, JSONObject jsonFacet) throws JSONException { - log.info("Creating facet with the following data: " + jsonFacet); - - JSONArray generalLabels = JSON.getJSONArray(jsonFacet, PROP_LABELS); - boolean isNoFacet = JSON.getBoolean(jsonFacet, NO_FACET); - - JSONObject jsonFacetGroup = jsonFacet.getJSONObject(FACET_GROUP); - - try (Transaction tx = graphDb.beginTx()) { - Node facetGroupsNode; - if (isNoFacet) - facetGroupsNode = getNoFacetGroupsNode(graphDb); - else - facetGroupsNode = getFacetGroupsNode(graphDb); - Node facetGroup = createFacetGroup(graphDb, facetGroupsNode, jsonFacetGroup); - - // Create the actual facet node and populate it with data. - Node facet = graphDb.createNode(FacetLabel.FACET); - PropertyUtilities.copyJSONObjectToPropertyContainer(jsonFacet, facet, NO_FACET, PROP_LABELS, - FACET_GROUP); - - // If everything is alright, get an ID for the facet. - String facetId = NodeIDPrefixConstants.FACET - + SequenceManager.getNextSequenceValue(graphDb, SequenceConstants.SEQ_FACET); - facet.setProperty(PROP_ID, facetId); - facetGroup.createRelationshipTo(facet, EdgeTypes.HAS_FACET); - if (null != generalLabels) { - for (int i = 0; i < generalLabels.length(); i++) { - String labelString = generalLabels.getString(i); - Label label = Label.label(labelString); - facet.addLabel(label); - } - } - - tx.success(); - return facet; - } - } - - private static int countFacetChildren(GraphDatabaseService graphDb, String fid) { - // -1, because starting node gets counted, too - int childCount = -1; - try (Transaction tx = graphDb.beginTx()) { - // there is a relationship of the type "IS_BROADER_THAN_fidxxx" for - // every facet - // they need to be created dynamically because it makes no sense to - // store all of them beforehand - RelationshipType dynRel = RelationshipType.withName("IS_BROADER_THAN_" + fid); - Node node = getFacetNode(graphDb, fid); - - Traverser traverser = graphDb.traversalDescription().breadthFirst().uniqueness(Uniqueness.NODE_GLOBAL) - .relationships(ConceptManager.EdgeTypes.HAS_ROOT_CONCEPT, Direction.OUTGOING) - .relationships(dynRel, Direction.OUTGOING).traverse(node); - for (@SuppressWarnings("unused") - Node n : traverser.nodes()) { - childCount++; - } - } - return childCount; - } - - /** - * Get the node with name facetGroupName which is connected as a - * facet group to facetGroupsNode or null if no such node - * exists. - * - * @param graphDb - * @param facetGroupsNode - * @param facetGroupName - * @return - */ - private static Node getFacetGroup(GraphDatabaseService graphDb, Node facetGroupsNode, String facetGroupName) { - // Traversal to get the particular facet group node with id - // 'facetGroupId' (and the facet groups node, in case we yet need to - // create the facet group node). - TraversalDescription td = PredefinedTraversals.getFacetGroupTraversal(graphDb, facetGroupName); - Traverser traverse = td.traverse(facetGroupsNode); - - TraversalMetadata metadata = traverse.metadata(); - if (metadata != null && metadata.getNumberOfPathsReturned() > 1) - throw new IllegalStateException( - "There is more than one path from the reference node to the facet group node with name '" - + facetGroupName + "'."); - - Iterator pathIterator = traverse.iterator(); - Node facetGroupNode = null; - while (pathIterator.hasNext()) { - Path path = pathIterator.next(); - if (path.length() == 1) - facetGroupNode = path.endNode(); - } - return facetGroupNode; - } - - /** - * Creates the facetGroup node with the delivered information in - * jsonFacetGroup, connects it with facetGroupsNode and - * return the created node, or returns the existing facet group node with - * the name found at the property FacetGroupConstants.PROP_NAME in - * jsonFacetGroup. - * - * @param graphDb - * @param jsonFacetGroup - * @return The facet group node with the name found at the property - * FacetGroupConstants.PROP_NAME in jsonFacetGroup - * . - * @throws JSONException - */ - private static Node createFacetGroup(GraphDatabaseService graphDb, Node facetGroupsNode, - final JSONObject jsonFacetGroup) throws JSONException { - String facetGroupName = jsonFacetGroup.getString(FacetGroupConstants.PROP_NAME); - Node facetGroupNode = getFacetGroup(graphDb, facetGroupsNode, facetGroupName); - - if (null == facetGroupNode) { - log.log(Level.FINE, "Facet group \"" + facetGroupName + "\" (ID: " + facetGroupName - + ") does not exist and is created."); - facetGroupNode = graphDb.createNode(); - PropertyUtilities.copyJSONObjectToPropertyContainer(jsonFacetGroup, facetGroupNode, PROP_LABELS); - - int nextSequenceValue = SequenceManager.getNextSequenceValue(graphDb, SequenceConstants.SEQ_FACET_GROUP); - facetGroupNode.setProperty(PROP_ID, NodeIDPrefixConstants.FACET_GROUP + nextSequenceValue); - facetGroupsNode.createRelationshipTo(facetGroupNode, EdgeTypes.HAS_FACET_GROUP); - } - JSONArray labels = JSON.getJSONArray(jsonFacetGroup, FacetGroupConstants.PROP_LABELS); - - if (null != labels) { - for (int i = 0; i < labels.length(); i++) { - String labelString = labels.getString(i); - Label label = Label.label(labelString); - facetGroupNode.addLabel(label); - } - } - - if (null == facetGroupNode.getProperty(FacetGroupConstants.PROP_POSITION)) - throw new IllegalArgumentException("The facet group \"" + facetGroupName - + "\" does not have the required property \"" + FacetGroupConstants.PROP_POSITION - + "\". It must either be passed with the inserted facets or already exist."); - - return facetGroupNode; - } - - public static Node getFacetGroupsNode(GraphDatabaseService graphDb) { - Node facetGroupsNode = null; - try (Transaction tx = graphDb.beginTx()) { - facetGroupsNode = NodeUtilities.findSingleNodeByLabelAndProperty(graphDb, NodeConstants.Labels.ROOT, - PROP_NAME, NAME_FACET_GROUPS); - if (null == facetGroupsNode) { - facetGroupsNode = graphDb.createNode(NodeConstants.Labels.ROOT); - facetGroupsNode.setProperty(PROP_NAME, NAME_FACET_GROUPS); - } - tx.success(); - } - return facetGroupsNode; - } - - public static Node getNoFacetGroupsNode(GraphDatabaseService graphDb) { - Node facetGroupsNode; - try (Transaction tx = graphDb.beginTx()) { - facetGroupsNode = NodeUtilities.findSingleNodeByLabelAndProperty(graphDb, NodeConstants.Labels.ROOT, - PROP_NAME, NAME_NO_FACET_GROUPS); - if (null == facetGroupsNode) { - facetGroupsNode = graphDb.createNode(NodeConstants.Labels.ROOT); - facetGroupsNode.setProperty(PROP_NAME, NAME_NO_FACET_GROUPS); - } - tx.success(); - } - return facetGroupsNode; - } - - public static Node getFacetNode(GraphDatabaseService graphDb, String facetId) { - return NodeUtilities.findSingleNodeByLabelAndProperty(graphDb, FacetLabel.FACET, PROP_ID, facetId); - } - - public static Node getNoFacet(GraphDatabaseService graphDb, String facetId) { - Node noFacetNode = NodeUtilities.findSingleNodeByLabelAndProperty(graphDb, FacetLabel.NO_FACET, PROP_ID, - facetId); - if (null == noFacetNode) { - Node facetNode = getFacetNode(graphDb, facetId); - noFacetNode = NodeUtilities.copyNode(graphDb, facetNode); - noFacetNode.addLabel(FacetManager.FacetLabel.NO_FACET); - - Node noFacetGroupsNode = getNoFacetGroupsNode(graphDb); - Node facetGroupNode = NodeUtilities.getSingleOtherNode(facetNode, EdgeTypes.HAS_FACET); - Node noFacetGroupNode = getFacetGroup(graphDb, noFacetGroupsNode, - (String) facetGroupNode.getProperty(PROP_NAME)); - if (null == noFacetGroupNode) { - noFacetGroupNode = NodeUtilities.copyNode(graphDb, facetGroupNode); - noFacetGroupsNode.createRelationshipTo(noFacetGroupNode, EdgeTypes.HAS_FACET_GROUP); - } - noFacetGroupNode.createRelationshipTo(noFacetNode, EdgeTypes.HAS_FACET); - } - return noFacetNode; - } + /** + * Key of the map to send to the {@link #INSERT_FACETS} endpoint. + */ + public static final String KEY_FACETS = "facets"; + public static final String KEY_ID = "id"; + public static final String GET_FACETS = "get_facets"; + public static final String INSERT_FACETS = "insert_facets"; + public static final String GET_FACET_SIZE = "get_facet_size"; + public static final String PARAM_RETURN_HOLLOW_FACETS = "returnHollowFacets"; + private static final Logger log = Logger.getLogger(FacetManager.class.getName()); + + public static Node createFacet(GraphDatabaseService graphDb, ImportFacet jsonFacet) { + log.info("Creating facet with the following data: " + jsonFacet); + + Collection generalLabels = jsonFacet.getLabels(); + boolean isNoFacet = jsonFacet.isNoFacet(); + + ImportFacetGroup jsonFacetGroup = jsonFacet.getFacetGroup(); + + try (Transaction tx = graphDb.beginTx()) { + Node facetGroupsNode; + if (isNoFacet) + facetGroupsNode = getNoFacetGroupsNode(graphDb); + else + facetGroupsNode = getFacetGroupsNode(graphDb); + Node facetGroup = createFacetGroup(graphDb, facetGroupsNode, jsonFacetGroup); + + // Create the actual facet node and populate it with data. + Node facet = graphDb.createNode(FacetLabel.FACET); + //PropertyUtilities.copyObjectToPropertyContainer(jsonFacet, facet, NO_FACET, PROP_LABELS, + // FACET_GROUP); + + PropertyUtilities.setNonNullNodeProperty(facet, PROP_NAME, jsonFacet.getName()); + PropertyUtilities.setNonNullNodeProperty(facet, PROP_SHORT_NAME, jsonFacet.getShortName()); + PropertyUtilities.setNonNullNodeProperty(facet, PROP_CUSTOM_ID, jsonFacet.getCustomId()); + PropertyUtilities.setNonNullNodeProperty(facet, PROP_LABELS, () -> jsonFacet.getLabels().toArray(new String[0])); + PropertyUtilities.setNonNullNodeProperty(facet, PROP_SOURCE_TYPE, jsonFacet.getSourceType()); + + + // If everything is alright, get an ID for the facet. + String facetId = NodeIDPrefixConstants.FACET + + SequenceManager.getNextSequenceValue(graphDb, SequenceConstants.SEQ_FACET); + facet.setProperty(PROP_ID, facetId); + facetGroup.createRelationshipTo(facet, EdgeTypes.HAS_FACET); + if (null != generalLabels) { + for (String labelString : generalLabels) { + Label label = Label.label(labelString); + facet.addLabel(label); + } + } + + tx.success(); + return facet; + } + } + + private static int countFacetChildren(GraphDatabaseService graphDb, String fid) { + // -1, because starting node gets counted, too + int childCount = -1; + try (Transaction tx = graphDb.beginTx()) { + // there is a relationship of the type "IS_BROADER_THAN_fidxxx" for + // every facet + // they need to be created dynamically because it makes no sense to + // store all of them beforehand + RelationshipType dynRel = RelationshipType.withName("IS_BROADER_THAN_" + fid); + Node node = getFacetNode(graphDb, fid); + + Traverser traverser = graphDb.traversalDescription().breadthFirst().uniqueness(Uniqueness.NODE_GLOBAL) + .relationships(ConceptManager.EdgeTypes.HAS_ROOT_CONCEPT, Direction.OUTGOING) + .relationships(dynRel, Direction.OUTGOING).traverse(node); + for (@SuppressWarnings("unused") + Node n : traverser.nodes()) { + childCount++; + } + } + return childCount; + } + + /** + * Get the node with name facetGroupName which is connected as a + * facet group to facetGroupsNode or null if no such node + * exists. + * + * @param graphDb + * @param facetGroupsNode + * @param facetGroupName + * @return + */ + private static Node getFacetGroup(GraphDatabaseService graphDb, Node facetGroupsNode, String facetGroupName) { + // Traversal to get the particular facet group node with id + // 'facetGroupId' (and the facet groups node, in case we yet need to + // create the facet group node). + TraversalDescription td = PredefinedTraversals.getFacetGroupTraversal(graphDb, facetGroupName); + Traverser traverse = td.traverse(facetGroupsNode); + + TraversalMetadata metadata = traverse.metadata(); + if (metadata != null && metadata.getNumberOfPathsReturned() > 1) + throw new IllegalStateException( + "There is more than one path from the reference node to the facet group node with name '" + + facetGroupName + "'."); + + Iterator pathIterator = traverse.iterator(); + Node facetGroupNode = null; + while (pathIterator.hasNext()) { + Path path = pathIterator.next(); + if (path.length() == 1) + facetGroupNode = path.endNode(); + } + return facetGroupNode; + } + + /** + * Creates the facetGroup node with the delivered information in + * jsonFacetGroup, connects it with facetGroupsNode and + * return the created node, or returns the existing facet group node with + * the name found at the property FacetGroupConstants.PROP_NAME in + * jsonFacetGroup. + * + * @param graphDb + * @param jsonFacetGroup + * @return The facet group node with the name found at the property + * FacetGroupConstants.PROP_NAME in jsonFacetGroup + * . + */ + private static Node createFacetGroup(GraphDatabaseService graphDb, Node facetGroupsNode, + final ImportFacetGroup jsonFacetGroup) { + String facetGroupName = jsonFacetGroup.name; + Node facetGroupNode = getFacetGroup(graphDb, facetGroupsNode, facetGroupName); + + if (null == facetGroupNode) { + log.log(Level.FINE, "Facet group \"" + facetGroupName + "\" (ID: " + facetGroupName + + ") does not exist and is created."); + facetGroupNode = graphDb.createNode(); + PropertyUtilities.copyObjectToPropertyContainer(jsonFacetGroup, facetGroupNode, PROP_LABELS); + + int nextSequenceValue = SequenceManager.getNextSequenceValue(graphDb, SequenceConstants.SEQ_FACET_GROUP); + facetGroupNode.setProperty(PROP_ID, NodeIDPrefixConstants.FACET_GROUP + nextSequenceValue); + facetGroupsNode.createRelationshipTo(facetGroupNode, EdgeTypes.HAS_FACET_GROUP); + } + List labels = jsonFacetGroup.labels; + + if (null != labels) { + for (int i = 0; i < labels.size(); i++) { + String labelString = labels.get(i); + Label label = Label.label(labelString); + facetGroupNode.addLabel(label); + } + } + + if (null == facetGroupNode.getProperty(FacetGroupConstants.PROP_POSITION)) + throw new IllegalArgumentException("The facet group \"" + facetGroupName + + "\" does not have the required property \"" + FacetGroupConstants.PROP_POSITION + + "\". It must either be passed with the inserted facets or already exist."); + + return facetGroupNode; + } + + public static Node getFacetGroupsNode(GraphDatabaseService graphDb) { + Node facetGroupsNode = null; + try (Transaction tx = graphDb.beginTx()) { + facetGroupsNode = NodeUtilities.findSingleNodeByLabelAndProperty(graphDb, NodeConstants.Labels.ROOT, + PROP_NAME, NAME_FACET_GROUPS); + if (null == facetGroupsNode) { + facetGroupsNode = graphDb.createNode(NodeConstants.Labels.ROOT); + facetGroupsNode.setProperty(PROP_NAME, NAME_FACET_GROUPS); + } + tx.success(); + } + return facetGroupsNode; + } + + public static Node getNoFacetGroupsNode(GraphDatabaseService graphDb) { + Node facetGroupsNode; + try (Transaction tx = graphDb.beginTx()) { + facetGroupsNode = NodeUtilities.findSingleNodeByLabelAndProperty(graphDb, NodeConstants.Labels.ROOT, + PROP_NAME, NAME_NO_FACET_GROUPS); + if (null == facetGroupsNode) { + facetGroupsNode = graphDb.createNode(NodeConstants.Labels.ROOT); + facetGroupsNode.setProperty(PROP_NAME, NAME_NO_FACET_GROUPS); + } + tx.success(); + } + return facetGroupsNode; + } + + public static Node getFacetNode(GraphDatabaseService graphDb, String facetId) { + return NodeUtilities.findSingleNodeByLabelAndProperty(graphDb, FacetLabel.FACET, PROP_ID, facetId); + } + + public static Node getNoFacet(GraphDatabaseService graphDb, String facetId) { + Node noFacetNode = NodeUtilities.findSingleNodeByLabelAndProperty(graphDb, FacetLabel.NO_FACET, PROP_ID, + facetId); + if (null == noFacetNode) { + Node facetNode = getFacetNode(graphDb, facetId); + noFacetNode = NodeUtilities.copyNode(graphDb, facetNode); + noFacetNode.addLabel(FacetManager.FacetLabel.NO_FACET); + + Node noFacetGroupsNode = getNoFacetGroupsNode(graphDb); + Node facetGroupNode = NodeUtilities.getSingleOtherNode(facetNode, EdgeTypes.HAS_FACET); + Node noFacetGroupNode = getFacetGroup(graphDb, noFacetGroupsNode, + (String) facetGroupNode.getProperty(PROP_NAME)); + if (null == noFacetGroupNode) { + noFacetGroupNode = NodeUtilities.copyNode(graphDb, facetGroupNode); + noFacetGroupsNode.createRelationshipTo(noFacetGroupNode, EdgeTypes.HAS_FACET_GROUP); + } + noFacetGroupNode.createRelationshipTo(noFacetNode, EdgeTypes.HAS_FACET); + } + return noFacetNode; + } + + @Name(GET_FACET_SIZE) + @Description("Returns the size of a facet by counting all the related children") + @PluginTarget(GraphDatabaseService.class) + public int getFacetSize(@Source GraphDatabaseService graphDb, + @Description("TODO") @Parameter(name = KEY_ID) String fid) { + return countFacetChildren(graphDb, fid); + } + + @Name(INSERT_FACETS) + // TODO + @Description("TODO") + @PluginTarget(GraphDatabaseService.class) + public ListRepresentation insertFacets(@Source GraphDatabaseService graphDb, + @Description("TODO") @Parameter(name = KEY_FACETS) String facetList) throws IOException { + final ObjectMapper om = new ObjectMapper(); + List input = om.readValue(facetList, new TypeReference>() { + }); + List facets = new ArrayList(); + for (int i = 0; i < input.size(); i++) { + ImportFacet jsonFacet = input.get(i); + Node facet = createFacet(graphDb, jsonFacet); + facets.add(facet); + } + + try (Transaction tx = graphDb.beginTx()) { + // The response is a list - according to the input order - where for + // each facet is shown its name and which ID it received. + List facetRepList = new ArrayList(); + for (Node facet : facets) { + Map map = new HashMap(); + map.put(PROP_NAME, facet.getProperty(PROP_NAME)); + map.put(PROP_ID, facet.getProperty(PROP_ID)); + RecursiveMappingRepresentation facetResponseRep = new RecursiveMappingRepresentation(Representation.MAP, + map); + facetRepList.add(facetResponseRep); + } + ListRepresentation listRep = new ListRepresentation(Representation.MAP, facetRepList); + tx.success(); + return listRep; + } + + } + + @SuppressWarnings("unchecked") + @Name(GET_FACETS) + // TODO + @Description("TODO") + @PluginTarget(GraphDatabaseService.class) + public MappingRepresentation getFacets(@Source GraphDatabaseService graphDb, + @Description("TODO") @Parameter(name = PARAM_RETURN_HOLLOW_FACETS, optional = true) Boolean returnHollowfacets) { + // As of Neo4j 2.0, read operations are required to be inside a + // transaction. + RecursiveMappingRepresentation facetGroupsRep; + try (Transaction tx = graphDb.beginTx()) { + Node facetGroupsNode = getFacetGroupsNode(graphDb); + TraversalDescription td = PredefinedTraversals.getFacetTraversal(graphDb); + Traverser traverse = td.traverse(facetGroupsNode); + + Map facetsByFacetGroupName = new HashMap(); + Map facetGroupsMap = new HashMap(); + List> facetGroupsWithFacetsList = new ArrayList>(); + + // First build intermediate maps where the facet group nodes and + // facets + // are + // organized by facet group name. + for (Path facetPath : traverse) { + Node facet = facetPath.endNode(); + Object sourceType = facet.getProperty(FacetConstants.PROP_SOURCE_TYPE); + boolean isFacetWithoutPredefinedRoots = !sourceType.equals(FacetConstants.SRC_TYPE_HIERARCHICAL); + + // For string-sourced facets it doesn't make sense to check + // their roots since they have none in the + // database anyway. Same with flat facets that don't have a + // hierarchic structure. + if (!isFacetWithoutPredefinedRoots) { + // Leave out facets without any root terms (this may happen + // by some weird BioPortal ontologies). + Iterator rootIt = facet.getRelationships(ConceptManager.EdgeTypes.HAS_ROOT_CONCEPT) + .iterator(); + if (!rootIt.hasNext()) + continue; + // Also leave out facets that only have Hollow root terms + // (happens with BioPortal ontology IMMDIS + // for + // example since all classes there seem to be subclasses of + // classes that are not defined anywhere). + if (!returnHollowfacets) { + boolean onlyHollowRoots = true; + while (rootIt.hasNext() && onlyHollowRoots) { + Node rootTerm = rootIt.next().getEndNode(); + boolean isHollow = false; + for (Label label : rootTerm.getLabels()) { + if (label.equals(ConceptLabel.HOLLOW)) { + isHollow = true; + break; + } + } + if (!isHollow) + onlyHollowRoots = false; + } + if (onlyHollowRoots) + continue; + } + } + + Iterable facetRels = facet.getRelationships(Direction.INCOMING, EdgeTypes.HAS_FACET); + for (Relationship facetRel : facetRels) { + Node facetGroupNode = facetRel.getStartNode(); + String facetGroupName = (String) facetGroupNode.getProperty(PROP_NAME); + + facetGroupsMap.put(facetGroupName, facetGroupNode); + + List facets = (List) facetsByFacetGroupName.get(facetGroupName); + if (facets == null) { + facets = new ArrayList(); + facetsByFacetGroupName.put(facetGroupName, facets); + } + facets.add(facet); + } + + } + + // Now connect the intermediate maps into a final list of facet + // groups + // where each facet group contains the facets belonging to it. + for (String facetGroupName : facetsByFacetGroupName.keySet()) { + Node facetGroupNode = facetGroupsMap.get(facetGroupName); + Object facets = facetsByFacetGroupName.get(facetGroupName); + + Map facetGroupMap = new HashMap(); + for (String propKey : facetGroupNode.getPropertyKeys()) + facetGroupMap.put(propKey, facetGroupNode.getProperty(propKey)); + List facetGroupLabels = new ArrayList<>(); + for (Label label : facetGroupNode.getLabels()) + facetGroupLabels.add(label.name()); + facetGroupMap.put(FacetGroupConstants.KEY_LABELS, facetGroupLabels); + facetGroupMap.put(KEY_FACETS, facets); + + facetGroupsWithFacetsList.add(facetGroupMap); + } + Map ret = new HashMap(); + ret.put("facetGroups", facetGroupsWithFacetsList); + facetGroupsRep = new RecursiveMappingRepresentation(Representation.MAP, ret); + tx.success(); + } + + return facetGroupsRep; + } + + public static enum EdgeTypes implements RelationshipType { + HAS_FACET_GROUP, HAS_FACET + } + + public static enum FacetLabel implements Label { + FACET, NO_FACET + } } diff --git a/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/auxiliaries/semedico/ConceptAggregateBuilder.java b/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/auxiliaries/semedico/ConceptAggregateBuilder.java index 9a1b7e8..84e03a3 100644 --- a/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/auxiliaries/semedico/ConceptAggregateBuilder.java +++ b/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/auxiliaries/semedico/ConceptAggregateBuilder.java @@ -6,7 +6,6 @@ import de.julielab.neo4j.plugins.ConceptManager; import de.julielab.neo4j.plugins.ConceptManager.ConceptLabel; import de.julielab.neo4j.plugins.ConceptManager.EdgeTypes; -import de.julielab.neo4j.plugins.auxiliaries.JSON; import de.julielab.neo4j.plugins.auxiliaries.JulieNeo4jUtilities; import de.julielab.neo4j.plugins.auxiliaries.PropertyUtilities; import de.julielab.neo4j.plugins.constants.semedico.SequenceConstants; @@ -16,8 +15,6 @@ import de.julielab.neo4j.plugins.datarepresentation.constants.NodeIDPrefixConstants; import org.neo4j.graphdb.*; import org.neo4j.graphdb.index.Index; -import org.neo4j.shell.util.json.JSONArray; -import org.neo4j.shell.util.json.JSONException; import java.util.*; import java.util.logging.Logger; @@ -38,10 +35,9 @@ public class ConceptAggregateBuilder { * @param graphDb The graph database to work on. * @param termPropertyKey actually not clear right now ;-) * @param propertyValues The properties to merge for aggregated nodes. - * @throws JSONException If propertyValues is not a valid JSON string. */ public static void buildAggregatesForEqualNames(GraphDatabaseService graphDb, String termPropertyKey, - JSONArray propertyValues) throws JSONException { + String[] propertyValues) { TermNameAndSynonymComparator nameAndSynonymComparator = new TermNameAndSynonymComparator(); try (Transaction tx = graphDb.beginTx()) { Index termIndex = graphDb.index().forNodes(INDEX_NAME); @@ -75,8 +71,7 @@ public static void buildAggregatesForEqualNames(GraphDatabaseService graphDb, St new String[]{ConceptManager.ConceptLabel.AGGREGATE_EQUAL_NAMES.toString()}, termIndex, ConceptManager.ConceptLabel.AGGREGATE_EQUAL_NAMES); for (Node equalNameTerm : equalNameTerms) - NodeUtilities.mergeArrayProperty(equalNameTerm, termPropertyKey, - JSON.json2JavaArray(propertyValues)); + NodeUtilities.mergeArrayProperty(equalNameTerm, termPropertyKey, propertyValues); equalNameTerms.clear(); equalNameTerms.add(term); } else { @@ -89,7 +84,7 @@ public static void buildAggregatesForEqualNames(GraphDatabaseService graphDb, St new String[]{ConceptManager.ConceptLabel.AGGREGATE_EQUAL_NAMES.toString()}, termIndex, ConceptManager.ConceptLabel.AGGREGATE_EQUAL_NAMES); for (Node term : equalNameTerms) - NodeUtilities.mergeArrayProperty(term, termPropertyKey, JSON.json2JavaArray(propertyValues)); + NodeUtilities.mergeArrayProperty(term, termPropertyKey, propertyValues); tx.success(); } diff --git a/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/auxiliaries/semedico/CoordinatesMap.java b/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/auxiliaries/semedico/CoordinatesMap.java index 5516553..77ca8fe 100644 --- a/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/auxiliaries/semedico/CoordinatesMap.java +++ b/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/auxiliaries/semedico/CoordinatesMap.java @@ -1,11 +1,10 @@ package de.julielab.neo4j.plugins.auxiliaries.semedico; -import java.util.HashMap; -import java.util.Map; - +import de.julielab.neo4j.plugins.datarepresentation.ConceptCoordinates; import org.neo4j.graphdb.Node; -import de.julielab.neo4j.plugins.datarepresentation.ConceptCoordinates; +import java.util.HashMap; +import java.util.Map; public class CoordinatesMap { private CoordinatesSet keys = new CoordinatesSet(); diff --git a/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/auxiliaries/semedico/CoordinatesSet.java b/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/auxiliaries/semedico/CoordinatesSet.java index dda448c..a85cb42 100644 --- a/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/auxiliaries/semedico/CoordinatesSet.java +++ b/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/auxiliaries/semedico/CoordinatesSet.java @@ -1,13 +1,9 @@ package de.julielab.neo4j.plugins.auxiliaries.semedico; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; - import de.julielab.neo4j.plugins.datarepresentation.ConceptCoordinates; +import java.util.*; + public class CoordinatesSet implements Iterable { private Map coordsByOriginalId = new HashMap<>(); private Map coordsBySourceId = new HashMap<>(); diff --git a/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/auxiliaries/semedico/NodeUtilities.java b/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/auxiliaries/semedico/NodeUtilities.java index c1ff038..3552622 100644 --- a/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/auxiliaries/semedico/NodeUtilities.java +++ b/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/auxiliaries/semedico/NodeUtilities.java @@ -1,26 +1,9 @@ package de.julielab.neo4j.plugins.auxiliaries.semedico; -import static de.julielab.neo4j.plugins.datarepresentation.constants.ConceptConstants.PARENT_COORDINATES; -import static de.julielab.neo4j.plugins.datarepresentation.constants.ConceptConstants.COORDINATES; -import static de.julielab.neo4j.plugins.datarepresentation.constants.ConceptConstants.PROP_FACETS; -import static de.julielab.neo4j.plugins.datarepresentation.constants.ConceptConstants.PROP_PREF_NAME; -import static de.julielab.neo4j.plugins.datarepresentation.constants.ConceptConstants.PROP_SOURCES; -import static de.julielab.neo4j.plugins.datarepresentation.constants.ConceptConstants.PROP_SRC_IDS; -import static de.julielab.neo4j.plugins.datarepresentation.constants.ConceptConstants.PROP_SYNONYMS; -import static de.julielab.neo4j.plugins.datarepresentation.constants.ConceptConstants.PROP_UNIQUE_SRC_ID; -import static de.julielab.neo4j.plugins.datarepresentation.constants.ConceptConstants.RELATIONSHIPS; -import static de.julielab.neo4j.plugins.datarepresentation.constants.NodeConstants.PROP_ID; -import static de.julielab.neo4j.plugins.datarepresentation.constants.NodeConstants.PROP_NAME; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.StreamSupport; - import de.julielab.neo4j.plugins.ConceptManager; import de.julielab.neo4j.plugins.ConceptManager.EdgeTypes; +import de.julielab.neo4j.plugins.auxiliaries.PropertyUtilities; +import de.julielab.neo4j.plugins.datarepresentation.constants.ConceptConstants; import org.apache.commons.lang.StringUtils; import org.neo4j.graphdb.Direction; import org.neo4j.graphdb.Label; @@ -29,8 +12,16 @@ import org.neo4j.graphdb.index.Index; import org.neo4j.graphdb.index.IndexHits; -import de.julielab.neo4j.plugins.auxiliaries.PropertyUtilities; -import de.julielab.neo4j.plugins.datarepresentation.constants.ConceptConstants; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +import static de.julielab.neo4j.plugins.datarepresentation.constants.ConceptConstants.*; +import static de.julielab.neo4j.plugins.datarepresentation.constants.NodeConstants.PROP_ID; +import static de.julielab.neo4j.plugins.datarepresentation.constants.NodeConstants.PROP_NAME; public class NodeUtilities extends de.julielab.neo4j.plugins.auxiliaries.NodeUtilities { diff --git a/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/auxiliaries/semedico/PredefinedTraversals.java b/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/auxiliaries/semedico/PredefinedTraversals.java index 824273f..965b4b4 100644 --- a/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/auxiliaries/semedico/PredefinedTraversals.java +++ b/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/auxiliaries/semedico/PredefinedTraversals.java @@ -1,19 +1,18 @@ package de.julielab.neo4j.plugins.auxiliaries.semedico; -import org.apache.commons.lang.StringUtils; -import org.neo4j.graphdb.Direction; -import org.neo4j.graphdb.GraphDatabaseService; -import org.neo4j.graphdb.RelationshipType; -import org.neo4j.graphdb.traversal.Evaluators; -import org.neo4j.graphdb.traversal.TraversalDescription; - +import de.julielab.neo4j.plugins.ConceptManager; import de.julielab.neo4j.plugins.FacetManager; import de.julielab.neo4j.plugins.FacetManager.EdgeTypes; -import de.julielab.neo4j.plugins.ConceptManager; import de.julielab.neo4j.plugins.evaluators.FacetGroupPathEvaluator; import de.julielab.neo4j.plugins.evaluators.HasRelationShipEvaluator; import de.julielab.neo4j.plugins.evaluators.NodeLabelEvaluator; import de.julielab.neo4j.plugins.evaluators.PropertyEvaluator; +import org.apache.commons.lang.StringUtils; +import org.neo4j.graphdb.Direction; +import org.neo4j.graphdb.GraphDatabaseService; +import org.neo4j.graphdb.RelationshipType; +import org.neo4j.graphdb.traversal.Evaluators; +import org.neo4j.graphdb.traversal.TraversalDescription; public class PredefinedTraversals { /** diff --git a/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/auxiliaries/semedico/SequenceManager.java b/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/auxiliaries/semedico/SequenceManager.java index 329bd76..69edc8b 100644 --- a/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/auxiliaries/semedico/SequenceManager.java +++ b/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/auxiliaries/semedico/SequenceManager.java @@ -1,20 +1,15 @@ package de.julielab.neo4j.plugins.auxiliaries.semedico; -import static de.julielab.neo4j.plugins.constants.semedico.SequenceConstants.NAME_SEQUENCES_ROOT; -import static de.julielab.neo4j.plugins.datarepresentation.constants.NodeConstants.PROP_NAME; -import static de.julielab.neo4j.plugins.datarepresentation.constants.NodeConstants.PROP_VALUE; - -import java.util.NoSuchElementException; - -import org.neo4j.graphdb.GraphDatabaseService; -import org.neo4j.graphdb.Label; -import org.neo4j.graphdb.Node; -import org.neo4j.graphdb.RelationshipType; -import org.neo4j.graphdb.Transaction; +import de.julielab.neo4j.plugins.datarepresentation.constants.NodeConstants; +import org.neo4j.graphdb.*; import org.neo4j.graphdb.index.Index; import org.neo4j.graphdb.index.IndexHits; -import de.julielab.neo4j.plugins.datarepresentation.constants.NodeConstants; +import java.util.NoSuchElementException; + +import static de.julielab.neo4j.plugins.constants.semedico.SequenceConstants.NAME_SEQUENCES_ROOT; +import static de.julielab.neo4j.plugins.datarepresentation.constants.NodeConstants.PROP_NAME; +import static de.julielab.neo4j.plugins.datarepresentation.constants.NodeConstants.PROP_VALUE; public class SequenceManager { diff --git a/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/auxiliaries/semedico/TermNameAndSynonymComparator.java b/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/auxiliaries/semedico/TermNameAndSynonymComparator.java index aee76c1..2393b29 100644 --- a/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/auxiliaries/semedico/TermNameAndSynonymComparator.java +++ b/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/auxiliaries/semedico/TermNameAndSynonymComparator.java @@ -1,18 +1,16 @@ package de.julielab.neo4j.plugins.auxiliaries.semedico; +import com.ibm.icu.text.Collator; +import com.ibm.icu.text.RuleBasedCollator; +import de.julielab.neo4j.plugins.datarepresentation.constants.ConceptConstants; +import org.apache.commons.lang.StringUtils; +import org.neo4j.graphdb.Node; + import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; -import org.apache.commons.lang.StringUtils; -import org.neo4j.graphdb.Node; - -import com.ibm.icu.text.Collator; -import com.ibm.icu.text.RuleBasedCollator; - -import de.julielab.neo4j.plugins.datarepresentation.constants.ConceptConstants; - /** * This comparator can be used to sort nodes according to their similarity in preferred name and synonyms. The * comparator uses a {@link RuleBasedCollator} to remove differences due to case or accents. diff --git a/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/auxiliaries/semedico/TermVariantComparator.java b/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/auxiliaries/semedico/TermVariantComparator.java index 0d25b09..d82e377 100644 --- a/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/auxiliaries/semedico/TermVariantComparator.java +++ b/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/auxiliaries/semedico/TermVariantComparator.java @@ -1,10 +1,10 @@ package de.julielab.neo4j.plugins.auxiliaries.semedico; +import org.apache.commons.lang3.StringUtils; + import java.util.Comparator; import java.util.Locale; -import org.apache.commons.lang3.StringUtils; - /** * This comparator aims to judge whether two term writing variants are the same * or not. For this purpose, some minor normalizations are applied to the diff --git a/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/evaluators/FacetGroupPathEvaluator.java b/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/evaluators/FacetGroupPathEvaluator.java index 276c9fe..09964dc 100644 --- a/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/evaluators/FacetGroupPathEvaluator.java +++ b/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/evaluators/FacetGroupPathEvaluator.java @@ -1,13 +1,12 @@ package de.julielab.neo4j.plugins.evaluators; +import de.julielab.neo4j.plugins.datarepresentation.constants.ConceptConstants; +import de.julielab.neo4j.plugins.datarepresentation.constants.FacetConstants; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Path; import org.neo4j.graphdb.traversal.Evaluation; import org.neo4j.graphdb.traversal.Evaluator; -import de.julielab.neo4j.plugins.datarepresentation.constants.ConceptConstants; -import de.julielab.neo4j.plugins.datarepresentation.constants.FacetConstants; - /** * An Evaluator which includes the facet groups node as well as the * facet group with the name passed to the constructor. diff --git a/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/evaluators/FacetGroupsEvaluator.java b/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/evaluators/FacetGroupsEvaluator.java index a71fb22..6a3bae6 100644 --- a/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/evaluators/FacetGroupsEvaluator.java +++ b/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/evaluators/FacetGroupsEvaluator.java @@ -1,13 +1,13 @@ package de.julielab.neo4j.plugins.evaluators; -import static de.julielab.neo4j.plugins.datarepresentation.constants.NodeConstants.PROP_NAME; -import static de.julielab.neo4j.plugins.datarepresentation.constants.FacetConstants.NAME_FACET_GROUPS; - import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Path; import org.neo4j.graphdb.traversal.Evaluation; import org.neo4j.graphdb.traversal.Evaluator; +import static de.julielab.neo4j.plugins.datarepresentation.constants.FacetConstants.NAME_FACET_GROUPS; +import static de.julielab.neo4j.plugins.datarepresentation.constants.NodeConstants.PROP_NAME; + /** * Evaluates to {@link Evaluation#INCLUDE_AND_CONTINUE} for the facet groups * node, i.e. the predecessor of the individual facet group nodes. diff --git a/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/evaluators/PropertyEvaluator.java b/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/evaluators/PropertyEvaluator.java index fd95a91..0bd5cca 100644 --- a/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/evaluators/PropertyEvaluator.java +++ b/julielab-neo4j-plugins-concepts/src/main/java/de/julielab/neo4j/plugins/evaluators/PropertyEvaluator.java @@ -1,13 +1,13 @@ package de.julielab.neo4j.plugins.evaluators; -import java.util.ArrayList; -import java.util.List; - import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Path; import org.neo4j.graphdb.traversal.Evaluation; import org.neo4j.graphdb.traversal.Evaluator; +import java.util.ArrayList; +import java.util.List; + /** * An Evaluator that returns {@link Evaluation#INCLUDE_AND_CONTINUE} if the evaluated node has the given property key * and the value is or contains (in case the value is an array) the given property value. diff --git a/julielab-neo4j-plugins-concepts/src/test/java/de/julielab/neo4j/plugins/ConceptManagerTest.java b/julielab-neo4j-plugins-concepts/src/test/java/de/julielab/neo4j/plugins/ConceptManagerTest.java index f8dafc3..965d0e2 100644 --- a/julielab-neo4j-plugins-concepts/src/test/java/de/julielab/neo4j/plugins/ConceptManagerTest.java +++ b/julielab-neo4j-plugins-concepts/src/test/java/de/julielab/neo4j/plugins/ConceptManagerTest.java @@ -17,10 +17,7 @@ import de.julielab.neo4j.plugins.util.AggregateConceptInsertionException; import de.julielab.neo4j.plugins.util.ConceptInsertionException; import org.apache.commons.lang.StringUtils; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.*; import org.neo4j.graphalgo.GraphAlgoFactory; import org.neo4j.graphalgo.PathFinder; import org.neo4j.graphdb.*; @@ -28,9 +25,8 @@ import org.neo4j.graphdb.index.IndexHits; import org.neo4j.graphdb.index.IndexManager; import org.neo4j.server.rest.repr.RecursiveMappingRepresentation; -import org.neo4j.shell.util.json.JSONException; -import org.neo4j.shell.util.json.JSONObject; +import java.io.IOException; import java.util.*; import java.util.stream.Stream; @@ -69,22 +65,22 @@ public void testOriginalIdMerging() throws Exception { ImportConcepts testTerms; testTerms = getTestTerms(1); - testTerms.getConceptsAsList().get(0).coordinates.originalId = "orgId"; - testTerms.getConceptsAsList().get(0).coordinates.originalSource = "src1"; - testTerms.getConceptsAsList().get(0).coordinates.source = "src1"; + testTerms.getConcepts().get(0).coordinates.originalId = "orgId"; + testTerms.getConcepts().get(0).coordinates.originalSource = "src1"; + testTerms.getConcepts().get(0).coordinates.source = "src1"; tm.insertConcepts(graphDb, ConceptsJsonSerializer.toJson(testTerms)); testTerms = getTestTerms(1); - testTerms.getConceptsAsList().get(0).coordinates.originalId = "orgId"; - testTerms.getConceptsAsList().get(0).coordinates.originalSource = "src1"; - testTerms.getConceptsAsList().get(0).coordinates.source = "src2"; + testTerms.getConcepts().get(0).coordinates.originalId = "orgId"; + testTerms.getConcepts().get(0).coordinates.originalSource = "src1"; + testTerms.getConcepts().get(0).coordinates.source = "src2"; tm.insertConcepts(graphDb, ConceptsJsonSerializer.toJson(testTerms)); testTerms = getTestTerms(1); - testTerms.getConceptsAsList().get(0).coordinates.sourceId = "CONCEPT42"; - testTerms.getConceptsAsList().get(0).coordinates.originalId = "orgId"; - testTerms.getConceptsAsList().get(0).coordinates.originalSource = "src1"; - testTerms.getConceptsAsList().get(0).coordinates.source = null; + testTerms.getConcepts().get(0).coordinates.sourceId = "CONCEPT42"; + testTerms.getConcepts().get(0).coordinates.originalId = "orgId"; + testTerms.getConcepts().get(0).coordinates.originalSource = "src1"; + testTerms.getConcepts().get(0).coordinates.source = null; tm.insertConcepts(graphDb, ConceptsJsonSerializer.toJson(testTerms)); try (Transaction tx = graphDb.beginTx()) { @@ -110,10 +106,10 @@ public void testMergeOnOriginalIdWithoutSourceId() throws Exception { ImportConcepts testTerms; testTerms = getTestTerms(1); - testTerms.getConceptsAsList().get(0).coordinates.originalId = "orgId"; - testTerms.getConceptsAsList().get(0).coordinates.originalSource = "src1"; - testTerms.getConceptsAsList().get(0).coordinates.source = "someSource"; - testTerms.getConceptsAsList().get(0).descriptions = null; + testTerms.getConcepts().get(0).coordinates.originalId = "orgId"; + testTerms.getConcepts().get(0).coordinates.originalSource = "src1"; + testTerms.getConcepts().get(0).coordinates.source = "someSource"; + testTerms.getConcepts().get(0).descriptions = null; tm.insertConcepts(graphDb, ConceptsJsonSerializer.toJson(testTerms)); try (Transaction tx = graphDb.beginTx()) { @@ -126,10 +122,10 @@ public void testMergeOnOriginalIdWithoutSourceId() throws Exception { // Now add a description, only by knowing the term's original ID. testTerms = getTestTerms(1); - testTerms.getConceptsAsList().get(0).coordinates.originalId = "orgId"; - testTerms.getConceptsAsList().get(0).coordinates.originalSource = "src1"; - testTerms.getConceptsAsList().get(0).coordinates.sourceId = null; - testTerms.getConceptsAsList().get(0).descriptions = Lists.newArrayList("desc"); + testTerms.getConcepts().get(0).coordinates.originalId = "orgId"; + testTerms.getConcepts().get(0).coordinates.originalSource = "src1"; + testTerms.getConcepts().get(0).coordinates.sourceId = null; + testTerms.getConcepts().get(0).descriptions = Lists.newArrayList("desc"); ImportOptions importOptions = new ImportOptions(); importOptions.merge = true; testTerms.setImportOptions(importOptions); @@ -156,19 +152,19 @@ public void testSameOrgIdDifferentSource() throws Exception { ImportConcepts testTerms; testTerms = getTestTerms(1); - testTerms.getConceptsAsList().get(0).coordinates.originalId = "orgId"; - testTerms.getConceptsAsList().get(0).coordinates.originalSource = "src1"; + testTerms.getConcepts().get(0).coordinates.originalId = "orgId"; + testTerms.getConcepts().get(0).coordinates.originalSource = "src1"; // we also have to set the source ID and source of at least one term to // a different value or we will get an exception telling us that our // data is inconsistent (because source ID and source would match but // the original ID and original source wouldn't) - testTerms.getConceptsAsList().get(0).coordinates.sourceId = "anothersourceid"; - testTerms.getConceptsAsList().get(0).coordinates.source = "anothersource"; + testTerms.getConcepts().get(0).coordinates.sourceId = "anothersourceid"; + testTerms.getConcepts().get(0).coordinates.source = "anothersource"; tm.insertConcepts(graphDb, ConceptsJsonSerializer.toJson(testTerms)); testTerms = getTestTerms(1); - testTerms.getConceptsAsList().get(0).coordinates.originalId = "orgId"; - testTerms.getConceptsAsList().get(0).coordinates.originalSource = "src2"; + testTerms.getConcepts().get(0).coordinates.originalId = "orgId"; + testTerms.getConcepts().get(0).coordinates.originalSource = "src2"; tm.insertConcepts(graphDb, ConceptsJsonSerializer.toJson(testTerms)); try (Transaction tx = graphDb.beginTx()) { @@ -196,8 +192,8 @@ public void testSameOrgIdDifferentSource() throws Exception { * */ @Test - public void testImportConceptsWithFacetDefinition() throws JSONException, SecurityException, - IllegalArgumentException, ConceptInsertionException { + public void testImportConceptsWithFacetDefinition() throws SecurityException, + IllegalArgumentException, ConceptInsertionException, IOException { testTermImportWithOrWithoutFacetDefinition(true); } @@ -208,14 +204,13 @@ public void testImportConceptsWithoutFacetDefinition() throws Exception { // one facet, so its fid0...) ImportFacet facetMap = FacetManagerTest.getImportFacet(); - String jsonFacet = ConceptsJsonSerializer.toJson(facetMap); - FacetManager.createFacet(graphDb, new JSONObject(jsonFacet)); + FacetManager.createFacet(graphDb, facetMap); // Do the term import and tests. testTermImportWithOrWithoutFacetDefinition(false); } - private void testTermImportWithOrWithoutFacetDefinition(boolean withFacetDefinition) throws JSONException, ConceptInsertionException { + private void testTermImportWithOrWithoutFacetDefinition(boolean withFacetDefinition) throws ConceptInsertionException, IOException { // ----------- THE FACET -------------- ImportFacet facetMap; if (withFacetDefinition) { @@ -360,8 +355,7 @@ public void testInsertTermIntoMultipleFacets() throws Exception { // Create the 2nd facet separately. facetMap = FacetManagerTest.getTestFacetMap(2); - String jsonFacet = ConceptsJsonSerializer.toJson(facetMap); - FacetManager.createFacet(graphDb, new JSONObject(jsonFacet)); + FacetManager.createFacet(graphDb, facetMap); // ---------- SEND CONCEPT ONLY WITH FACET ID -------- facetMap = new ImportFacet("fid1"); @@ -505,11 +499,11 @@ public void testMergeTermLabels() throws Exception { testTerms = getTestTerms(1); testTerms.setImportOptions(new ImportOptions()); testTerms.getImportOptions().merge = true; - testTerms.getConceptsAsList().get(0).addGeneralLabel("ANOTHER_LABEL"); + testTerms.getConcepts().get(0).addGeneralLabel("ANOTHER_LABEL"); // just to make am more thorough test, we change the source coordinates (but NOT // the original coordinates) - testTerms.getConceptsAsList().get(0).coordinates.sourceId = "somesrcid"; - testTerms.getConceptsAsList().get(0).coordinates.source = "somesrc"; + testTerms.getConcepts().get(0).coordinates.sourceId = "somesrcid"; + testTerms.getConcepts().get(0).coordinates.source = "somesrc"; cm.insertConcepts(graphDb, ConceptsJsonSerializer.toJson(testTerms)); try (Transaction tx = graphDb.beginTx()) { @@ -622,8 +616,7 @@ public void testImportEdgeMultipleTimes() throws Exception { * "Matching facet" means that in this test, there is a facet - and the test * terms belong to that facet - that has the label "USE_FOR_SUGGESTIONS". * - * @throws JSONException - * @throws AggregateConceptInsertionException + * @throws AggregateConceptInsertionException */ @Test public void testPushAllTermsToSetMatchingFacet() throws Exception { @@ -637,8 +630,8 @@ public void testPushAllTermsToSetMatchingFacet() throws Exception { // We set for two terms the general properties // "do not use for suggestions", "do not use for query dictionary" // that should be excluded then. - testTerms.getConceptsAsList().get(numTerms).addGeneralLabel(termLabelDoNotUseForSuggestions); - testTerms.getConceptsAsList().get(numTerms + 1).addGeneralLabel(termLabelDoNotUseForSuggestions); + testTerms.getConcepts().get(numTerms).addGeneralLabel(termLabelDoNotUseForSuggestions); + testTerms.getConcepts().get(numTerms + 1).addGeneralLabel(termLabelDoNotUseForSuggestions); // We do set the correct property to the test facet so that the test // method call to pushAllTermsToSet() may refer to this property as a // constraint. @@ -694,8 +687,7 @@ public void testPushAllTermsToSetMatchingFacet() throws Exception { * property "general labels" with the value "USE_FOR_SUGGESTIONS". Thus, no * terms should be pushed into the set. * - * @throws JSONException - * @throws AggregateConceptInsertionException + * @throws AggregateConceptInsertionException */ @Test public void testPushAllTermstoSetNoMatchingFacet() throws Exception { @@ -868,7 +860,7 @@ public void testAdditionalRelationships() throws Exception { // created on behalf of the referenced other half. After inserting // this other half, there should be no more "hollow" terms. ImportConcepts testTermsAndFacet = getTestTerms(4); - List terms = testTermsAndFacet.getConceptsAsList(); + List terms = testTermsAndFacet.getConcepts(); // Now we just create relationships so that: // 0 equals 1 // 0 equals 3 @@ -975,7 +967,7 @@ public void testAdditionalRelationships() throws Exception { @Test public void testAdditionalRelationships2() throws Exception { ImportConcepts testTermsAndFacet = getTestTerms(4); - List terms = testTermsAndFacet.getConceptsAsList(); + List terms = testTermsAndFacet.getConcepts(); String termSource = terms.get(0).coordinates.originalSource; ImportConceptRelationship rel1 = new ImportConceptRelationship(new ConceptCoordinates("CONCEPT" + 1, termSource, true), ConceptManager.EdgeTypes.HAS_SAME_NAMES.name()); @@ -1012,7 +1004,7 @@ public void testInsertAggregateTerm() throws Exception { // from external data as opposed to // computing it within the database. ImportConcepts testTerms = getTestTerms(5); - List terms = testTerms.getConceptsAsList(); + List terms = testTerms.getConcepts(); // Add an aggregate term with terms 0-3 as elements. The term on // position 4 will stay alone. List aggregateElementSrcIds = Lists.newArrayList("CONCEPT" + 0, "CONCEPT" + 1, "CONCEPT" + 2, "CONCEPT" + 3); @@ -1083,9 +1075,9 @@ public void testAddAggregateAsHierarchyNode() throws Exception { Collections.singletonList(PROP_PREF_NAME)); aggregate.coordinates = new ConceptCoordinates("testagg", "TEST_DATA", SRC); aggregate.aggregateIncludeInHierarchy = true; - testTerms.getConceptsAsList().add(aggregate); - testTerms.getConceptsAsList().get(0).parentCoordinates = Collections.singletonList(new ConceptCoordinates("testagg", "TEST_DATA", SRC)); - testTerms.getConceptsAsList().get(1).parentCoordinates = Collections.singletonList(new ConceptCoordinates("testagg", "TEST_DATA", SRC)); + testTerms.getConcepts().add(aggregate); + testTerms.getConcepts().get(0).parentCoordinates = Collections.singletonList(new ConceptCoordinates("testagg", "TEST_DATA", SRC)); + testTerms.getConcepts().get(1).parentCoordinates = Collections.singletonList(new ConceptCoordinates("testagg", "TEST_DATA", SRC)); ConceptManager ftm = new ConceptManager(); ftm.insertConcepts(graphDb, ConceptsJsonSerializer.toJson(testTerms)); @@ -1121,10 +1113,10 @@ public void testAddAggregateAsHierarchyNode2() throws Exception { aggregate.coordinates = new ConceptCoordinates("testagg", "TEST_CONCEPT", SRC); aggregate.aggregateIncludeInHierarchy = true; aggregate.generalLabels = Arrays.asList("MY_COOL_AGGREGATE_LABEL"); - testTerms.getConceptsAsList().add(aggregate); - testTerms.getConceptsAsList().get(0).parentCoordinates = Arrays + testTerms.getConcepts().add(aggregate); + testTerms.getConcepts().get(0).parentCoordinates = Arrays .asList(new ConceptCoordinates("testagg", "TEST_CONCEPT", SRC)); - testTerms.getConceptsAsList().get(1).parentCoordinates = Arrays + testTerms.getConcepts().get(1).parentCoordinates = Arrays .asList(new ConceptCoordinates("testagg", "TEST_CONCEPT", SRC)); ConceptManager ftm = new ConceptManager(); @@ -1234,13 +1226,13 @@ public void testBuildMappingAggregate() throws Exception { testTerms2.getFacet().setName("facet2"); testTerms3.getFacet().setName("facet3"); testTerms4.getFacet().setName("facet4"); - testTerms1.getConceptsAsList().get(0).parentCoordinates = Arrays + testTerms1.getConcepts().get(0).parentCoordinates = Arrays .asList(new ConceptCoordinates("CONCEPT0", "TEST_DATA", SRC)); - testTerms2.getConceptsAsList().get(0).parentCoordinates = Arrays + testTerms2.getConcepts().get(0).parentCoordinates = Arrays .asList(new ConceptCoordinates("CONCEPT1", "TEST_DATA", SRC)); - testTerms3.getConceptsAsList().get(0).parentCoordinates = Arrays + testTerms3.getConcepts().get(0).parentCoordinates = Arrays .asList(new ConceptCoordinates("CONCEPT2", "TEST_DATA", SRC)); - testTerms4.getConceptsAsList().get(0).parentCoordinates = Arrays + testTerms4.getConcepts().get(0).parentCoordinates = Arrays .asList(new ConceptCoordinates("CONCEPT3", "TEST_DATA", SRC)); ftm.insertConcepts(graphDb, ConceptsJsonSerializer.toJson(testTerms)); ftm.insertConcepts(graphDb, ConceptsJsonSerializer.toJson(testTerms1)); @@ -1273,7 +1265,7 @@ public void testBuildMappingAggregate() throws Exception { // now: get the "children" of the aggregate (should be the elements) RecursiveMappingRepresentation response = (RecursiveMappingRepresentation) ftm.getChildrenOfConcepts( - graphDb, "[" + NodeIDPrefixConstants.AGGREGATE_TERM + "0]", ConceptLabel.AGGREGATE.name()); + graphDb, "[\"" + NodeIDPrefixConstants.AGGREGATE_TERM + "0\"]", ConceptLabel.AGGREGATE.name()); @SuppressWarnings("unchecked") Map relAndChildMap = (Map) response.getUnderlyingMap() .get(NodeIDPrefixConstants.AGGREGATE_TERM + 0); @@ -1430,7 +1422,7 @@ public void testNonFacetGroupCommand() throws Exception { AddToNonFacetGroupCommand cmd = new AddToNonFacetGroupCommand(); cmd.addParentCriterium(AddToNonFacetGroupCommand.ParentCriterium.NO_PARENT); options.noFacetCmd = cmd; - List terms = testTerms.getConceptsAsList(); + List terms = testTerms.getConcepts(); // Here, we just give any parent so that the non-facet-group-command // does not trigger. List parentSrcIds = Lists @@ -1655,7 +1647,7 @@ public void testUpdateChildrenInformation() throws Exception { ImportConcepts testTerms; ConceptManager ftm = new ConceptManager(); testTerms = getTestTerms(2); - testTerms.getConceptsAsList().get(1).parentCoordinates = Arrays + testTerms.getConcepts().get(1).parentCoordinates = Arrays .asList(new ConceptCoordinates("CONCEPT0", "TEST_DATA", SRC)); ftm.insertConcepts(graphDb, ConceptsJsonSerializer.toJson(testTerms)); @@ -1664,13 +1656,13 @@ public void testUpdateChildrenInformation() throws Exception { // two because the duplicate source IDs would be detected. testTerms = getTestTerms(2); testTerms.getFacet().setName("secondfacet"); - testTerms.getConceptsAsList().get(0).coordinates.sourceId = "CONCEPT2"; - testTerms.getConceptsAsList().get(0).coordinates.originalId = "CONCEPT2"; - testTerms.getConceptsAsList().get(1).coordinates.sourceId = "CONCEPT3"; - testTerms.getConceptsAsList().get(1).coordinates.originalId = "CONCEPT3"; - testTerms.getConceptsAsList().get(0).parentCoordinates = Arrays + testTerms.getConcepts().get(0).coordinates.sourceId = "CONCEPT2"; + testTerms.getConcepts().get(0).coordinates.originalId = "CONCEPT2"; + testTerms.getConcepts().get(1).coordinates.sourceId = "CONCEPT3"; + testTerms.getConcepts().get(1).coordinates.originalId = "CONCEPT3"; + testTerms.getConcepts().get(0).parentCoordinates = Arrays .asList(new ConceptCoordinates("CONCEPT0", "TEST_DATA", SRC)); - testTerms.getConceptsAsList().get(1).parentCoordinates = Arrays + testTerms.getConcepts().get(1).parentCoordinates = Arrays .asList(new ConceptCoordinates("CONCEPT0", "TEST_DATA", SRC)); ftm.insertConcepts(graphDb, ConceptsJsonSerializer.toJson(testTerms)); @@ -1693,13 +1685,13 @@ public void testGetTermChildren() throws Exception { ImportConcepts testTerms; ConceptManager ftm = new ConceptManager(); testTerms = getTestTerms(5); - testTerms.getConceptsAsList().get(1).parentCoordinates = Arrays + testTerms.getConcepts().get(1).parentCoordinates = Arrays .asList(new ConceptCoordinates("CONCEPT0", "TEST_DATA", SRC)); - testTerms.getConceptsAsList().get(2).parentCoordinates = Arrays + testTerms.getConcepts().get(2).parentCoordinates = Arrays .asList(new ConceptCoordinates("CONCEPT0", "TEST_DATA", SRC)); - testTerms.getConceptsAsList().get(3).parentCoordinates = Arrays + testTerms.getConcepts().get(3).parentCoordinates = Arrays .asList(new ConceptCoordinates("CONCEPT0", "TEST_DATA", SRC)); - testTerms.getConceptsAsList().get(4).parentCoordinates = Arrays + testTerms.getConcepts().get(4).parentCoordinates = Arrays .asList(new ConceptCoordinates("CONCEPT3", "TEST_DATA", SRC)); ftm.insertConcepts(graphDb, ConceptsJsonSerializer.toJson(testTerms)); @@ -1760,13 +1752,13 @@ public void testAddMappings() throws Exception { testTerms2.getFacet().setName("facet2"); testTerms3.getFacet().setName("facet3"); testTerms4.getFacet().setName("facet4"); - testTerms1.getConceptsAsList().get(0).parentCoordinates = Arrays + testTerms1.getConcepts().get(0).parentCoordinates = Arrays .asList(new ConceptCoordinates("CONCEPT0", "TEST_DATA", SRC)); - testTerms2.getConceptsAsList().get(0).parentCoordinates = Arrays + testTerms2.getConcepts().get(0).parentCoordinates = Arrays .asList(new ConceptCoordinates("CONCEPT1", "TEST_DATA", SRC)); - testTerms3.getConceptsAsList().get(0).parentCoordinates = Arrays + testTerms3.getConcepts().get(0).parentCoordinates = Arrays .asList(new ConceptCoordinates("CONCEPT2", "TEST_DATA", SRC)); - testTerms4.getConceptsAsList().get(0).parentCoordinates = Arrays + testTerms4.getConcepts().get(0).parentCoordinates = Arrays .asList(new ConceptCoordinates("CONCEPT3", "TEST_DATA", SRC)); ftm.insertConcepts(graphDb, ConceptsJsonSerializer.toJson(testTerms)); ftm.insertConcepts(graphDb, ConceptsJsonSerializer.toJson(testTerms1)); @@ -1847,13 +1839,13 @@ public void testAddMappingsInSameFacet() throws Exception { ConceptManager ftm = new ConceptManager(); // Create terms in THE SAME facets we will then map to each other testTerms = getTestTerms(5); - testTerms.getConceptsAsList().get(1).parentCoordinates = Arrays + testTerms.getConcepts().get(1).parentCoordinates = Arrays .asList(new ConceptCoordinates("CONCEPT0", "TEST_DATA", SRC)); - testTerms.getConceptsAsList().get(2).parentCoordinates = Arrays + testTerms.getConcepts().get(2).parentCoordinates = Arrays .asList(new ConceptCoordinates("CONCEPT1", "TEST_DATA", SRC)); - testTerms.getConceptsAsList().get(3).parentCoordinates = Arrays + testTerms.getConcepts().get(3).parentCoordinates = Arrays .asList(new ConceptCoordinates("CONCEPT2", "TEST_DATA", SRC)); - testTerms.getConceptsAsList().get(4).parentCoordinates = Arrays + testTerms.getConcepts().get(4).parentCoordinates = Arrays .asList(new ConceptCoordinates("CONCEPT3", "TEST_DATA", SRC)); ftm.insertConcepts(graphDb, ConceptsJsonSerializer.toJson(testTerms)); @@ -1875,10 +1867,10 @@ public void testMergeTerms() throws Exception { // terms. ImportConcepts testTerms = getTestTerms(4); // add a fifth term that has the first term as a parent - testTerms.getConceptsAsList() + testTerms.getConcepts() .add(new ImportConcept("someterm", new ConceptCoordinates("somesrcid", "somesource", SRC), new ConceptCoordinates("CONCEPT0", "TEST_DATA", SRC))); - testTerms.getConceptsAsList().get(testTerms.getConceptsAsList().size() - 1).coordinates.source = "somesource"; + testTerms.getConcepts().get(testTerms.getConcepts().size() - 1).coordinates.source = "somesource"; ConceptManager tm = new ConceptManager(); // first insert. tm.insertConcepts(graphDb, ConceptsJsonSerializer.toJson(testTerms)); @@ -1892,15 +1884,15 @@ public void testMergeTerms() throws Exception { testTerms.setFacet(null); // Give new property values to the first term, leave the second // unchanged. - testTerms.getConceptsAsList().get(0).generalLabels = Lists.newArrayList("newlabel1"); - testTerms.getConceptsAsList().get(0).descriptions = Lists.newArrayList("newdescription1"); - testTerms.getConceptsAsList().get(0).prefName = "newprefname1"; + testTerms.getConcepts().get(0).generalLabels = Lists.newArrayList("newlabel1"); + testTerms.getConcepts().get(0).descriptions = Lists.newArrayList("newdescription1"); + testTerms.getConcepts().get(0).prefName = "newprefname1"; // re-insert the additional term from above but with a description and a // synonym, without a parent; we should // not need it since the term is already known. ImportConcept term = new ImportConcept("somesrcid", Arrays.asList("newsynonym2"), "newdesc2", new ConceptCoordinates("somesrcid", "somesource", SRC)); - testTerms.getConceptsAsList().add(term); + testTerms.getConcepts().add(term); // second insert, duplicate terms should now be merged. tm.insertConcepts(graphDb, ConceptsJsonSerializer.toJson(testTerms)); @@ -1943,6 +1935,11 @@ public void testMergeTerms() throws Exception { } @Test + // This test aims at the capability to transfer arbitrary json properties into the Neo4j node. + // This does not work any more since the neo4j shell was deprecated and all usage of JSONObject was + // let go. If this feature is necessary, we need to add some "properties" map into the ImportConcept class + // and copy from there into the Neo4j node properties. EF, August 21st 2019 + @Ignore public void testIntegerProperty() throws Exception { List> terms = new ArrayList<>(); Map term = new HashMap<>(); @@ -2272,19 +2269,19 @@ public void testUniqueSourceIds() throws Exception { ImportConcepts testTerms = getTestTerms(2); // first, remove original ID and source because otherwise the original // ID checks will take over - testTerms.getConceptsAsList().get(0).coordinates.originalId = null; - testTerms.getConceptsAsList().get(0).coordinates.originalSource = null; - testTerms.getConceptsAsList().get(1).coordinates.originalId = null; - testTerms.getConceptsAsList().get(1).coordinates.originalSource = null; + testTerms.getConcepts().get(0).coordinates.originalId = null; + testTerms.getConcepts().get(0).coordinates.originalSource = null; + testTerms.getConcepts().get(1).coordinates.originalId = null; + testTerms.getConcepts().get(1).coordinates.originalSource = null; // now set terms that should be equal by source ID despite having a // different source - testTerms.getConceptsAsList().get(0).coordinates.uniqueSourceId = true; - testTerms.getConceptsAsList().get(0).coordinates.sourceId = "id0"; - testTerms.getConceptsAsList().get(0).coordinates.source = "source0"; - testTerms.getConceptsAsList().get(1).coordinates.uniqueSourceId = true; - testTerms.getConceptsAsList().get(1).coordinates.sourceId = "id0"; - testTerms.getConceptsAsList().get(1).coordinates.source = "source1"; + testTerms.getConcepts().get(0).coordinates.uniqueSourceId = true; + testTerms.getConcepts().get(0).coordinates.sourceId = "id0"; + testTerms.getConcepts().get(0).coordinates.source = "source0"; + testTerms.getConcepts().get(1).coordinates.uniqueSourceId = true; + testTerms.getConcepts().get(1).coordinates.sourceId = "id0"; + testTerms.getConcepts().get(1).coordinates.source = "source1"; ConceptManager tm = new ConceptManager(); tm.insertConcepts(graphDb, ConceptsJsonSerializer.toJson(testTerms)); diff --git a/julielab-neo4j-plugins-concepts/src/test/java/de/julielab/neo4j/plugins/ExportTest.java b/julielab-neo4j-plugins-concepts/src/test/java/de/julielab/neo4j/plugins/ExportTest.java index fd6efea..70fc8d2 100644 --- a/julielab-neo4j-plugins-concepts/src/test/java/de/julielab/neo4j/plugins/ExportTest.java +++ b/julielab-neo4j-plugins-concepts/src/test/java/de/julielab/neo4j/plugins/ExportTest.java @@ -1,13 +1,12 @@ package de.julielab.neo4j.plugins; -import static org.junit.Assert.assertEquals; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.lang.reflect.Method; -import java.util.zip.GZIPInputStream; - +import com.google.common.collect.Lists; +import de.julielab.neo4j.plugins.auxiliaries.NodeUtilities; +import de.julielab.neo4j.plugins.datarepresentation.ConceptCoordinates; +import de.julielab.neo4j.plugins.datarepresentation.ImportConcept; +import de.julielab.neo4j.plugins.datarepresentation.ImportConcepts; +import de.julielab.neo4j.plugins.datarepresentation.util.ConceptsJsonSerializer; +import de.julielab.neo4j.plugins.test.TestUtilities; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.junit.AfterClass; @@ -18,167 +17,165 @@ import org.neo4j.graphdb.Node; import org.neo4j.graphdb.ResourceIterator; import org.neo4j.graphdb.Transaction; -import org.neo4j.shell.util.json.JSONArray; -import com.google.common.collect.Lists; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.zip.GZIPInputStream; -import de.julielab.neo4j.plugins.auxiliaries.NodeUtilities; -import de.julielab.neo4j.plugins.datarepresentation.ConceptCoordinates; -import de.julielab.neo4j.plugins.datarepresentation.ImportConcept; -import de.julielab.neo4j.plugins.datarepresentation.ImportConcepts; -import de.julielab.neo4j.plugins.datarepresentation.util.ConceptsJsonSerializer; -import de.julielab.neo4j.plugins.test.TestUtilities; +import static org.junit.Assert.assertEquals; public class ExportTest { - - private static GraphDatabaseService graphDb; - - @BeforeClass - public static void initialize() { - graphDb = TestUtilities.getGraphDB(); - } - - @Before - public void cleanForTest() throws IOException { - TestUtilities.deleteEverythingInDB(graphDb); - } - - @AfterClass - public static void shutdown() { - graphDb.shutdown(); - } - - @Test - public void createIdMappingOneFacetSourceIds() throws Exception { - ImportConcepts testTerms = ConceptManagerTest.getTestTerms(10); - testTerms.getFacet().setName("facet1"); - for (ImportConcept term : testTerms.getConceptsAsList()) { - term.generalLabels = Lists.newArrayList("TESTLABEL"); - // clear the original ID and source of the test terms for this test - term.coordinates.originalId = null; - term.coordinates.originalSource = null; - } - testTerms.getConceptsAsList().get(0).coordinates.originalId = "orgId1"; - testTerms.getConceptsAsList().get(0).coordinates.originalSource = "src1"; - testTerms.getConceptsAsList().get(1).coordinates.originalId = "orgId2"; - testTerms.getConceptsAsList().get(1).coordinates.originalSource = "src2"; - testTerms.getConceptsAsList().get(2).coordinates.originalId = "orgId3"; - testTerms.getConceptsAsList().get(2).coordinates.originalSource = "src3"; - // We create a second term for orgId2 - this will result in a single new term but with multiple source IDs. - ImportConcept term = new ImportConcept("Added Last PrefName", new ConceptCoordinates("addedLastSourceId", "TEST_SOURCE", "orgId2", "src2")); - testTerms.getConceptsAsList().add(term); - ConceptManager tm = new ConceptManager(); - tm.insertConcepts(graphDb, ConceptsJsonSerializer.toJson(testTerms)); - // Get some more terms; those will be in another label and should be ignored here. - testTerms = ConceptManagerTest.getTestTerms(15); - testTerms.getFacet().setName("facet2"); - for (ImportConcept t : testTerms.getConceptsAsList()) { - t.coordinates.originalId = null; - t.coordinates.originalSource = null; - } - - tm.insertConcepts(graphDb, ConceptsJsonSerializer.toJson(testTerms)); - - // Assure we have two facets. - try (Transaction tx = graphDb.beginTx()){ - ResourceIterator allNodesWithLabel = graphDb.findNodes(FacetManager.FacetLabel.FACET); - int facetCount = 0; - while (allNodesWithLabel.hasNext()) { - Node facet = (Node) allNodesWithLabel.next(); - System.out.println("Got facet node: " + NodeUtilities.getNodePropertiesAsString(facet)); - facetCount++; - } - assertEquals(2, facetCount); - } - - Method method = Export.class.getDeclaredMethod("createIdMapping", GraphDatabaseService.class, String.class, - JSONArray.class); - method.setAccessible(true); - Export export = new Export(); - JSONArray labelsArray = new JSONArray(Lists.newArrayList("TESTLABEL")); - ByteArrayOutputStream baos; - byte[] byteArray; - ByteArrayInputStream bais; - GZIPInputStream gzis; - String fileContent; - - // create mapping file contents for sourceIDs - baos = (ByteArrayOutputStream) method.invoke(export, graphDb, "sourceIds", labelsArray); - byteArray = baos.toByteArray(); - bais = new ByteArrayInputStream(byteArray); - gzis = new GZIPInputStream(bais); - fileContent = IOUtils.toString(gzis, "UTF-8"); - - // We have inserted 15 terms - long numTerms = tm.getNumConcepts(graphDb); - assertEquals(15, numTerms); - int countMatches = StringUtils.countMatches(fileContent, "\n"); - // All terms have a source ID, in the test case one term has two source IDs, thus we should have 11 mapping - // lines. - assertEquals(11, countMatches); - - // NEXT TEST - // create mapping file contents for original Ids - baos = (ByteArrayOutputStream) method.invoke(export, graphDb, "originalId", labelsArray); - byteArray = baos.toByteArray(); - bais = new ByteArrayInputStream(byteArray); - gzis = new GZIPInputStream(bais); - fileContent = IOUtils.toString(gzis, "UTF-8"); - - // We have inserted 15 terms - numTerms = tm.getNumConcepts(graphDb); - assertEquals(15, numTerms); - countMatches = StringUtils.countMatches(fileContent, "\n"); - // only three terms have an original ID. No term can have more than one original ID. - assertEquals(3, countMatches); - } - - @Test - public void createIdMappingOneFacetOriginalId() throws Exception { - ImportConcepts testTerms = ConceptManagerTest.getTestTerms(10); - for (ImportConcept term : testTerms.getConceptsAsList()) { - term.generalLabels = Lists.newArrayList("TESTLABEL"); - term.coordinates.originalId = null; - term.coordinates.originalSource = null; - } - testTerms.getConceptsAsList().get(0).coordinates.originalId = "orgId1"; - testTerms.getConceptsAsList().get(0).coordinates.originalSource = "src1"; - testTerms.getConceptsAsList().get(1).coordinates.originalId = "orgId2"; - testTerms.getConceptsAsList().get(1).coordinates.originalSource = "src2"; - testTerms.getConceptsAsList().get(2).coordinates.originalId = "orgId3"; - testTerms.getConceptsAsList().get(2).coordinates.originalSource = "src3"; - // We create a second term for orgId2 - this will result in a single new term but with multiple source IDs. - ImportConcept term = new ImportConcept("Added Last PrefName", new ConceptCoordinates("addedLastSourceId", "TEST_SOURCE", "orgId2", "src2")); - term.coordinates.originalId = "orgId2"; - term.coordinates.originalSource = "src2"; - testTerms.getConceptsAsList().add(term); - ConceptManager tm = new ConceptManager(); - tm.insertConcepts(graphDb, ConceptsJsonSerializer.toJson(testTerms)); - - Method method = Export.class.getDeclaredMethod("createIdMapping", GraphDatabaseService.class, String.class, - JSONArray.class); - method.setAccessible(true); - Export export = new Export(); - JSONArray labelsArray = new JSONArray(Lists.newArrayList("TESTLABEL")); - ByteArrayOutputStream baos; - byte[] byteArray; - ByteArrayInputStream bais; - GZIPInputStream gzis; - String fileContent; - - // create mapping file contents for original Ids - baos = (ByteArrayOutputStream) method.invoke(export, graphDb, "originalId", labelsArray); - byteArray = baos.toByteArray(); - bais = new ByteArrayInputStream(byteArray); - gzis = new GZIPInputStream(bais); - fileContent = IOUtils.toString(gzis, "UTF-8"); - - // We have inserted 10 terms - long numTerms = tm.getNumConcepts(graphDb); - assertEquals(10, numTerms); - int countMatches = StringUtils.countMatches(fileContent, "\n"); - // only three terms have an original ID. No term can have more than one original ID. - assertEquals(3, countMatches); - } + + private static GraphDatabaseService graphDb; + + @BeforeClass + public static void initialize() { + graphDb = TestUtilities.getGraphDB(); + } + + @AfterClass + public static void shutdown() { + graphDb.shutdown(); + } + + @Before + public void cleanForTest() throws IOException { + TestUtilities.deleteEverythingInDB(graphDb); + } + + @Test + public void createIdMappingOneFacetSourceIds() throws Exception { + ImportConcepts testTerms = ConceptManagerTest.getTestTerms(10); + testTerms.getFacet().setName("facet1"); + for (ImportConcept term : testTerms.getConcepts()) { + term.generalLabels = Lists.newArrayList("TESTLABEL"); + // clear the original ID and source of the test terms for this test + term.coordinates.originalId = null; + term.coordinates.originalSource = null; + } + testTerms.getConcepts().get(0).coordinates.originalId = "orgId1"; + testTerms.getConcepts().get(0).coordinates.originalSource = "src1"; + testTerms.getConcepts().get(1).coordinates.originalId = "orgId2"; + testTerms.getConcepts().get(1).coordinates.originalSource = "src2"; + testTerms.getConcepts().get(2).coordinates.originalId = "orgId3"; + testTerms.getConcepts().get(2).coordinates.originalSource = "src3"; + // We create a second term for orgId2 - this will result in a single new term but with multiple source IDs. + ImportConcept term = new ImportConcept("Added Last PrefName", new ConceptCoordinates("addedLastSourceId", "TEST_SOURCE", "orgId2", "src2")); + testTerms.getConcepts().add(term); + ConceptManager tm = new ConceptManager(); + tm.insertConcepts(graphDb, ConceptsJsonSerializer.toJson(testTerms)); + // Get some more terms; those will be in another label and should be ignored here. + testTerms = ConceptManagerTest.getTestTerms(15); + testTerms.getFacet().setName("facet2"); + for (ImportConcept t : testTerms.getConcepts()) { + t.coordinates.originalId = null; + t.coordinates.originalSource = null; + } + + tm.insertConcepts(graphDb, ConceptsJsonSerializer.toJson(testTerms)); + + // Assure we have two facets. + try (Transaction tx = graphDb.beginTx()) { + ResourceIterator allNodesWithLabel = graphDb.findNodes(FacetManager.FacetLabel.FACET); + int facetCount = 0; + while (allNodesWithLabel.hasNext()) { + Node facet = (Node) allNodesWithLabel.next(); + System.out.println("Got facet node: " + NodeUtilities.getNodePropertiesAsString(facet)); + facetCount++; + } + assertEquals(2, facetCount); + } + + Method method = Export.class.getDeclaredMethod("createIdMapping", GraphDatabaseService.class, String.class, + String[].class); + method.setAccessible(true); + Export export = new Export(); + String[] labelsArray = new String[]{"TESTLABEL"}; + ByteArrayOutputStream baos; + byte[] byteArray; + ByteArrayInputStream bais; + GZIPInputStream gzis; + String fileContent; + + // create mapping file contents for sourceIDs + baos = (ByteArrayOutputStream) method.invoke(export, graphDb, "sourceIds", labelsArray); + byteArray = baos.toByteArray(); + bais = new ByteArrayInputStream(byteArray); + gzis = new GZIPInputStream(bais); + fileContent = IOUtils.toString(gzis, "UTF-8"); + + // We have inserted 15 terms + long numTerms = tm.getNumConcepts(graphDb); + assertEquals(15, numTerms); + int countMatches = StringUtils.countMatches(fileContent, "\n"); + // All terms have a source ID, in the test case one term has two source IDs, thus we should have 11 mapping + // lines. + assertEquals(11, countMatches); + + // NEXT TEST + // create mapping file contents for original Ids + baos = (ByteArrayOutputStream) method.invoke(export, graphDb, "originalId", labelsArray); + byteArray = baos.toByteArray(); + bais = new ByteArrayInputStream(byteArray); + gzis = new GZIPInputStream(bais); + fileContent = IOUtils.toString(gzis, "UTF-8"); + + // We have inserted 15 terms + numTerms = tm.getNumConcepts(graphDb); + assertEquals(15, numTerms); + countMatches = StringUtils.countMatches(fileContent, "\n"); + // only three terms have an original ID. No term can have more than one original ID. + assertEquals(3, countMatches); + } + + @Test + public void createIdMappingOneFacetOriginalId() throws Exception { + ImportConcepts testTerms = ConceptManagerTest.getTestTerms(10); + for (ImportConcept term : testTerms.getConcepts()) { + term.generalLabels = Lists.newArrayList("TESTLABEL"); + term.coordinates.originalId = null; + term.coordinates.originalSource = null; + } + testTerms.getConcepts().get(0).coordinates.originalId = "orgId1"; + testTerms.getConcepts().get(0).coordinates.originalSource = "src1"; + testTerms.getConcepts().get(1).coordinates.originalId = "orgId2"; + testTerms.getConcepts().get(1).coordinates.originalSource = "src2"; + testTerms.getConcepts().get(2).coordinates.originalId = "orgId3"; + testTerms.getConcepts().get(2).coordinates.originalSource = "src3"; + // We create a second term for orgId2 - this will result in a single new term but with multiple source IDs. + ImportConcept term = new ImportConcept("Added Last PrefName", new ConceptCoordinates("addedLastSourceId", "TEST_SOURCE", "orgId2", "src2")); + term.coordinates.originalId = "orgId2"; + term.coordinates.originalSource = "src2"; + testTerms.getConcepts().add(term); + ConceptManager tm = new ConceptManager(); + tm.insertConcepts(graphDb, ConceptsJsonSerializer.toJson(testTerms)); + + Method method = Export.class.getDeclaredMethod("createIdMapping", GraphDatabaseService.class, String.class, + String[].class); + method.setAccessible(true); + Export export = new Export(); + String[] labelsArray = new String[]{"TESTLABEL"}; + ByteArrayOutputStream baos; + byte[] byteArray; + ByteArrayInputStream bais; + GZIPInputStream gzis; + String fileContent; + + // create mapping file contents for original Ids + baos = (ByteArrayOutputStream) method.invoke(export, graphDb, "originalId", labelsArray); + byteArray = baos.toByteArray(); + bais = new ByteArrayInputStream(byteArray); + gzis = new GZIPInputStream(bais); + fileContent = IOUtils.toString(gzis, "UTF-8"); + + // We have inserted 10 terms + long numTerms = tm.getNumConcepts(graphDb); + assertEquals(10, numTerms); + int countMatches = StringUtils.countMatches(fileContent, "\n"); + // only three terms have an original ID. No term can have more than one original ID. + assertEquals(3, countMatches); + } } diff --git a/julielab-neo4j-plugins-concepts/src/test/java/de/julielab/neo4j/plugins/FacetManagerTest.java b/julielab-neo4j-plugins-concepts/src/test/java/de/julielab/neo4j/plugins/FacetManagerTest.java index a94392a..9e92f97 100644 --- a/julielab-neo4j-plugins-concepts/src/test/java/de/julielab/neo4j/plugins/FacetManagerTest.java +++ b/julielab-neo4j-plugins-concepts/src/test/java/de/julielab/neo4j/plugins/FacetManagerTest.java @@ -15,15 +15,12 @@ import org.neo4j.server.rest.repr.ListRepresentation; import org.neo4j.server.rest.repr.RecursiveMappingRepresentation; import org.neo4j.server.rest.repr.Representation; -import org.neo4j.shell.util.json.JSONException; -import org.neo4j.shell.util.json.JSONObject; import java.io.IOException; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.*; -import static de.julielab.neo4j.plugins.datarepresentation.constants.FacetConstants.*; +import static de.julielab.neo4j.plugins.datarepresentation.constants.FacetConstants.SRC_TYPE_HIERARCHICAL; import static de.julielab.neo4j.plugins.datarepresentation.constants.NodeConstants.PROP_ID; import static de.julielab.neo4j.plugins.datarepresentation.constants.NodeConstants.PROP_NAME; import static org.junit.Assert.*; @@ -44,35 +41,23 @@ public void cleanForTest() throws IOException { } @Test - public void testCreateFacetGroup() throws SecurityException, NoSuchMethodException, - IllegalArgumentException, IllegalAccessException, InvocationTargetException, - JSONException { - Gson gson = new Gson(); + public void testCreateFacetGroup() throws Exception { + ImportFacetGroup facetGroupMap1 = new ImportFacetGroup("Test Facet Group"); + facetGroupMap1.position = 1; + facetGroupMap1.labels = Lists.newArrayList("showForBTerms"); - Map facetGroupMap1 = new HashMap(); - facetGroupMap1.put(FacetGroupConstants.PROP_NAME, "Test Facet Group"); - facetGroupMap1.put(FacetGroupConstants.PROP_POSITION, 1); - facetGroupMap1.put(FacetGroupConstants.PROP_LABELS, - Lists.newArrayList("showForBTerms")); - String facetGroupJsonString1 = gson.toJson(facetGroupMap1); - JSONObject jsonFacetGroup1 = new JSONObject(facetGroupJsonString1); - - Map facetGroupMap2 = new HashMap(); - facetGroupMap2.put(FacetGroupConstants.PROP_NAME, "Test Facet Group 2"); - facetGroupMap2.put(FacetGroupConstants.PROP_POSITION, 2); - facetGroupMap2.put(FacetGroupConstants.PROP_LABELS, - Lists.newArrayList("showForSearch")); - String facetGroupJsonString2 = gson.toJson(facetGroupMap2); - JSONObject jsonFacetGroup2 = new JSONObject(facetGroupJsonString2); + ImportFacetGroup facetGroupMap2 = new ImportFacetGroup("Test Facet Group 2"); + facetGroupMap2.position = 2; + facetGroupMap2.labels = Lists.newArrayList("showForSearch"); FacetManager fm = new FacetManager(); Method createFacetGroupMethod = FacetManager.class.getDeclaredMethod("createFacetGroup", - GraphDatabaseService.class, Node.class, JSONObject.class); + GraphDatabaseService.class, Node.class, ImportFacetGroup.class); createFacetGroupMethod.setAccessible(true); try (Transaction tx = graphDb.beginTx()) { Node facetGroupsNode = FacetManager.getFacetGroupsNode(graphDb); Node facetGroupNode = (Node) createFacetGroupMethod.invoke(fm, graphDb, - facetGroupsNode, jsonFacetGroup1); + facetGroupsNode, facetGroupMap1); assertEquals("fgid0", facetGroupNode.getProperty(FacetGroupConstants.PROP_ID)); assertEquals("Test Facet Group", facetGroupNode.getProperty(FacetGroupConstants.PROP_NAME)); @@ -81,7 +66,7 @@ public void testCreateFacetGroup() throws SecurityException, NoSuchMethodExcepti assertFalse(facetGroupNode.hasLabel(Label.label("showForSearch"))); Node facetGroupNode2 = (Node) createFacetGroupMethod.invoke(fm, graphDb, - facetGroupsNode, jsonFacetGroup2); + facetGroupsNode, facetGroupMap2); assertEquals("fgid1", facetGroupNode2.getProperty(ConceptConstants.PROP_ID)); assertEquals("Test Facet Group 2", facetGroupNode2.getProperty(ConceptConstants.PROP_NAME)); assertEquals(2, facetGroupNode2.getProperty(FacetGroupConstants.PROP_POSITION)); @@ -120,57 +105,24 @@ public void testGetFacetGroupsNode() { } @Test - public void testCreateMinimalFacet() throws JSONException { - Map facetGroupMap = new HashMap(); - facetGroupMap.put(FacetGroupConstants.PROP_NAME, "facetGroup1"); - facetGroupMap.put(FacetGroupConstants.PROP_POSITION, 1); - facetGroupMap.put(FacetGroupConstants.PROP_LABELS, - Lists.newArrayList("showForSearch")); - - Map facetMap = new HashMap(); - facetMap.put(PROP_NAME, "testfacet1"); - facetMap.put("cssId", "cssid1"); - facetMap.put(PROP_SOURCE_TYPE, SRC_TYPE_HIERARCHICAL); - facetMap.put("searchFieldNames", new String[] { "sf1", "sf2" }); - facetMap.put("position", 1); - facetMap.put(FACET_GROUP, facetGroupMap); + public void testCreateMinimalFacet(){ + ImportFacetGroup facetGroupMap = new ImportFacetGroup("facetGroup1"); + facetGroupMap.position = 1; + facetGroupMap.labels = Lists.newArrayList("showForSearch"); - Gson gson = new Gson(); - String jsonFacetString = gson.toJson(facetMap); - JSONObject jsonFacet = new JSONObject(jsonFacetString); + ImportFacet facetMap = new ImportFacet(facetGroupMap, null, "testfacet1", null, SRC_TYPE_HIERARCHICAL); - Node facet = FacetManager.createFacet(graphDb, jsonFacet); + Node facet = FacetManager.createFacet(graphDb, facetMap); assertNotNull(facet); } @Test - public void testCreateFacetWithSourceName() throws JSONException { - ImportFacet facetMap = getImportFacet(); - - Gson gson = new Gson(); - String jsonFacetString = gson.toJson(facetMap); - JSONObject jsonFacet = new JSONObject(jsonFacetString); - jsonFacet.put("sourceName", "facetTermsAuthors"); - - Node facet = FacetManager.createFacet(graphDb, jsonFacet); - try (Transaction tx = graphDb.beginTx()) { - assertNotNull(facet); - assertEquals("Facet source name", "facetTermsAuthors", - facet.getProperty("sourceName")); - tx.success(); - } - } - - @Test - public void testCreateFacet() throws JSONException { + public void testCreateFacet() { ImportFacet facetMap = getTestFacetMap(1); facetMap.setLabels(Lists.newArrayList("uniqueLabel1", "uniqueLabel2")); - Gson gson = new Gson(); - String jsonFacetString = gson.toJson(facetMap); - JSONObject jsonFacet = new JSONObject(jsonFacetString); // Check whether the facet itself has been created correctly. - Node facet = FacetManager.createFacet(graphDb, jsonFacet); + Node facet = FacetManager.createFacet(graphDb, facetMap); try (Transaction tx = graphDb.beginTx()) { assertEquals("testfacet1", facet.getProperty(PROP_NAME)); assertTrue(facet.hasLabel(Label.label("uniqueLabel1"))); @@ -194,9 +146,7 @@ public void testCreateFacet() throws JSONException { // Let's see what happens when we create a second facet. There should be // two facets connected to a single facetGroups node. facetMap = getTestFacetMap(2); - jsonFacetString = gson.toJson(facetMap); - jsonFacet = new JSONObject(jsonFacetString); - FacetManager.createFacet(graphDb, jsonFacet); + FacetManager.createFacet(graphDb, facetMap); try (Transaction tx = graphDb.beginTx()) { Node facetGroups = FacetManager.getFacetGroupsNode(graphDb); Node facetGroup1 = facetGroups.getSingleRelationship( @@ -222,7 +172,7 @@ public void testCreateFacet() throws JSONException { } @Test - public void testInsertFacets() throws JSONException, SecurityException, NoSuchFieldException, + public void testInsertFacets() throws Exception, IllegalArgumentException, IllegalAccessException { List jsonFacets = new ArrayList<>(); ImportFacet facetMap = getTestFacetMap(1); diff --git a/julielab-neo4j-plugins-concepts/src/test/java/de/julielab/neo4j/plugins/JacksonTest.java b/julielab-neo4j-plugins-concepts/src/test/java/de/julielab/neo4j/plugins/JacksonTest.java new file mode 100644 index 0000000..df20326 --- /dev/null +++ b/julielab-neo4j-plugins-concepts/src/test/java/de/julielab/neo4j/plugins/JacksonTest.java @@ -0,0 +1,17 @@ +package de.julielab.neo4j.plugins; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import de.julielab.neo4j.plugins.datarepresentation.ImportConcepts; + +public class JacksonTest { + public static void main(String args[]) throws JsonProcessingException { + ImportConcepts testTerms = new ImportConcepts(null); +// testTerms = getTestTerms(1); +// testTerms.getConcepts().get(0).coordinates.originalId = "orgId"; +// testTerms.getConcepts().get(0).coordinates.originalSource = "src1"; +// testTerms.getConcepts().get(0).coordinates.source = "src1"; + final ObjectMapper om = new ObjectMapper(); + System.out.println(om.writeValueAsString(testTerms)); + } +} diff --git a/julielab-neo4j-plugins-concepts/src/test/java/de/julielab/neo4j/plugins/TraversalTest.java b/julielab-neo4j-plugins-concepts/src/test/java/de/julielab/neo4j/plugins/TraversalTest.java index 11cd37b..7b0be4c 100644 --- a/julielab-neo4j-plugins-concepts/src/test/java/de/julielab/neo4j/plugins/TraversalTest.java +++ b/julielab-neo4j-plugins-concepts/src/test/java/de/julielab/neo4j/plugins/TraversalTest.java @@ -1,14 +1,13 @@ package de.julielab.neo4j.plugins; -import static org.junit.Assert.assertTrue; - -import java.io.IOException; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - +import de.julielab.neo4j.plugins.ConceptManager.ConceptLabel; +import de.julielab.neo4j.plugins.auxiliaries.semedico.PredefinedTraversals; +import de.julielab.neo4j.plugins.datarepresentation.ImportConcepts; +import de.julielab.neo4j.plugins.datarepresentation.constants.ConceptConstants; +import de.julielab.neo4j.plugins.datarepresentation.constants.MorphoConstants; +import de.julielab.neo4j.plugins.datarepresentation.constants.NodeIDPrefixConstants; +import de.julielab.neo4j.plugins.datarepresentation.util.ConceptsJsonSerializer; +import de.julielab.neo4j.plugins.test.TestUtilities; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; @@ -20,14 +19,10 @@ import org.neo4j.graphdb.traversal.TraversalDescription; import org.neo4j.graphdb.traversal.Traverser; -import de.julielab.neo4j.plugins.ConceptManager.ConceptLabel; -import de.julielab.neo4j.plugins.auxiliaries.semedico.PredefinedTraversals; -import de.julielab.neo4j.plugins.datarepresentation.ImportConcepts; -import de.julielab.neo4j.plugins.datarepresentation.constants.ConceptConstants; -import de.julielab.neo4j.plugins.datarepresentation.constants.MorphoConstants; -import de.julielab.neo4j.plugins.datarepresentation.constants.NodeIDPrefixConstants; -import de.julielab.neo4j.plugins.datarepresentation.util.ConceptsJsonSerializer; -import de.julielab.neo4j.plugins.test.TestUtilities; +import java.io.IOException; +import java.util.*; + +import static org.junit.Assert.assertTrue; public class TraversalTest { diff --git a/julielab-neo4j-plugins-concepts/src/test/java/de/julielab/neo4j/plugins/auxiliaries/semedico/ConceptAggregateBuilderTest.java b/julielab-neo4j-plugins-concepts/src/test/java/de/julielab/neo4j/plugins/auxiliaries/semedico/ConceptAggregateBuilderTest.java index 49c8720..792cdfa 100644 --- a/julielab-neo4j-plugins-concepts/src/test/java/de/julielab/neo4j/plugins/auxiliaries/semedico/ConceptAggregateBuilderTest.java +++ b/julielab-neo4j-plugins-concepts/src/test/java/de/julielab/neo4j/plugins/auxiliaries/semedico/ConceptAggregateBuilderTest.java @@ -1,51 +1,32 @@ package de.julielab.neo4j.plugins.auxiliaries.semedico; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.function.BiFunction; -import java.util.function.Function; - -import org.apache.commons.lang.StringUtils; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.neo4j.graphdb.GraphDatabaseService; -import org.neo4j.graphdb.Label; -import org.neo4j.graphdb.Node; -import org.neo4j.graphdb.Relationship; -import org.neo4j.graphdb.ResourceIterable; -import org.neo4j.graphdb.Transaction; -import org.neo4j.server.rest.repr.RecursiveMappingRepresentation; - import com.google.common.collect.Lists; import com.google.common.collect.Sets; - import de.julielab.neo4j.plugins.ConceptManager; import de.julielab.neo4j.plugins.ConceptManager.ConceptLabel; import de.julielab.neo4j.plugins.FacetManagerTest; import de.julielab.neo4j.plugins.auxiliaries.PropertyUtilities; import de.julielab.neo4j.plugins.auxiliaries.semedico.ConceptAggregateBuilder.CopyAggregatePropertiesStatistics; -import de.julielab.neo4j.plugins.datarepresentation.ConceptCoordinates; -import de.julielab.neo4j.plugins.datarepresentation.CoordinateType; -import de.julielab.neo4j.plugins.datarepresentation.ImportConcept; -import de.julielab.neo4j.plugins.datarepresentation.ImportFacet; -import de.julielab.neo4j.plugins.datarepresentation.ImportMapping; +import de.julielab.neo4j.plugins.datarepresentation.*; import de.julielab.neo4j.plugins.datarepresentation.constants.AggregateConstants; import de.julielab.neo4j.plugins.datarepresentation.constants.ConceptConstants; import de.julielab.neo4j.plugins.datarepresentation.constants.NodeIDPrefixConstants; import de.julielab.neo4j.plugins.datarepresentation.util.ConceptsJsonSerializer; import de.julielab.neo4j.plugins.test.TestUtilities; +import org.apache.commons.lang.StringUtils; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.neo4j.graphdb.*; +import org.neo4j.server.rest.repr.RecursiveMappingRepresentation; + +import java.io.IOException; +import java.util.*; +import java.util.function.BiFunction; +import java.util.function.Function; + +import static org.junit.Assert.*; public class ConceptAggregateBuilderTest { private static GraphDatabaseService graphDb; diff --git a/julielab-neo4j-plugins-concepts/src/test/java/de/julielab/neo4j/plugins/auxiliaries/semedico/SequenceManagerTest.java b/julielab-neo4j-plugins-concepts/src/test/java/de/julielab/neo4j/plugins/auxiliaries/semedico/SequenceManagerTest.java index da5fa7a..56bf4f3 100644 --- a/julielab-neo4j-plugins-concepts/src/test/java/de/julielab/neo4j/plugins/auxiliaries/semedico/SequenceManagerTest.java +++ b/julielab-neo4j-plugins-concepts/src/test/java/de/julielab/neo4j/plugins/auxiliaries/semedico/SequenceManagerTest.java @@ -1,24 +1,19 @@ package de.julielab.neo4j.plugins.auxiliaries.semedico; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.util.HashSet; -import java.util.Set; - +import de.julielab.neo4j.plugins.constants.semedico.SequenceConstants; +import de.julielab.neo4j.plugins.datarepresentation.constants.NodeConstants; +import de.julielab.neo4j.plugins.test.TestUtilities; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; -import org.neo4j.graphdb.Direction; -import org.neo4j.graphdb.GraphDatabaseService; -import org.neo4j.graphdb.Node; -import org.neo4j.graphdb.Relationship; -import org.neo4j.graphdb.Transaction; +import org.neo4j.graphdb.*; -import de.julielab.neo4j.plugins.constants.semedico.SequenceConstants; -import de.julielab.neo4j.plugins.datarepresentation.constants.NodeConstants; -import de.julielab.neo4j.plugins.test.TestUtilities; +import java.util.HashSet; +import java.util.Set; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; public class SequenceManagerTest { private static GraphDatabaseService graphDb; diff --git a/julielab-neo4j-plugins-utilities/pom.xml b/julielab-neo4j-plugins-utilities/pom.xml index 24fc472..f10596d 100644 --- a/julielab-neo4j-plugins-utilities/pom.xml +++ b/julielab-neo4j-plugins-utilities/pom.xml @@ -3,7 +3,7 @@ de.julielab julielab-neo4j-server-plugins - 2.1.0-SNAPSHOT + 2.1.0 .. julielab-neo4j-plugins-utilities @@ -16,5 +16,9 @@ 4.12 provided + + com.fasterxml.jackson.core + jackson-databind + \ No newline at end of file diff --git a/julielab-neo4j-plugins-utilities/src/main/java/de/julielab/neo4j/plugins/auxiliaries/JSON.java b/julielab-neo4j-plugins-utilities/src/main/java/de/julielab/neo4j/plugins/auxiliaries/JSON.java deleted file mode 100644 index ae81d33..0000000 --- a/julielab-neo4j-plugins-utilities/src/main/java/de/julielab/neo4j/plugins/auxiliaries/JSON.java +++ /dev/null @@ -1,117 +0,0 @@ -package de.julielab.neo4j.plugins.auxiliaries; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.neo4j.shell.util.json.JSONArray; -import org.neo4j.shell.util.json.JSONException; -import org.neo4j.shell.util.json.JSONObject; - -public class JSON { - /** - *

- * Copies the contents of {@link JSONArray} into a newly allocated Java - * String array which is then returned. - *

- *

- * If exclusion Strings are specified, those elements will not be copied - * into the new Java array. - *

- * - * @param jsonArray - * A JSONArray of primitives to be converted into a Java array. - * @param exclusions - * Elements in jsonArray to be excluded from the new - * Java array. - * @return A Java array with the contents of jsonArray, if - * jsonArray has elements, null otherwise. - * @throws JSONException - */ - @SafeVarargs - public static T[] json2JavaArray(JSONArray jsonArray, T... exclusions) throws JSONException { - if (null == jsonArray || jsonArray.length() == 0) - return null; - Set exclusionSet = null; - if (exclusions.length > 0) { - exclusionSet = new HashSet<>(); - for (T e : exclusions) - exclusionSet.add(e); - } - - // We have to know the class of the array elements. Just start with the - // first element. - Class listElementClass = jsonArray.get(0).getClass(); - List list = new ArrayList<>(jsonArray.length()); - for (int i = 0; i < jsonArray.length(); i++) { - @SuppressWarnings("unchecked") - T object = (T) jsonArray.get(i); - if (JSONObject.NULL != object && (null == exclusionSet || !exclusionSet.contains(object))) { - list.add(object); - } - - // If the current element is not assignment compatible to its former - // elements, two things can have happened: - // 1) The current element is a super type of the former elements so - // we just switch the class to the current - // class. 2) The current and its former elements are of sibling - // classes (can happen in JSONArrays). Then, we - // have to use an Object array, thus Object is our class. - if (!listElementClass.isAssignableFrom(object.getClass())) { - if (!object.getClass().isAssignableFrom(listElementClass)) - listElementClass = Object.class; - else - listElementClass = object.getClass(); - } - - } - return JulieNeo4jUtilities.convertListToArray(list, listElementClass); - } - - public static String getString(JSONObject o, String key) throws JSONException { - if (o.isNull(key)) - return null; - return o.getString(key); - } - - public static JSONObject getJSONObject(JSONObject o, String key) throws JSONException { - if (o.isNull(key)) - return null; - return o.getJSONObject(key); - } - - public static JSONArray getJSONArray(JSONObject o, String key) throws JSONException { - if (o.isNull(key)) - return null; - return o.getJSONArray(key); - } - - public static boolean getBoolean(JSONObject o, String key, boolean defaultValue) throws JSONException { - if (o.isNull(key)) - return defaultValue; - return o.getBoolean(key); - } - - public static boolean getBoolean(JSONObject o, String key) throws JSONException { - return getBoolean(o, key, false); - } - - public static Integer getInt(JSONObject o, String key) throws JSONException { - if (o.isNull(key)) - return null; - return o.getInt(key); - } - - @SuppressWarnings("unchecked") - public static Set jsonArray2JavaSet(JSONArray jsonArray) throws JSONException { - if (jsonArray == null) - return null; - Set set = new HashSet<>(); - for (int i = 0; i < jsonArray.length(); ++i) { - set.add((T) jsonArray.get(i)); - } - return set; - } - -} diff --git a/julielab-neo4j-plugins-utilities/src/main/java/de/julielab/neo4j/plugins/auxiliaries/JulieNeo4jUtilities.java b/julielab-neo4j-plugins-utilities/src/main/java/de/julielab/neo4j/plugins/auxiliaries/JulieNeo4jUtilities.java index 4a55856..95334da 100644 --- a/julielab-neo4j-plugins-utilities/src/main/java/de/julielab/neo4j/plugins/auxiliaries/JulieNeo4jUtilities.java +++ b/julielab-neo4j-plugins-utilities/src/main/java/de/julielab/neo4j/plugins/auxiliaries/JulieNeo4jUtilities.java @@ -1,9 +1,9 @@ package de.julielab.neo4j.plugins.auxiliaries; -import java.util.List; - import org.apache.commons.lang.ArrayUtils; +import java.util.List; + public class JulieNeo4jUtilities { /** * Converts elements into an array of the runtime type cls diff --git a/julielab-neo4j-plugins-utilities/src/main/java/de/julielab/neo4j/plugins/auxiliaries/NodeRepresentation.java b/julielab-neo4j-plugins-utilities/src/main/java/de/julielab/neo4j/plugins/auxiliaries/NodeRepresentation.java index fa87211..c8af50d 100644 --- a/julielab-neo4j-plugins-utilities/src/main/java/de/julielab/neo4j/plugins/auxiliaries/NodeRepresentation.java +++ b/julielab-neo4j-plugins-utilities/src/main/java/de/julielab/neo4j/plugins/auxiliaries/NodeRepresentation.java @@ -1,16 +1,15 @@ package de.julielab.neo4j.plugins.auxiliaries; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - +import de.julielab.neo4j.plugins.constants.NodeConstants; import org.neo4j.graphdb.Label; import org.neo4j.graphdb.Node; import org.neo4j.server.rest.repr.RecursiveMappingRepresentation; import org.neo4j.server.rest.repr.Representation; -import de.julielab.neo4j.plugins.constants.NodeConstants; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; public class NodeRepresentation extends RecursiveMappingRepresentation { public NodeRepresentation(Node node) { diff --git a/julielab-neo4j-plugins-utilities/src/main/java/de/julielab/neo4j/plugins/auxiliaries/NodeUtilities.java b/julielab-neo4j-plugins-utilities/src/main/java/de/julielab/neo4j/plugins/auxiliaries/NodeUtilities.java index 6324ac9..5457286 100644 --- a/julielab-neo4j-plugins-utilities/src/main/java/de/julielab/neo4j/plugins/auxiliaries/NodeUtilities.java +++ b/julielab-neo4j-plugins-utilities/src/main/java/de/julielab/neo4j/plugins/auxiliaries/NodeUtilities.java @@ -1,18 +1,12 @@ package de.julielab.neo4j.plugins.auxiliaries; +import org.apache.commons.lang.StringUtils; +import org.neo4j.graphdb.*; + import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import org.apache.commons.lang.StringUtils; -import org.neo4j.graphdb.GraphDatabaseService; -import org.neo4j.graphdb.Label; -import org.neo4j.graphdb.Node; -import org.neo4j.graphdb.Relationship; -import org.neo4j.graphdb.RelationshipType; -import org.neo4j.graphdb.ResourceIterable; -import org.neo4j.graphdb.ResourceIterator; - public class NodeUtilities extends PropertyUtilities { /** diff --git a/julielab-neo4j-plugins-utilities/src/main/java/de/julielab/neo4j/plugins/auxiliaries/PropertyUtilities.java b/julielab-neo4j-plugins-utilities/src/main/java/de/julielab/neo4j/plugins/auxiliaries/PropertyUtilities.java index eef4461..5b9e922 100644 --- a/julielab-neo4j-plugins-utilities/src/main/java/de/julielab/neo4j/plugins/auxiliaries/PropertyUtilities.java +++ b/julielab-neo4j-plugins-utilities/src/main/java/de/julielab/neo4j/plugins/auxiliaries/PropertyUtilities.java @@ -1,376 +1,408 @@ package de.julielab.neo4j.plugins.auxiliaries; -import java.lang.reflect.Array; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; - +import com.fasterxml.jackson.annotation.JsonProperty; import org.apache.commons.lang.StringUtils; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.PropertyContainer; -import org.neo4j.shell.util.json.JSONArray; -import org.neo4j.shell.util.json.JSONException; -import org.neo4j.shell.util.json.JSONObject; + +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.*; +import java.util.function.Supplier; public class PropertyUtilities { - public static void copyJSONObjectToPropertyContainer(JSONObject object, PropertyContainer node) - throws JSONException { - copyJSONObjectToPropertyContainer(object, node, (Set) null); - } - - public static void copyJSONObjectToPropertyContainer(JSONObject object, PropertyContainer node, - String... exclusions) throws JSONException { - Set exclusionSet = new HashSet<>(); - for (int i = 0; i < exclusions.length; i++) { - String exclusion = exclusions[i]; - exclusionSet.add(exclusion); - } - copyJSONObjectToPropertyContainer(object, node, exclusionSet); - } - - public static void copyJSONObjectToPropertyContainer(JSONObject object, PropertyContainer node, - Set exclusions) throws JSONException { - Iterator keys = object.keys(); - while (keys.hasNext()) { - String key = (String) keys.next(); - if (null != exclusions && exclusions.contains(key)) - continue; - Object value = object.get(key); - if (value.getClass().equals(JSONArray.class)) { - String[] json2JavaArray = JSON.json2JavaArray((JSONArray) value); - if (null != json2JavaArray && json2JavaArray.length > 0) - node.setProperty(key, json2JavaArray); - } else if (value.getClass().equals(JSONObject.class)) { - throw new IllegalArgumentException("The value for key \"" + key - + "\" is a JSONObject. This is not allowed for node properties and thus cannot be set. The JSONObject to copy was: " - + object); - } else { - node.setProperty(key, value); - } - } - } - - public static void mergeJSONObjectIntoPropertyContainer(JSONObject object, PropertyContainer node, - String... exclusions) throws JSONException { - Set exclusionSet = new HashSet<>(); - for (int i = 0; i < exclusions.length; i++) { - String exclusion = exclusions[i]; - exclusionSet.add(exclusion); - } - mergeJSONObjectIntoPropertyContainer(object, node, exclusionSet); - } - - public static void mergeJSONObjectIntoPropertyContainer(JSONObject object, PropertyContainer node, - Set exclusions) throws JSONException { - Iterator keys = object.keys(); - while (keys.hasNext()) { - String key = (String) keys.next(); - if (null != exclusions && exclusions.contains(key)) - continue; - Object value = object.get(key); - if (value.getClass().equals(JSONArray.class)) { - mergeArrayProperty(node, key, JSON.json2JavaArray((JSONArray) value)); - } else if (value.getClass().equals(JSONObject.class)) { - throw new IllegalArgumentException("The value for key \"" + key - + "\" is a JSONObject. This is not allowed for node properties and thus cannot be set. The JSONObject to copy was: " - + object); - } else { - setNonNullNodeProperty(node, key, value); - } - } - } - - public static void mergePropertyContainerIntoPropertyContainer(Node from, Node to, String... exclusions) { - Set exclusionSet = new HashSet<>(); - for (int i = 0; i < exclusions.length; i++) { - String exclusion = exclusions[i]; - exclusionSet.add(exclusion); - } - mergeJSONObjectIntoPropertyContainer(from, to, exclusionSet); - } - - private static void mergeJSONObjectIntoPropertyContainer(Node from, Node to, Set exclusions) { - Iterator keys = from.getPropertyKeys().iterator(); - while (keys.hasNext()) { - String key = (String) keys.next(); - if (null != exclusions && exclusions.contains(key)) - continue; - Object value = from.getProperty(key); - if (value.getClass().isArray()) { - mergeArrayProperty(to, key, (Object[]) value); - } else { - setNonNullNodeProperty(to, key, value); - } - } - } - - /** - * Gets the current property values at key for the node - * node and adds them all into a single Set together with - * the contents of array to avoid duplicates. Then, the - * Set is converted back into an array which is then set as the new - * node property. A {@link LinkedHashSet} is used to maintain the original - * order. The original values are added first. Thus, new values are appended - * to the end of the new array. - * - * @param node - * @param key - * @param array - */ - @SuppressWarnings("unchecked") - public static void mergeArrayProperty(PropertyContainer node, String key, T[] array) { - try { - if (null == array || array.length == 0) - return; - // we can't directly cast to T[] because sometimes we will get an - // Integer[] but the node stored an int[] - // which is not castable... - // Use the set to avoid duplicates. - Set set = new LinkedHashSet(); - for (T o : array) - set.add(o); - - if (node.hasProperty(key)) { - Object storedArray = node.getProperty(key); - // casting the elements one-by-one is working because int can be - // cast to Integer and the other way round via - // autoboxing - for (int i = 0; i < Array.getLength(storedArray); ++i) - set.add((T) Array.get(storedArray, i)); - } - T[] newArray = (T[]) Array.newInstance(array[0].getClass(), set.size()); - try { - set.toArray(newArray); - } catch (ArrayStoreException e) { - T next = set.iterator().next(); - throw new IllegalArgumentException("Trying to merge array properties of different types (array class: " - + newArray.getClass() + " element class: " + next.getClass() + ")"); - } - node.setProperty(key, newArray); - } catch (Exception e) { - throw new RuntimeException( - "Exception occurred while merging property \"" + key + "\" of property container \"" + node - + "\" (value before merging: \"" + (node.hasProperty(key) ? node.getProperty(key) : null) - + ")\" with data \"" + Arrays.toString(array) + "\" (object notation: \"" + array + "\").", - e); - } - } - - /** - * Adds value to the property with name key but does not - * allow duplicates or null values. - * - * @param node - * @param key - * @param value - * @return - */ - public static int addToArrayProperty(PropertyContainer node, String key, T value) { - return addToArrayProperty(node, key, value, false, false); - } - - public static int addToArrayProperty(PropertyContainer node, String key, T value, boolean allowDuplicates) { - return addToArrayProperty(node, key, value, allowDuplicates, false); - } - - @SuppressWarnings("unchecked") - public static int addToArrayProperty(PropertyContainer node, String key, T value, boolean allowDuplicates, - boolean allowNullValues) { - if (!allowNullValues && null == value) - return -1; - T[] array = null; - if (node.hasProperty(key)) { - Object arrayProperty = node.getProperty(key); - try { - array = (T[]) arrayProperty; - } catch (ClassCastException e) { - // happens when the existing array on node is of a primitive array type, e.g. byte[], since then it will be tried to cast to Byte[] which does not work - array = (T[]) JulieNeo4jUtilities.convertArray(arrayProperty); - } - } else { - T[] newArray = (T[]) Array.newInstance(value.getClass(), 1); - newArray[0] = value; - node.setProperty(key, newArray); - return 0; - } - - boolean valueFound = false; - if (!allowDuplicates) { - for (int i = 0; i < array.length; i++) { - T element = array[i]; - if (element.equals(value)) { - valueFound = true; - break; - } - } - } - if (!valueFound || allowDuplicates) { - T[] newArray = (T[]) Array.newInstance(value.getClass(), array.length + 1); - System.arraycopy(array, 0, newArray, 0, array.length); - newArray[newArray.length - 1] = value; - node.setProperty(key, newArray); - return newArray.length - 1; - } - return -1; - } - - /** - * Sets the property at property key key of node to - * value, if value is not null and the property on the node not - * already set. - * - * @param node - * @param key - * @param value - */ - public static void setNonNullNodeProperty(PropertyContainer node, String key, Object value) { - if (null == value) - return; - if (node.hasProperty(key)) - return; - node.setProperty(key, value); - } - - /** - * Sets the property at property key key of node to - * value, if value is not null and the property on the node not - * already set. If value is null, the property is set to - * defaultValue. - * - * @param node - * @param key - * @param value - */ - public static void setNonNullNodeProperty(PropertyContainer node, String key, Object value, Object defaultValue) { - if (node.hasProperty(key)) - return; - if (null != value) - node.setProperty(key, value); - else - node.setProperty(key, defaultValue); - } - - /** - * Returns the property stored at key key in the specified property - * container or null. - * - * @param node - * @param key - * @return - */ - public static Object getNonNullNodeProperty(PropertyContainer node, String key) { - if (null != node && node.hasProperty(key)) - return node.getProperty(key); - return null; - } - - public static String getNodePropertiesAsString(PropertyContainer node) { - List values = new ArrayList<>(); - for (String pk : node.getPropertyKeys()) { - Object p = node.getProperty(pk); - if (p.getClass().isArray()) - values.add(pk + ": " + Arrays.toString(JulieNeo4jUtilities.convertArray(p))); - else - values.add(pk + ": " + p); - } - return StringUtils.join(values, " ; "); - } - - public static int findFirstValueInArrayProperty(Node term, String key, String value) { - if (!term.hasProperty(key)) { - return -1; - } - Object property = term.getProperty(key); - Object[] array = JulieNeo4jUtilities.convertArray(property); - for (int i = 0; i < array.length; i++) { - if (null != array[i] && array[i].equals(value)) - return i; - else if (null == array[i] && null == value) - return i; - } - - return -1; - - } - - /** - * Checks whether the property container has the exact - * valueToCompare as value for the property identified by - * key. - * - * @param term - * @param key - * @param valueToCompare - * @return - */ - public static boolean hasSamePropertyValue(PropertyContainer term, String key, Object valueToCompare) { - if (null != valueToCompare && !term.hasProperty(key)) - return false; - Object value = term.getProperty(key); - if (!valueToCompare.equals(value)) { - return false; - } - return true; - } - - /** - * Determines whether the property container has a value for the property - * with key key and this value does not equal - * valueToCompare. I.e. if the property value is null, - * this is not seen as a contradiction - not even if term of - * valueToCompare itself is null. - * - * @param term - * @param key - * @param valueToCompare - * @return - */ - public static boolean hasContradictingPropertyValue(PropertyContainer term, String key, Object valueToCompare) { - if (null == term || null == valueToCompare || !term.hasProperty(key)) - return false; - Object value = term.getProperty(key); - if (!valueToCompare.equals(value)) { - return true; - } - return false; - } - - public static boolean mergeProperties(PropertyContainer propContainer, Object... properties) { - boolean success = true; - // Type and direction match. - // Now check whether properties fit. - if (null != properties && properties.length > 0) { - for (int i = 0; i < properties.length; i += 2) { - String key = (String) properties[i]; - Object value = properties[i + 1]; - boolean passedValueIsArray = value.getClass().isArray(); - if (propContainer.hasProperty(key)) { - Object existingValue = propContainer.getProperty(key); - boolean existingValueIsArray = existingValue.getClass().isArray(); - // The property must have the correct value - if (!existingValueIsArray && !value.equals(existingValue)) { - success = false; - } else { - // If we have two array-valued values, we - // may merge them - if (existingValueIsArray != passedValueIsArray) - throw new IllegalArgumentException( - "Trying to merge an array value with a non-array value."); - if (existingValueIsArray) { - PropertyUtilities.mergeArrayProperty(propContainer, key, (Object[]) value); - } - } - } else { - propContainer.setProperty(key, value); - } - } - } - return success; - } + public static void copyObjectToPropertyContainer(Object object, PropertyContainer node) { + copyObjectToPropertyContainer(object, node, (Set) null); + } + + public static void copyObjectToPropertyContainer(Object object, PropertyContainer node, + String... exclusions) { + Set exclusionSet = new HashSet<>(); + for (int i = 0; i < exclusions.length; i++) { + String exclusion = exclusions[i]; + exclusionSet.add(exclusion); + } + copyObjectToPropertyContainer(object, node, exclusionSet); + } + + public static void copyObjectToPropertyContainer(Object object, PropertyContainer node, + Set exclusions) { + + try { + final Field[] fields = object.getClass().getDeclaredFields(); + for (Field field : fields) { + String key = field.getName(); + // Check if the field is annotated to give it another name + final JsonProperty[] jsonProperties = field.getAnnotationsByType(JsonProperty.class); + if (jsonProperties != null && jsonProperties[0].value() != null) { + key = jsonProperties[0].value(); + } + if ((Modifier.PUBLIC & field.getModifiers()) != 0 && (exclusions == null || !exclusions.contains(key))) { + Object value = field.get(object); + if (value != null) { + if (List.class.isAssignableFrom(value.getClass())) { + value = ((List) value).toArray(); + } + node.setProperty(key, value); + } else { + node.removeProperty(key); + } + } + } + } catch (IllegalAccessException e) { + throw new IllegalArgumentException(e); + } + } + + public static void mergeObjectIntoPropertyContainer(Object object, PropertyContainer node, + String... exclusions) { + Set exclusionSet = new HashSet<>(); + for (int i = 0; i < exclusions.length; i++) { + String exclusion = exclusions[i]; + exclusionSet.add(exclusion); + } + mergeObjectIntoPropertyContainer(object, node, exclusionSet); + } + + public static void mergeObjectIntoPropertyContainer(Object object, PropertyContainer node, + Set exclusions) { + try { + final Field[] fields = object.getClass().getFields(); + for (Field field : fields) { + String key = field.getName(); + // Check if the field is annotated to give it another name + final JsonProperty[] jsonProperties = field.getAnnotationsByType(JsonProperty.class); + if (jsonProperties != null && jsonProperties[0].value() != null) { + key = jsonProperties[0].value(); + } + if ((Modifier.PUBLIC & field.getModifiers()) != 0 && (exclusions == null || !exclusions.contains(key))) { + final Object value = field.get(object); + if (value != null) { + if (value.getClass().isArray()) { + mergeArrayProperty(node, key, (Object[]) value); + } else if (List.class.isAssignableFrom(value.getClass())) { + mergeArrayProperty(node, key, ((List) value).toArray()); + } else { + setNonNullNodeProperty(node, key, value); + } + } + } + } + } catch (IllegalAccessException e) { + throw new IllegalArgumentException(e); + } + } + + public static void mergePropertyContainerIntoPropertyContainer(Node from, Node to, String... exclusions) { + Set exclusionSet = new HashSet<>(); + for (int i = 0; i < exclusions.length; i++) { + String exclusion = exclusions[i]; + exclusionSet.add(exclusion); + } + mergeJSONObjectIntoPropertyContainer(from, to, exclusionSet); + } + + private static void mergeJSONObjectIntoPropertyContainer(Node from, Node to, Set exclusions) { + Iterator keys = from.getPropertyKeys().iterator(); + while (keys.hasNext()) { + String key = keys.next(); + if (null != exclusions && exclusions.contains(key)) + continue; + Object value = from.getProperty(key); + if (value.getClass().isArray()) { + mergeArrayProperty(to, key, (Object[]) value); + } else { + setNonNullNodeProperty(to, key, value); + } + } + } + + public static void mergeArrayProperty(PropertyContainer node, String key, Supplier arraySupplier) { + try { + final T[] value = arraySupplier.get(); + mergeArrayProperty(node, key, value); + } catch (NullPointerException e) { + // nothing, this was expected + } + } + + /** + * Gets the current property values at key for the node + * node and adds them all into a single Set together with + * the contents of array to avoid duplicates. Then, the + * Set is converted back into an array which is then set as the new + * node property. A {@link LinkedHashSet} is used to maintain the original + * order. The original values are added first. Thus, new values are appended + * to the end of the new array. + * + * @param node + * @param key + * @param array + */ + @SuppressWarnings("unchecked") + public static void mergeArrayProperty(PropertyContainer node, String key, T[] array) { + try { + if (null == array || array.length == 0) + return; + + if (array[0] == null) + throw new IllegalArgumentException("An array was passed whose first element is null. This is not allowed."); + + // we can't directly cast to T[] because sometimes we will get an + // Integer[] but the node stored an int[] + // which is not castable... + // Use the set to avoid duplicates. + Set set = new LinkedHashSet(); + for (T o : array) + set.add(o); + + if (node.hasProperty(key)) { + Object storedArray = node.getProperty(key); + // casting the elements one-by-one is working because int can be + // cast to Integer and the other way round via + // autoboxing + for (int i = 0; i < Array.getLength(storedArray); ++i) + set.add((T) Array.get(storedArray, i)); + } + T[] newArray = (T[]) Array.newInstance(array[0].getClass(), set.size()); + try { + set.toArray(newArray); + } catch (ArrayStoreException e) { + T next = set.iterator().next(); + throw new IllegalArgumentException("Trying to merge array properties of different types (array class: " + + newArray.getClass() + " element class: " + next.getClass() + ")"); + } + node.setProperty(key, newArray); + } catch (Exception e) { + throw new RuntimeException( + "Exception occurred while merging property \"" + key + "\" of property container \"" + node + + "\" (value before merging: \"" + (node.hasProperty(key) ? node.getProperty(key) : null) + + ")\" with data \"" + Arrays.toString(array) + "\" (object notation: \"" + array + "\").", + e); + } + } + + /** + * Adds value to the property with name key but does not + * allow duplicates or null values. + * + * @param node + * @param key + * @param value + * @return + */ + public static int addToArrayProperty(PropertyContainer node, String key, T value) { + return addToArrayProperty(node, key, value, false, false); + } + + public static int addToArrayProperty(PropertyContainer node, String key, T value, boolean allowDuplicates) { + return addToArrayProperty(node, key, value, allowDuplicates, false); + } + + @SuppressWarnings("unchecked") + public static int addToArrayProperty(PropertyContainer node, String key, T value, boolean allowDuplicates, + boolean allowNullValues) { + if (!allowNullValues && null == value) + return -1; + T[] array = null; + if (node.hasProperty(key)) { + Object arrayProperty = node.getProperty(key); + try { + array = (T[]) arrayProperty; + } catch (ClassCastException e) { + // happens when the existing array on node is of a primitive array type, e.g. byte[], since then it will be tried to cast to Byte[] which does not work + array = (T[]) JulieNeo4jUtilities.convertArray(arrayProperty); + } + } else { + T[] newArray = (T[]) Array.newInstance(value.getClass(), 1); + newArray[0] = value; + node.setProperty(key, newArray); + return 0; + } + + boolean valueFound = false; + if (!allowDuplicates) { + for (int i = 0; i < array.length; i++) { + T element = array[i]; + if (element.equals(value)) { + valueFound = true; + break; + } + } + } + if (!valueFound || allowDuplicates) { + T[] newArray = (T[]) Array.newInstance(value.getClass(), array.length + 1); + System.arraycopy(array, 0, newArray, 0, array.length); + newArray[newArray.length - 1] = value; + node.setProperty(key, newArray); + return newArray.length - 1; + } + return -1; + } + + public static void setNonNullNodeProperty(PropertyContainer node, String key, Supplier value) { + try { + final Object nonNulValue = value.get(); + setNonNullNodeProperty(node, key, nonNulValue); + } catch (NullPointerException e) { + // nothing, was expected + } + } + + /** + * Sets the property at property key key of node to + * value, if value is not null and the property on the node not + * already set. + * + * @param node + * @param key + * @param value + */ + public static void setNonNullNodeProperty(PropertyContainer node, String key, Object value) { + if (null == value) + return; + if (node.hasProperty(key)) + return; + node.setProperty(key, value); + } + + /** + * Sets the property at property key key of node to + * value, if value is not null and the property on the node not + * already set. If value is null, the property is set to + * defaultValue. + * + * @param node + * @param key + * @param value + */ + public static void setNonNullNodeProperty(PropertyContainer node, String key, Object value, Object defaultValue) { + if (node.hasProperty(key)) + return; + if (null != value) + node.setProperty(key, value); + else + node.setProperty(key, defaultValue); + } + + /** + * Returns the property stored at key key in the specified property + * container or null. + * + * @param node + * @param key + * @return + */ + public static Object getNonNullNodeProperty(PropertyContainer node, String key) { + if (null != node && node.hasProperty(key)) + return node.getProperty(key); + return null; + } + + public static String getNodePropertiesAsString(PropertyContainer node) { + List values = new ArrayList<>(); + for (String pk : node.getPropertyKeys()) { + Object p = node.getProperty(pk); + if (p.getClass().isArray()) + values.add(pk + ": " + Arrays.toString(JulieNeo4jUtilities.convertArray(p))); + else + values.add(pk + ": " + p); + } + return StringUtils.join(values, " ; "); + } + + public static int findFirstValueInArrayProperty(Node term, String key, String value) { + if (!term.hasProperty(key)) { + return -1; + } + Object property = term.getProperty(key); + Object[] array = JulieNeo4jUtilities.convertArray(property); + for (int i = 0; i < array.length; i++) { + if (null != array[i] && array[i].equals(value)) + return i; + else if (null == array[i] && null == value) + return i; + } + + return -1; + + } + + /** + * Checks whether the property container has the exact + * valueToCompare as value for the property identified by + * key. + * + * @param term + * @param key + * @param valueToCompare + * @return + */ + public static boolean hasSamePropertyValue(PropertyContainer term, String key, Object valueToCompare) { + if (null != valueToCompare && !term.hasProperty(key)) + return false; + Object value = term.getProperty(key); + if (!valueToCompare.equals(value)) { + return false; + } + return true; + } + + /** + * Determines whether the property container has a value for the property + * with key key and this value does not equal + * valueToCompare. I.e. if the property value is null, + * this is not seen as a contradiction - not even if term of + * valueToCompare itself is null. + * + * @param term + * @param key + * @param valueToCompare + * @return + */ + public static boolean hasContradictingPropertyValue(PropertyContainer term, String key, Object valueToCompare) { + if (null == term || null == valueToCompare || !term.hasProperty(key)) + return false; + Object value = term.getProperty(key); + if (!valueToCompare.equals(value)) { + return true; + } + return false; + } + + public static boolean mergeProperties(PropertyContainer propContainer, Object... properties) { + boolean success = true; + // Type and direction match. + // Now check whether properties fit. + if (null != properties && properties.length > 0) { + for (int i = 0; i < properties.length; i += 2) { + String key = (String) properties[i]; + Object value = properties[i + 1]; + boolean passedValueIsArray = value.getClass().isArray(); + if (propContainer.hasProperty(key)) { + Object existingValue = propContainer.getProperty(key); + boolean existingValueIsArray = existingValue.getClass().isArray(); + // The property must have the correct value + if (!existingValueIsArray && !value.equals(existingValue)) { + success = false; + } else { + // If we have two array-valued values, we + // may merge them + if (existingValueIsArray != passedValueIsArray) + throw new IllegalArgumentException( + "Trying to merge an array value with a non-array value."); + if (existingValueIsArray) { + PropertyUtilities.mergeArrayProperty(propContainer, key, (Object[]) value); + } + } + } else { + propContainer.setProperty(key, value); + } + } + } + return success; + } } diff --git a/julielab-neo4j-plugins-utilities/src/main/java/de/julielab/neo4j/plugins/test/TestUtilities.java b/julielab-neo4j-plugins-utilities/src/main/java/de/julielab/neo4j/plugins/test/TestUtilities.java index 5fcfd1b..2fe70ef 100644 --- a/julielab-neo4j-plugins-utilities/src/main/java/de/julielab/neo4j/plugins/test/TestUtilities.java +++ b/julielab-neo4j-plugins-utilities/src/main/java/de/julielab/neo4j/plugins/test/TestUtilities.java @@ -1,13 +1,5 @@ package de.julielab.neo4j.plugins.test; -import static org.junit.Assert.assertFalse; - -import java.io.File; -import java.lang.reflect.Field; -import java.util.Iterator; -import java.util.List; -import java.util.Random; - import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Relationship; @@ -19,6 +11,14 @@ import org.neo4j.server.rest.repr.ListRepresentation; import org.neo4j.server.rest.repr.Representation; +import java.io.File; +import java.lang.reflect.Field; +import java.util.Iterator; +import java.util.List; +import java.util.Random; + +import static org.junit.Assert.assertFalse; + public class TestUtilities { public static final File GRAPH_DB_DIR = new File("src/test/resources/graph.db"); diff --git a/julielab-neo4j-plugins-utilities/src/main/java/org/neo4j/server/rest/repr/RecursiveMappingRepresentation.java b/julielab-neo4j-plugins-utilities/src/main/java/org/neo4j/server/rest/repr/RecursiveMappingRepresentation.java index f6c52ec..6b8a90f 100644 --- a/julielab-neo4j-plugins-utilities/src/main/java/org/neo4j/server/rest/repr/RecursiveMappingRepresentation.java +++ b/julielab-neo4j-plugins-utilities/src/main/java/org/neo4j/server/rest/repr/RecursiveMappingRepresentation.java @@ -1,25 +1,13 @@ package org.neo4j.server.rest.repr; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.neo4j.graphdb.Node; -import org.neo4j.server.rest.repr.ListRepresentation; -import org.neo4j.server.rest.repr.MappingRepresentation; -import org.neo4j.server.rest.repr.MappingSerializer; -import org.neo4j.server.rest.repr.Representation; -import org.neo4j.server.rest.repr.RepresentationType; -import org.neo4j.server.rest.repr.ValueRepresentation; - import com.google.common.primitives.Booleans; import com.google.common.primitives.Doubles; import com.google.common.primitives.Ints; import com.google.common.primitives.Longs; - import de.julielab.neo4j.plugins.auxiliaries.NodeRepresentation; +import org.neo4j.graphdb.Node; + +import java.util.*; /** * Custom convenience representation type. Must reside in this very package in diff --git a/julielab-neo4j-plugins-utilities/src/test/java/de/julielab/neo4j/plugins/auxiliaries/JulieNeo4jUtilitiesTest.java b/julielab-neo4j-plugins-utilities/src/test/java/de/julielab/neo4j/plugins/auxiliaries/JulieNeo4jUtilitiesTest.java index 62c48b8..d9368ad 100644 --- a/julielab-neo4j-plugins-utilities/src/test/java/de/julielab/neo4j/plugins/auxiliaries/JulieNeo4jUtilitiesTest.java +++ b/julielab-neo4j-plugins-utilities/src/test/java/de/julielab/neo4j/plugins/auxiliaries/JulieNeo4jUtilitiesTest.java @@ -1,11 +1,9 @@ package de.julielab.neo4j.plugins.auxiliaries; -import static org.junit.Assert.*; - -import java.util.Arrays; - import org.junit.Test; +import static org.junit.Assert.assertEquals; + public class JulieNeo4jUtilitiesTest { @Test diff --git a/julielab-neo4j-plugins-utilities/src/test/java/de/julielab/neo4j/plugins/auxiliaries/NodeRepresentationTest.java b/julielab-neo4j-plugins-utilities/src/test/java/de/julielab/neo4j/plugins/auxiliaries/NodeRepresentationTest.java index bf4fb0a..f9f0e15 100644 --- a/julielab-neo4j-plugins-utilities/src/test/java/de/julielab/neo4j/plugins/auxiliaries/NodeRepresentationTest.java +++ b/julielab-neo4j-plugins-utilities/src/test/java/de/julielab/neo4j/plugins/auxiliaries/NodeRepresentationTest.java @@ -1,12 +1,8 @@ package de.julielab.neo4j.plugins.auxiliaries; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.io.IOException; -import java.util.List; -import java.util.Map; - +import com.google.common.collect.Lists; +import de.julielab.neo4j.plugins.constants.NodeConstants; +import de.julielab.neo4j.plugins.test.TestUtilities; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; @@ -16,10 +12,12 @@ import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Transaction; -import com.google.common.collect.Lists; +import java.io.IOException; +import java.util.List; +import java.util.Map; -import de.julielab.neo4j.plugins.constants.NodeConstants; -import de.julielab.neo4j.plugins.test.TestUtilities; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; public class NodeRepresentationTest { private static GraphDatabaseService graphDb; diff --git a/pom.xml b/pom.xml index 7bffc58..9341606 100644 --- a/pom.xml +++ b/pom.xml @@ -4,10 +4,10 @@ julielab-parent de.julielab - 2.2.0 + 2.3.0 julielab-neo4j-server-plugins - 2.1.0-SNAPSHOT + 2.1.0 JULIE Lab Neo4j Server Plugins @@ -47,11 +47,6 @@ ${neo4j-release-version} provided - - org.neo4j - neo4j-shell - ${neo4j-release-version} - org.neo4j neo4j-kernel @@ -84,7 +79,7 @@ com.google.guava guava - 18.0 + 28.0-jre This project contains Neo4j server plugins used by the Julie Lab team. @@ -102,12 +97,12 @@ com.fasterxml.jackson.core jackson-databind - 2.9.10.4 + ${jackson-release-version} - 3.4.10 - 2.9.9 + 3.5.17 + 2.9.10.4