1 package de.dlr.shepard.common.neo4j.daos;
2
3 import de.dlr.shepard.common.neo4j.NeoConnector;
4 import de.dlr.shepard.common.util.Constants;
5 import de.dlr.shepard.common.util.CypherQueryHelper;
6 import de.dlr.shepard.common.util.CypherQueryHelper.Neighborhood;
7 import de.dlr.shepard.common.util.TraversalRules;
8 import io.quarkus.logging.Log;
9 import java.util.Collection;
10 import java.util.HashMap;
11 import java.util.Map;
12 import org.neo4j.ogm.cypher.Filter;
13 import org.neo4j.ogm.model.Result;
14 import org.neo4j.ogm.session.Session;
15
16 public abstract class GenericDAO<T> {
17
18 protected static final int DEPTH_ENTITY = 1;
19
20 protected Session session = null;
21
22 protected GenericDAO() {
23 session = NeoConnector.getInstance().getNeo4jSession();
24 }
25
26
27
28
29
30
31 public Collection<T> findAll() {
32 Collection<T> iter = session.loadAll(getEntityType(), DEPTH_ENTITY);
33 return iter;
34 }
35
36
37
38
39
40
41
42 public T findByNeo4jId(long id) {
43 return session.load(getEntityType(), id, DEPTH_ENTITY);
44 }
45
46
47
48
49
50
51
52 public T findLightByNeo4jId(long id) {
53 return session.load(getEntityType(), id, 0);
54 }
55
56
57
58
59
60
61
62 public Collection<T> findMatching(Filter filter) {
63 return session.loadAll(getEntityType(), filter, DEPTH_ENTITY);
64 }
65
66
67
68
69
70
71
72
73
74
75 public boolean deleteByNeo4jId(long id) {
76 T entity = session.load(getEntityType(), id);
77 if (entity != null) {
78 session.delete(entity);
79 return true;
80 }
81 return false;
82 }
83
84
85
86
87
88
89
90 public T createOrUpdate(T entity) {
91 session.save(entity, DEPTH_ENTITY);
92 return entity;
93 }
94
95 public void clearSession() {
96 session.clear();
97 }
98
99
100
101
102
103
104
105
106
107 public Iterable<T> findByQuery(String query, Map<String, Object> paramsMap) {
108 Log.debugf("Run query: %s", query);
109 StringBuilder str = new StringBuilder();
110 for (var entry : paramsMap.entrySet()) {
111 str.append("(" + entry.getKey() + ", " + entry.getValue() + "), ");
112 }
113 Log.debugf("queryParams: %s", str.toString());
114 Iterable<T> iter = session.query(getEntityType(), query, paramsMap);
115 return iter;
116 }
117
118 public boolean runQuery(String query, Map<String, Object> paramsMap) {
119 Log.debugf("Run query: %s", query);
120 Result result = session.query(query, paramsMap);
121 return result.queryStatistics().containsUpdates();
122 }
123
124 public String getSearchForReachableReferencesByShepardIdQuery(
125 TraversalRules traversalRule,
126 long collectionShepardId,
127 long startShepardId,
128 String userName
129 ) {
130 String ret = "MATCH path = (col:Collection)-[:has_dataobject]->";
131 ret += getTraversalRulesPath(traversalRule);
132 ret += "-[hr:has_reference]->(r:" + getEntityType().getSimpleName() + ")";
133 ret += getWithPart("ns", "ret");
134 ret +=
135 " WHERE d." +
136 Constants.SHEPARD_ID +
137 " = " +
138 startShepardId +
139 " AND col." +
140 Constants.SHEPARD_ID +
141 " = " +
142 collectionShepardId;
143 ret += getReturnPart("ns", "ret", "col", userName);
144 return ret;
145 }
146
147 public String getSearchForReachableReferencesByNeo4jIdQuery(
148 TraversalRules traversalRule,
149 long collectionShepardId,
150 long startShepardId,
151 String userName
152 ) {
153 String ret = "MATCH path = (col:Collection)-[:has_dataobject]->";
154 ret += getTraversalRulesPath(traversalRule);
155 ret += "-[hr:has_reference]->(r:" + getEntityType().getSimpleName() + ")";
156 ret += getWithPart("ns", "ret");
157 ret += " WHERE id(d) = " + startShepardId + " AND id(col) = " + collectionShepardId;
158 ret += getReturnPart("ns", "ret", "col", userName);
159 return ret;
160 }
161
162 private String getTraversalRulesPath(TraversalRules traversalRule) {
163 if (traversalRule == null) return "(d:DataObject)";
164 return switch (traversalRule) {
165 case children -> "(d:DataObject)-[:has_child*0..]->(e:DataObject)";
166 case parents -> "(d:DataObject)<-[:has_child*0..]-(e:DataObject)";
167 case successors -> "(d:DataObject)-[:has_successor*0..]->(e:DataObject)";
168 case predecessors -> "(d:DataObject)<-[:has_successor*0..]-(e:DataObject)";
169 default -> "(d:DataObject)";
170 };
171 }
172
173 public String getSearchForReachableReferencesQuery(long collectionId, String userName) {
174 String ret = "MATCH path = (col:Collection)-[:has_dataobject]->(do:DataObject)";
175 ret += "-[hr:has_reference]->(r:" + getEntityType().getSimpleName() + ")";
176 ret += getWithPart("ns", "ret");
177 ret += " WHERE id(col) = " + collectionId;
178 ret += getReturnPart("ns", "ret", "col", userName);
179 return ret;
180 }
181
182 public String getSearchForReachableReferencesByShepardIdQuery(long collectionShepardId, String userName) {
183 String ret = "MATCH path = (col:Collection)-[:has_dataobject]->(do:DataObject)";
184 ret += "-[hr:has_reference]->(r:" + getEntityType().getSimpleName() + ")";
185 ret += getWithPart("ns", "ret");
186 ret += " WHERE col." + Constants.SHEPARD_ID + " = " + collectionShepardId;
187 ret += getReturnPart("ns", "ret", "col", userName);
188 return ret;
189 }
190
191 public String getSearchForReachableReferencesQuery(long collectionId, long startId, String userName) {
192 String ret = "MATCH path = (col:Collection)-[:has_dataobject]->(d:DataObject)";
193 ret += "-[hr:has_reference]->(r:" + getEntityType().getSimpleName() + ")";
194 ret += getWithPart("ns", "ret");
195 ret += " WHERE id(d) = " + startId + " AND id(col) = " + collectionId;
196 ret += getReturnPart("ns", "ret", "col", userName);
197 return ret;
198 }
199
200 public String getSearchForReachableReferencesByShepardIdQuery(
201 long collectionShepardId,
202 long startShepardId,
203 String userName
204 ) {
205 String ret = "MATCH path = (col:Collection)-[:has_dataobject]->(d:DataObject)";
206 ret += "-[hr:has_reference]->(r:" + getEntityType().getSimpleName() + ")";
207 ret += getWithPart("ns", "ret");
208 ret +=
209 " WHERE d." +
210 Constants.SHEPARD_ID +
211 " = " +
212 startShepardId +
213 " AND col." +
214 Constants.SHEPARD_ID +
215 " = " +
216 collectionShepardId;
217 ret += getReturnPart("ns", "ret", "col", userName);
218 return ret;
219 }
220
221 private String getWithPart(String nodesVar, String retVar) {
222 return " WITH nodes(path) as " + nodesVar + ", r as " + retVar;
223 }
224
225 private String getReturnPart(String nodesVar, String retVar, String collectionVar, String username) {
226 String ret = "";
227 ret += " AND NONE(node IN " + nodesVar + " WHERE (node.deleted = TRUE))";
228 ret += " AND " + CypherQueryHelper.getReadableByQuery(collectionVar, username);
229 ret += " " + CypherQueryHelper.getReturnPart(retVar, Neighborhood.EVERYTHING);
230 return ret;
231 }
232
233 public void deleteRelation(long fromId, long toId, String fromType, String toType, String relationName) {
234 String query = String.format(
235 "MATCH (a:%s {shepardId: %s})-[r:%s]->(b:%s {shepardId: %s}) DELETE r;",
236 fromType,
237 fromId,
238 relationName,
239 toType,
240 toId
241 );
242 session.query(query, new HashMap<String, String>());
243 }
244
245 public abstract Class<T> getEntityType();
246 }