org.neo4j.procedure.builtin.graphschema.GraphSchemaGraphyResultWrapper Maven / Gradle / Ivy
/*
* Copyright (c) "Neo4j"
* Neo4j Sweden AB [https://neo4j.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package org.neo4j.procedure.builtin.graphschema;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.Entity;
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.procedure.builtin.graphschema.GraphSchema.NodeObjectType;
import org.neo4j.procedure.builtin.graphschema.GraphSchema.Ref;
import org.neo4j.procedure.builtin.graphschema.GraphSchema.RelationshipObjectType;
import org.neo4j.procedure.builtin.graphschema.GraphSchema.Token;
/**
* A graph-y result build from a {@link GraphSchema}. The wrapper is needed to make the Neo4j embedded API happy.
*/
public final class GraphSchemaGraphyResultWrapper {
public static GraphSchemaGraphyResultWrapper flat(GraphSchema graphSchema) {
var nodeLabels = graphSchema.nodeLabels().values().stream().collect(Collectors.toMap(Token::id, Token::value));
var relationshipTypes =
graphSchema.relationshipTypes().values().stream().collect(Collectors.toMap(Token::id, Token::value));
var result = new GraphSchemaGraphyResultWrapper();
var nodeObjectTypeNodes = new HashMap();
for (NodeObjectType nodeObjectType : graphSchema.nodeObjectTypes().values()) {
var labels = nodeObjectType.labels().stream()
.map(v -> nodeLabels.get(v.value()))
.toArray(String[]::new);
var node = new VirtualNode(
Map.of(
"$id",
nodeObjectType.id(),
"name",
labels.length == 0 ? "n/a" : labels[0],
"properties",
GraphSchemaModule.asJsonString(nodeObjectType.properties())),
labels);
nodeObjectTypeNodes.put(new Ref(nodeObjectType.id()), node);
}
result.nodes.addAll(nodeObjectTypeNodes.values());
for (RelationshipObjectType relationshipObjectType :
graphSchema.relationshipObjectTypes().values()) {
var relationship = new VirtualRelationship(
nodeObjectTypeNodes.get(relationshipObjectType.from()),
relationshipTypes.get(relationshipObjectType.type().value()),
Map.of(
"$id",
relationshipObjectType.id(),
"properties",
GraphSchemaModule.asJsonString(relationshipObjectType.properties())),
nodeObjectTypeNodes.get(relationshipObjectType.to()));
result.relationships.add(relationship);
}
return result;
}
public static GraphSchemaGraphyResultWrapper full(GraphSchema graphSchema) {
var nodeLabelNodes = graphSchema.nodeLabels().values().stream()
.collect(Collectors.toMap(Token::id, t -> toVirtualNode(t, "NodeLabel")));
var relationshipTypeNodes = graphSchema.relationshipTypes().values().stream()
.collect(Collectors.toMap(Token::id, t -> toVirtualNode(t, "RelationshipType")));
var result = new GraphSchemaGraphyResultWrapper();
var nodeObjectTypeNodes = new HashMap();
for (var entry : graphSchema.nodeObjectTypes().entrySet()) {
var nodeObjectType = entry.getValue();
var node = new VirtualNode(
Map.of(
"$id",
nodeObjectType.id(),
"properties",
GraphSchemaModule.asJsonString(nodeObjectType.properties())),
"NodeObjectType");
nodeObjectTypeNodes.put(entry.getKey(), node);
for (var ref : nodeObjectType.labels()) {
var tokenNode = nodeLabelNodes.get(ref.value());
result.relationships.add(new VirtualRelationship(node, "HAS_LABEL", tokenNode));
}
}
for (RelationshipObjectType relationshipObjectType :
graphSchema.relationshipObjectTypes().values()) {
var node = new VirtualNode(
Map.of(
"$id",
relationshipObjectType.id(),
"properties",
GraphSchemaModule.asJsonString(relationshipObjectType.properties())),
"RelationshipObjectTypes");
result.nodes.add(node);
result.relationships.add(new VirtualRelationship(
node,
"HAS_TYPE",
relationshipTypeNodes.get(relationshipObjectType.type().value())));
result.relationships.add(
new VirtualRelationship(node, "FROM", nodeObjectTypeNodes.get(relationshipObjectType.from())));
result.relationships.add(
new VirtualRelationship(node, "TO", nodeObjectTypeNodes.get(relationshipObjectType.to())));
}
// Add remaining things
result.nodes.addAll(nodeLabelNodes.values());
result.nodes.addAll(relationshipTypeNodes.values());
result.nodes.addAll(nodeObjectTypeNodes.values());
return result;
}
private static Node toVirtualNode(Token token, String label) {
return new VirtualNode(Map.of("$id", token.id(), "value", token.value()), "Token", label);
}
// Public field required for Neo4j internal API.
public final List nodes = new ArrayList<>();
public final List relationships = new ArrayList<>();
/**
* A virtual entity, spotting a negative ID and a random element id.
*/
abstract static class VirtualEntity implements Entity {
private static final Supplier ID_FACTORY = new AtomicLong(-1)::decrementAndGet;
private final long id;
private final String elementId;
private final Map properties;
VirtualEntity(Map properties) {
this.id = ID_FACTORY.get();
this.elementId = String.valueOf(this.id);
this.properties = Map.copyOf(properties);
}
@SuppressWarnings("removal")
@Override
public final long getId() {
return id;
}
@Override
public final String getElementId() {
return elementId;
}
@Override
public final boolean hasProperty(String key) {
return properties.containsKey(key);
}
@Override
public final Object getProperty(String key) {
return properties.get(key);
}
@Override
public final Object getProperty(String key, Object defaultValue) {
return properties.getOrDefault(key, defaultValue);
}
@Override
public final void setProperty(String key, Object value) {
throw new UnsupportedOperationException();
}
@Override
public final Object removeProperty(String key) {
throw new UnsupportedOperationException();
}
@Override
public final Iterable getPropertyKeys() {
return properties.keySet();
}
@Override
public final Map getProperties(String... keys) {
Map result = new HashMap<>();
for (String key : keys) {
if (!hasProperty(key)) {
continue;
}
result.put(key, getProperty(key));
}
return result;
}
@Override
public final Map getAllProperties() {
return properties;
}
@Override
public final void delete() {
throw new UnsupportedOperationException();
}
}
static final class VirtualNode extends VirtualEntity implements Node {
private final Set
© 2015 - 2025 Weber Informatics LLC | Privacy Policy