Skip to content
This repository was archived by the owner on May 24, 2022. It is now read-only.

Commit f25b562

Browse files
author
Thomas Gängler
committed
[DD-1002] records deprecation endpoint
1 parent 7530e8b commit f25b562

File tree

4 files changed

+333
-9
lines changed

4 files changed

+333
-9
lines changed

src/main/java/org/dswarm/graph/delta/util/GraphDBUtil.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1253,12 +1253,13 @@ private static String buildGetRecordUriQuery(
12531253
// RETURN n.uri;
12541254

12551255
final StringBuilder sb = new StringBuilder();
1256-
sb.append("MATCH (o:").append(NodeType.Literal).append(" {").append(GraphStatics.VALUE_PROPERTY).append(":\"").append(recordId).append("\"})\n")
1256+
sb.append("MATCH (o:").append(NodeType.Literal).append(" {").append(GraphStatics.VALUE_PROPERTY).append(":\"").append(recordId)
1257+
.append("\"})\n")
12571258
.append("WITH o\n")
12581259
.append("MATCH (o)");
12591260

12601261
final List<Attribute> attributes = prefixedRecordIdentifierAP.getAttributes();
1261-
int i = attributes.size() -1;
1262+
int i = attributes.size() - 1;
12621263

12631264
while (i >= 0) {
12641265

@@ -1289,12 +1290,13 @@ private static String buildGetRecordUrisQuery(final String searchValue, final At
12891290
throws DMPGraphException {
12901291

12911292
final StringBuilder sb = new StringBuilder();
1292-
sb.append("MATCH (o:").append(NodeType.Literal).append(" {").append(GraphStatics.VALUE_PROPERTY).append(":\"").append(searchValue).append("\"})\n")
1293+
sb.append("MATCH (o:").append(NodeType.Literal).append(" {").append(GraphStatics.VALUE_PROPERTY).append(":\"").append(searchValue)
1294+
.append("\"})\n")
12931295
.append("WITH o\n")
12941296
.append("MATCH (o)");
12951297

12961298
final List<Attribute> attributes = prefixedKeyAttributePath.getAttributes();
1297-
int i = attributes.size() -1;
1299+
int i = attributes.size() - 1;
12981300

12991301
while (i >= 0) {
13001302

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
/**
2+
* This file is part of d:swarm graph extension.
3+
*
4+
* d:swarm graph extension is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* d:swarm graph extension is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with d:swarm graph extension. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
package org.dswarm.graph.deprecate;
18+
19+
import java.util.Collection;
20+
import java.util.Iterator;
21+
import java.util.Map;
22+
import java.util.Optional;
23+
24+
import org.neo4j.graphdb.GraphDatabaseService;
25+
import org.neo4j.graphdb.Node;
26+
import org.neo4j.graphdb.Result;
27+
import org.slf4j.Logger;
28+
import org.slf4j.LoggerFactory;
29+
30+
import org.dswarm.graph.BasicNeo4jProcessor;
31+
import org.dswarm.graph.DMPGraphException;
32+
import org.dswarm.graph.NodeType;
33+
import org.dswarm.graph.model.GraphStatics;
34+
import org.dswarm.graph.versioning.DataModelNeo4jVersionHandler;
35+
36+
/**
37+
* @author tgaengler
38+
*/
39+
public class RecordsNeo4jDeprecator extends BaseNeo4jDeprecator {
40+
41+
private static final Logger LOG = LoggerFactory.getLogger(RecordsNeo4jDeprecator.class);
42+
public static final String RECORD_VARIABLE = "record";
43+
44+
private final String prefixedDataModelUri;
45+
private final Collection<String> prefixedRecordURIs;
46+
47+
public RecordsNeo4jDeprecator(final BasicNeo4jProcessor processorArg, final boolean enableVersioningArg, final String prefixedDataModelUriArg,
48+
final Collection<String> prefixedRecordURIsArg)
49+
throws DMPGraphException {
50+
51+
super(processorArg, enableVersioningArg);
52+
53+
prefixedDataModelUri = prefixedDataModelUriArg;
54+
prefixedRecordURIs = prefixedRecordURIsArg;
55+
}
56+
57+
@Override
58+
protected void init() throws DMPGraphException {
59+
60+
versionHandler = new DataModelNeo4jVersionHandler(processor, enableVersioning);
61+
version = versionHandler.getLatestVersion();
62+
previousVersion = version - 1;
63+
}
64+
65+
@Override public void work() throws DMPGraphException {
66+
67+
LOG.debug("try to deprecate some records in data model '{}'", prefixedDataModelUri);
68+
69+
processor.ensureRunningTx();
70+
71+
final GraphDatabaseService database = processor.getDatabase();
72+
73+
for (final String prefixedRecordURI : prefixedRecordURIs) {
74+
75+
final Optional<Node> optionalRecord = getRecord(database, prefixedRecordURI);
76+
77+
if(!optionalRecord.isPresent()) {
78+
79+
continue;
80+
}
81+
82+
final Node record = optionalRecord.get();
83+
84+
startNodeHandler.handleNode(record);
85+
}
86+
87+
LOG.debug("finished deprecating some records in data model '{}'", prefixedDataModelUri);
88+
}
89+
90+
private Optional<Node> getRecord(final GraphDatabaseService database, final String prefixedRecordURI) {
91+
92+
final String query = buildQuery(prefixedRecordURI);
93+
94+
final Result result = database.execute(query);
95+
96+
return evaluateSingleNodeResult(prefixedRecordURI, result);
97+
}
98+
99+
private Optional<Node> evaluateSingleNodeResult(String prefixedRecordURI, Result result) {
100+
101+
if(result == null) {
102+
103+
LOG.error("couldn't retrieve record for uri '{}'", prefixedRecordURI);
104+
105+
return Optional.empty();
106+
}
107+
108+
if (!result.hasNext()) {
109+
110+
result.close();
111+
112+
LOG.error("couldn't find record for uri '{}'", prefixedRecordURI);
113+
114+
return Optional.empty();
115+
}
116+
117+
final Map<String, Object> row = result.next();
118+
119+
final Iterator<Map.Entry<String, Object>> rowIter = row.entrySet().iterator();
120+
121+
if (!rowIter.hasNext()) {
122+
123+
result.close();
124+
125+
LOG.error("couldn't find record for uri '{}'", prefixedRecordURI);
126+
127+
return Optional.empty();
128+
}
129+
130+
final Map.Entry<String, Object> column = rowIter.next();
131+
132+
if (column.getValue() == null) {
133+
134+
result.close();
135+
136+
LOG.error("couldn't find record for uri '{}'", prefixedRecordURI);
137+
138+
return Optional.empty();
139+
}
140+
141+
if (!column.getKey().equals(RECORD_VARIABLE) || !Node.class.isInstance(column.getValue())) {
142+
143+
result.close();
144+
145+
return Optional.empty();
146+
}
147+
148+
final Node record = (Node) column.getValue();
149+
150+
result.close();
151+
152+
return Optional.ofNullable(record);
153+
}
154+
155+
private String buildQuery(final String prefixedRecordURI) {
156+
157+
final StringBuilder sb = new StringBuilder();
158+
159+
sb.append("MATCH ").append("(n:").append(NodeType.Resource).append(" {").append(GraphStatics.URI_PROPERTY).append(" : \"").append(prefixedRecordURI).append("\"})\n")
160+
.append("WHERE n.").append(GraphStatics.DATA_MODEL_PROPERTY).append(" = \"").append(prefixedDataModelUri).append("\"\n")
161+
.append("RETURN n AS ").append(RECORD_VARIABLE);
162+
163+
return sb.toString();
164+
}
165+
}

src/main/java/org/dswarm/graph/resources/MaintainResource.java

Lines changed: 92 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import java.io.IOException;
2121
import java.io.StringWriter;
2222
import java.net.URL;
23+
import java.util.ArrayList;
24+
import java.util.Collection;
2325
import java.util.HashMap;
2426
import java.util.Map;
2527
import java.util.Map.Entry;
@@ -37,6 +39,7 @@
3739

3840
import com.fasterxml.jackson.core.JsonGenerator;
3941
import com.fasterxml.jackson.core.type.TypeReference;
42+
import com.fasterxml.jackson.databind.JsonNode;
4043
import com.fasterxml.jackson.databind.node.ObjectNode;
4144
import com.google.common.base.Charsets;
4245
import com.google.common.base.Optional;
@@ -61,6 +64,7 @@
6164
import org.dswarm.graph.GraphIndexStatics;
6265
import org.dswarm.graph.GraphProcessingStatics;
6366
import org.dswarm.graph.deprecate.DataModelNeo4jDeprecator;
67+
import org.dswarm.graph.deprecate.RecordsNeo4jDeprecator;
6468
import org.dswarm.graph.deprecate.RelationshipDeprecator;
6569
import org.dswarm.graph.index.MapDBUtils;
6670
import org.dswarm.graph.index.NamespaceIndex;
@@ -87,6 +91,8 @@ public class MaintainResource extends GraphResource {
8791

8892
private static final String DEPRECATE_DATA_MODEL_TYPE = "deprecate data model";
8993

94+
private static final String DEPRECATE_RECORDS_TYPE = "deprecate records";
95+
9096
public MaintainResource() {
9197

9298
}
@@ -121,19 +127,19 @@ public Response deprecateDataModel(final String jsonObjectString, @Context final
121127

122128
final BasicNeo4jProcessor processor = new DataModelNeo4jProcessor(database, tx, namespaceIndex, prefixedDataModelUri);
123129

124-
final RelationshipDeprecator statementDeprecator = new DataModelNeo4jDeprecator(processor, true, prefixedDataModelUri);
130+
final RelationshipDeprecator dataModelDeprecator = new DataModelNeo4jDeprecator(processor, true, prefixedDataModelUri);
125131

126-
statementDeprecator.work();
132+
dataModelDeprecator.work();
127133

128-
final int relationshipsDeprecated = statementDeprecator.getRelationshipsDeprecated();
134+
final int relationshipsDeprecated = dataModelDeprecator.getRelationshipsDeprecated();
129135

130136
if (relationshipsDeprecated > 0) {
131137

132138
// update data model version only when some statements are deprecated the DB
133-
statementDeprecator.getVersionHandler().updateLatestVersion();
139+
dataModelDeprecator.getVersionHandler().updateLatestVersion();
134140
}
135141

136-
statementDeprecator.closeTransaction();
142+
dataModelDeprecator.closeTransaction();
137143

138144
LOG.info("deprecated '{}' relationships in data model '{}' ('{}') in graph db", relationshipsDeprecated, dataModelUri, prefixedDataModelUri);
139145

@@ -144,6 +150,57 @@ public Response deprecateDataModel(final String jsonObjectString, @Context final
144150
return Response.ok(result, MediaType.APPLICATION_JSON_TYPE).build();
145151
}
146152

153+
@POST
154+
@Path("/deprecate/records")
155+
@Consumes(MediaType.APPLICATION_JSON)
156+
@Produces(MediaType.APPLICATION_JSON)
157+
public Response deprecateRecords(final String jsonObjectString, @Context final GraphDatabaseService database) throws DMPGraphException {
158+
159+
MaintainResource.LOG.info("try to deprecate records in a data model in graph db");
160+
161+
final ObjectNode requestJSON = deserializeJSON(jsonObjectString, DEPRECATE_RECORDS_TYPE);
162+
163+
final String dataModelUri = requestJSON.get(DMPStatics.DATA_MODEL_URI_IDENTIFIER).asText();
164+
165+
final Collection<String> recordURIs = getRecordURIs(requestJSON);
166+
167+
final TransactionHandler tx = new Neo4jTransactionHandler(database);
168+
final NamespaceIndex namespaceIndex = new NamespaceIndex(database, tx);
169+
170+
final String prefixedDataModelUri = namespaceIndex.createPrefixedURI(dataModelUri);
171+
172+
final Collection<String> prefixedRecordURIs = prefixRecordURIs(recordURIs, namespaceIndex);
173+
174+
MaintainResource.LOG.info("try to deprecate '{}' records in data model '{}' ('{}') in graph db", prefixedRecordURIs.size(), dataModelUri,
175+
prefixedDataModelUri);
176+
177+
final BasicNeo4jProcessor processor = new DataModelNeo4jProcessor(database, tx, namespaceIndex, prefixedDataModelUri);
178+
179+
final RelationshipDeprecator recordsDeprecator = new RecordsNeo4jDeprecator(processor, true, prefixedDataModelUri, prefixedRecordURIs);
180+
181+
recordsDeprecator.work();
182+
183+
final int relationshipsDeprecated = recordsDeprecator.getRelationshipsDeprecated();
184+
185+
if (relationshipsDeprecated > 0) {
186+
187+
// update data model version only when some statements are deprecated the DB
188+
recordsDeprecator.getVersionHandler().updateLatestVersion();
189+
}
190+
191+
recordsDeprecator.closeTransaction();
192+
193+
LOG.info("deprecated '{}' records with '{}' relationships in data model '{}' ('{}') in graph db", prefixedRecordURIs.size(),
194+
relationshipsDeprecated, dataModelUri, prefixedDataModelUri);
195+
196+
final ObjectNode resultJSON = simpleObjectMapper.createObjectNode();
197+
resultJSON.put("deprecated", relationshipsDeprecated);
198+
final String result = serializeJSON(resultJSON, DEPRECATE_DATA_MODEL_TYPE);
199+
200+
return Response.ok(result, MediaType.APPLICATION_JSON_TYPE).build();
201+
202+
}
203+
147204
/**
148205
* note utilise this endpoint with care, because it cleans your complete db!
149206
*
@@ -512,4 +569,34 @@ private void initPrefixes(final GraphDatabaseService database) throws DMPGraphEx
512569

513570
MaintainResource.LOG.debug("finished initialising namespaces index");
514571
}
572+
573+
private Collection<String> getRecordURIs(final ObjectNode json) {
574+
575+
final JsonNode recordsNode = json.get(DMPStatics.RECORDS_IDENTIFIER);
576+
577+
final ArrayList<String> recordURIs = new ArrayList<>();
578+
579+
for (final JsonNode recordNode : recordsNode) {
580+
581+
final String recordURI = recordNode.asText();
582+
583+
recordURIs.add(recordURI);
584+
}
585+
586+
return recordURIs;
587+
}
588+
589+
private Collection<String> prefixRecordURIs(final Collection<String> recordURIs, final NamespaceIndex namespaceIndex) throws DMPGraphException {
590+
591+
final ArrayList<String> prefixedRecordURIs = new ArrayList<>();
592+
593+
for (final String recordURI : recordURIs) {
594+
595+
final String prefixedRecordURI = namespaceIndex.createPrefixedURI(recordURI);
596+
597+
prefixedRecordURIs.add(prefixedRecordURI);
598+
}
599+
600+
return prefixedRecordURIs;
601+
}
515602
}

0 commit comments

Comments
 (0)