1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package eu.ehri.project.core.impl;
21
22 import com.google.common.base.Preconditions;
23 import com.google.common.collect.Sets;
24 import com.tinkerpop.blueprints.CloseableIterable;
25 import com.tinkerpop.blueprints.Vertex;
26 import com.tinkerpop.frames.FramedGraph;
27 import eu.ehri.project.core.impl.neo4j.Neo4j2Graph;
28 import eu.ehri.project.core.impl.neo4j.Neo4j2Vertex;
29 import eu.ehri.project.exceptions.IntegrityError;
30 import eu.ehri.project.exceptions.ItemNotFound;
31 import eu.ehri.project.models.EntityClass;
32 import eu.ehri.project.models.annotations.EntityType;
33 import eu.ehri.project.models.utils.ClassUtils;
34 import org.neo4j.graphdb.GraphDatabaseService;
35 import org.neo4j.graphdb.Label;
36 import org.neo4j.graphdb.schema.ConstraintDefinition;
37 import org.neo4j.graphdb.schema.IndexDefinition;
38 import org.neo4j.graphdb.schema.Schema;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41
42 import java.util.Collection;
43 import java.util.Map;
44 import java.util.NoSuchElementException;
45 import java.util.Set;
46
47
48
49
50
51 public final class Neo4jGraphManager<T extends Neo4j2Graph> extends BlueprintsGraphManager<T> {
52
53 private final static Logger logger = LoggerFactory.getLogger(Neo4jGraphManager.class);
54
55 public Neo4jGraphManager(FramedGraph<T> graph) {
56 super(graph);
57 }
58
59 public static final String BASE_LABEL = "_Entity";
60
61 @Override
62 public boolean exists(String id) {
63 Preconditions.checkNotNull(id,
64 "attempt determine existence of a vertex with a null id");
65 try (CloseableIterable<Vertex> q = graph.getBaseGraph()
66 .getVerticesByLabelKeyValue(BASE_LABEL, EntityType.ID_KEY, id)) {
67 return q.iterator().hasNext();
68 }
69 }
70
71 @Override
72 public Vertex getVertex(String id) throws ItemNotFound {
73 Preconditions
74 .checkNotNull(id, "attempt to fetch vertex with a null id");
75 try (CloseableIterable<Vertex> q = graph.getBaseGraph()
76 .getVerticesByLabelKeyValue(BASE_LABEL, EntityType.ID_KEY, id)) {
77 return q.iterator().next();
78 } catch (NoSuchElementException e) {
79 throw new ItemNotFound(id);
80 }
81 }
82
83 @Override
84 public CloseableIterable<Vertex> getVertices(String key, Object value,
85 EntityClass type) {
86 return graph.getBaseGraph().getVerticesByLabelKeyValue(type.getName(),
87 key, value);
88 }
89
90 @Override
91 public Vertex createVertex(String id, EntityClass type,
92 Map<String, ?> data) throws IntegrityError {
93 return setLabels(super.createVertex(id, type, data));
94 }
95
96 @Override
97 public Vertex updateVertex(String id, EntityClass type,
98 Map<String, ?> data) throws ItemNotFound {
99 return setLabels(super.updateVertex(id, type, data));
100 }
101
102 @Override
103 public void initialize() {
104 createIndicesAndConstraints(graph.getBaseGraph().getRawGraph());
105 }
106
107 @Override
108 public CloseableIterable<Vertex> getVertices(EntityClass type) {
109 return graph.getBaseGraph().getVerticesByLabel(type.getName());
110 }
111
112
113
114
115
116
117
118 public Vertex setLabels(Vertex vertex) {
119 Neo4j2Vertex node = (Neo4j2Vertex) vertex;
120 for (String label : node.getLabels()) {
121 node.removeLabel(label);
122 }
123 node.addLabel(BASE_LABEL);
124 String type = getType(vertex);
125 node.addLabel(type);
126 return node;
127 }
128
129
130
131
132 public static void createIndicesAndConstraints(GraphDatabaseService graph) {
133 Schema schema = graph.schema();
134 for (ConstraintDefinition constraintDefinition : schema.getConstraints()) {
135 constraintDefinition.drop();
136 }
137 for (IndexDefinition indexDefinition : schema.getIndexes()) {
138 indexDefinition.drop();
139 }
140
141 schema.constraintFor(Label.label(BASE_LABEL))
142 .assertPropertyIsUnique(EntityType.ID_KEY)
143 .create();
144 schema.indexFor(Label.label(BASE_LABEL))
145 .on(EntityType.TYPE_KEY)
146 .create();
147
148
149
150 for (EntityClass cls : EntityClass.values()) {
151 Set<String> propertyKeys = Sets.newHashSet();
152 propertyKeys.addAll(ClassUtils.getIndexedPropertyKeys(cls.getJavaClass()));
153 propertyKeys.addAll(ClassUtils.getMandatoryPropertyKeys(cls.getJavaClass()));
154 for (String prop : propertyKeys) {
155 logger.trace("Creating index on property: {} -> {}", cls.getName(), prop);
156 schema.indexFor(Label.label(cls.getName()))
157 .on(prop)
158 .create();
159 }
160
161 Collection<String> uniquePropertyKeys = ClassUtils.getUniquePropertyKeys(cls.getJavaClass());
162 for (String unique : uniquePropertyKeys) {
163 logger.trace("Creating constraint on unique property: {} -> {}",
164 cls.getName(), unique);
165 schema.constraintFor(Label.label(cls.getName()))
166 .assertPropertyIsUnique(unique)
167 .create();
168 }
169 }
170 }
171 }