Skip to content

Commit

Permalink
Update label property from 'name' to 'label' (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
QubitPi authored Nov 15, 2024
1 parent ea314ab commit aac89a2
Show file tree
Hide file tree
Showing 8 changed files with 46 additions and 26 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ We should see `HTTP/1.1 201 Created` as signs of success.
- vocabulary count: https://api.paion-data.dev/wilhelm/languages/german?perPage=100&page=1
- query vocabulary paged: https://api.paion-data.dev/wilhelm/languages/german/count
- expand: https://api.paion-data.dev/wilhelm/expand/nämlich
- search: https://api.paion-data.dev/wilhelm/search/das

License
-------
Expand Down
16 changes: 11 additions & 5 deletions src/main/java/org/qubitpi/wilhelm/Link.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@
@JsonIncludeProperties({ "label", "sourceNodeId", "targetNodeId", "attributes" })
public class Link {

/**
* The database node attribute name whose value is used for displaying the relationship caption on UI.
* <p>
* For example, for Neo4J database, this would correspond to a relationship property.
*/
public static final String LABEL_ATTRIBUTE = "label";

private static final Logger LOG = LoggerFactory.getLogger(Link.class);

private final String label;
Expand Down Expand Up @@ -93,18 +100,17 @@ private Link(
* @throws IllegalStateException if {@code relationship} is missing a "name" property
*/
public static Link valueOf(final Relationship relationship) {
final String labelKey = "name";
if (!Objects.requireNonNull(relationship).asMap().containsKey(labelKey)) {
LOG.error("Neo4J relationship does not contain '{}' attribute: {}", labelKey, relationship.asMap());
if (!Objects.requireNonNull(relationship).asMap().containsKey(LABEL_ATTRIBUTE)) {
LOG.error("Neo4J relationship does not contain '{}' attribute: {}", LABEL_ATTRIBUTE, relationship.asMap());
throw new IllegalStateException(
"There seems to be a data format mismatch between Wilhelm webservice and Neo4J database. " +
"Please file an issue at https://github.com/QubitPi/wilhelm-ws/issues for a fix"
);
}

final String label = relationship.asMap().get(labelKey).toString();
final String label = relationship.asMap().get(LABEL_ATTRIBUTE).toString();
final Map<String, Object> attributes = relationship.asMap().entrySet().stream()
.filter(entry -> !labelKey.equals(entry.getKey()))
.filter(entry -> !LABEL_ATTRIBUTE.equals(entry.getKey()))
.collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, Map.Entry::getValue));

return new Link(label, relationship.startNodeElementId(), relationship.endNodeElementId(), attributes);
Expand Down
16 changes: 11 additions & 5 deletions src/main/java/org/qubitpi/wilhelm/Node.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@
@JsonIncludeProperties({ "id", "label", "attributes" })
public class Node {

/**
* The database node attribute name whose value is used for displaying the node caption on UI.
* <p>
* For example, for Neo4J database, this would correspond to a node property.
*/
public static final String LABEL_ATTRIBUTE = "label";

private static final Logger LOG = LoggerFactory.getLogger(Node.class);

private final String id;
Expand Down Expand Up @@ -82,18 +89,17 @@ private Node(@NotNull final String id, @NotNull final String label, @NotNull fin
* @throws IllegalStateException if {@code node} is missing a "name" property
*/
public static Node valueOf(@NotNull final org.neo4j.driver.types.Node node) {
final String labelKey = "name";
if (!Objects.requireNonNull(node).asMap().containsKey(labelKey)) {
LOG.error("Neo4J node does not contain '{}' attribute: {}", labelKey, node.asMap());
if (!Objects.requireNonNull(node).asMap().containsKey(LABEL_ATTRIBUTE)) {
LOG.error("Neo4J node does not contain '{}' attribute: {}", LABEL_ATTRIBUTE, node.asMap());
throw new IllegalStateException(
"There seems to be a data format mismatch between Wilhelm webservice and Neo4J database. " +
"Please file an issue at https://github.com/QubitPi/wilhelm-ws/issues for a fix"
);
}

final String label = node.asMap().get(labelKey).toString();
final String label = node.asMap().get(LABEL_ATTRIBUTE).toString();
final Map<String, Object> attributes = node.asMap().entrySet().stream()
.filter(entry -> !labelKey.equals(entry.getKey()))
.filter(entry -> !LABEL_ATTRIBUTE.equals(entry.getKey()))
.collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, Map.Entry::getValue));

return new Node(node.elementId(), label, attributes);
Expand Down
17 changes: 12 additions & 5 deletions src/main/java/org/qubitpi/wilhelm/web/endpoints/Neo4JServlet.java
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,12 @@ public Response getVocabularyByLanguagePaged(

final String query = String.format(
"MATCH (t:Term WHERE t.language = '%s')-[r]->(d:Definition) " +
"RETURN t.name AS term, d.name AS definition " +
"RETURN t.%s AS term, d.%s AS definition " +
"SKIP %s LIMIT %s",
requestedLanguage.getDatabaseName(), (Integer.parseInt(page) - 1) * Integer.parseInt(perPage), perPage
requestedLanguage.getDatabaseName(),
Node.LABEL_ATTRIBUTE,
Node.LABEL_ATTRIBUTE,
(Integer.parseInt(page) - 1) * Integer.parseInt(perPage), perPage
);

return Response
Expand All @@ -142,14 +145,17 @@ public Response getVocabularyByLanguagePaged(
*
* @param keyword The provided keyword
*
* @return all nodes whose "name" attribute contains the search keyword
* @return all nodes whose {@link Node#LABEL_ATTRIBUTE "label"} attribute contains the search keyword
*/
@GET
@Path("/search/{keyword}")
@Produces(MediaType.APPLICATION_JSON)
@SuppressWarnings("MultipleStringLiterals")
public Response search(@NotNull @PathParam("keyword") final String keyword) {
final String query = String.format("MATCH (node) WHERE node.name =~ '.*%s.*' RETURN node", keyword);
final String query = String.format(
"MATCH (node) WHERE node.%s =~ '.*%s.*' RETURN node",
Node.LABEL_ATTRIBUTE, keyword
);

return Response
.status(Response.Status.OK)
Expand Down Expand Up @@ -313,12 +319,13 @@ public Response expandApoc(

final String query = String.format(
"""
MATCH (node{name:'%s'})
MATCH (node{%s:'%s'})
CALL apoc.path.expand(node, "LINK", null, 1, %s)
YIELD path
RETURN path, length(path) AS hops
ORDER BY hops;
""",
Node.LABEL_ATTRIBUTE,
word.replace("'", "\\'"), maxHops
);

Expand Down
4 changes: 2 additions & 2 deletions src/test/groovy/org/qubitpi/wilhelm/LinkSpec.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class LinkSpec extends Specification {
_ | "attributes"
}

def "when a Neo4J relationship does not contain 'name' property, an error is thrown"() {
def "when a Neo4J relationship does not contain 'label' property, an error is thrown"() {
when: "a Neo4J node has no properties"
Link.valueOf(Mock(Relationship) {asMap() >> [:]})

Expand All @@ -62,7 +62,7 @@ class LinkSpec extends Specification {
when: "a happy path Neo4J relationship is being converted to a transparent link"
Link actual = Link.valueOf(Mock(Relationship) {
asMap() >> [
name: "my node",
label: "my node",
type: "follows"
]
startNodeElementId() >> "node1"
Expand Down
4 changes: 2 additions & 2 deletions src/test/groovy/org/qubitpi/wilhelm/NodeSpec.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class NodeSpec extends Specification {
_ | "attributes"
}

def "when a Neo4J node does not contain 'name' property, an error is thrown"() {
def "when a Neo4J node does not contain 'label' property, an error is thrown"() {
when: "a Neo4J node has no properties"
Node.valueOf(Mock(org.neo4j.driver.types.Node) {asMap() >> [:]})

Expand All @@ -59,7 +59,7 @@ class NodeSpec extends Specification {
when: "a happy path Neo4J node is being converted to a transparent node"
Node actual = Node.valueOf(Mock(org.neo4j.driver.types.Node) {
asMap() >> [
name: "my node",
label: "my node",
color: "blue",
size: "medium"
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ class Neo4JServletITSpec extends Specification {
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.when()
.get("/neo4j/expand/nämlich")
.get("/neo4j/expand/dreißig")
.then()
.statusCode(200)
.body("", hasKey("nodes"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ class Neo4JServletSpec extends Specification {
keys() >> ["term", "definition"]
get("term") >> Mock(Value) {
type() >> InternalTypeSystem.TYPE_SYSTEM.NODE()
keys() >> ["name", "language"]
get("name") >> Mock(Value) {
keys() >> ["label", "language"]
get("label") >> Mock(Value) {
type() >> InternalTypeSystem.TYPE_SYSTEM.STRING()
asString() >> "Hallo"
}
Expand All @@ -44,8 +44,8 @@ class Neo4JServletSpec extends Specification {
}
get("definition") >> Mock(Value) {
type() >> InternalTypeSystem.TYPE_SYSTEM.NODE()
keys() >> ["name"]
get("name") >> Mock(Value) {
keys() >> ["label"]
get("label") >> Mock(Value) {
type() >> InternalTypeSystem.TYPE_SYSTEM.STRING()
asString() >> "Hello"
}
Expand All @@ -55,11 +55,11 @@ class Neo4JServletSpec extends Specification {
expect:
Neo4JServlet.expand(value) == [
term: [
name: "Hallo",
label: "Hallo",
language: "German"
],
definition: [
name: "Hello"
label: "Hello"
]
]
}
Expand Down

0 comments on commit aac89a2

Please sign in to comment.