|
16 | 16 |
|
17 | 17 | import jakarta.data.exceptions.EmptyResultException; |
18 | 18 | import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; |
| 19 | +import org.apache.tinkerpop.gremlin.structure.Direction; |
| 20 | +import org.apache.tinkerpop.gremlin.structure.Edge; |
19 | 21 | import org.apache.tinkerpop.gremlin.structure.Graph; |
20 | 22 | import org.apache.tinkerpop.gremlin.structure.Vertex; |
21 | 23 | import org.eclipse.jnosql.communication.CommunicationException; |
|
26 | 28 | import org.eclipse.jnosql.communication.semistructured.SelectQuery; |
27 | 29 |
|
28 | 30 | import java.time.Duration; |
| 31 | +import java.util.HashMap; |
29 | 32 | import java.util.Iterator; |
30 | 33 | import java.util.Map; |
31 | 34 | import java.util.Objects; |
@@ -173,21 +176,97 @@ public void close() { |
173 | 176 |
|
174 | 177 | @Override |
175 | 178 | public CommunicationEdge edge(CommunicationEntity source, String label, CommunicationEntity target, Map<String, Object> properties) { |
176 | | - return null; |
| 179 | + Objects.requireNonNull(source, "source is required"); |
| 180 | + Objects.requireNonNull(target, "target is required"); |
| 181 | + Objects.requireNonNull(label, "label is required"); |
| 182 | + |
| 183 | + Vertex sourceVertex = findOrCreateVertex(source); |
| 184 | + |
| 185 | + Vertex targetVertex = findOrCreateVertex(target); |
| 186 | + |
| 187 | + var edge = sourceVertex.addEdge(label, targetVertex); |
| 188 | + properties.forEach(edge::property); |
| 189 | + |
| 190 | + GraphTransactionUtil.transaction(graph); |
| 191 | + |
| 192 | + return new TinkerpopCommunicationEdge(edge.id(), source, target, label, properties); |
177 | 193 | } |
178 | 194 |
|
179 | 195 | @Override |
180 | 196 | public void remove(CommunicationEntity source, String label, CommunicationEntity target) { |
| 197 | + Objects.requireNonNull(source, "source is required"); |
| 198 | + Objects.requireNonNull(target, "target is required"); |
| 199 | + Objects.requireNonNull(label, "label is required"); |
| 200 | + |
| 201 | + Vertex sourceVertex = findVertexById(source.find(ID_PROPERTY) |
| 202 | + .orElseThrow(() -> new CommunicationException("Source entity must have an ID"))) |
| 203 | + .orElseThrow(() -> new EmptyResultException("Source entity not found"))); |
181 | 204 |
|
| 205 | + Vertex targetVertex = findVertexById(target.find(ID_PROPERTY) |
| 206 | + .orElseThrow(() -> new CommunicationException("Target entity must have an ID"))) |
| 207 | + .orElseThrow(() -> new EmptyResultException("Target entity not found"))); |
| 208 | + |
| 209 | + Iterator<Edge> edges = sourceVertex.edges(Direction.OUT, label); |
| 210 | + while (edges.hasNext()) { |
| 211 | + Edge edge = edges.next(); |
| 212 | + if (edge.inVertex().id().equals(targetVertex.id())) { |
| 213 | + edge.remove(); |
| 214 | + } |
| 215 | + } |
| 216 | + |
| 217 | + GraphTransactionUtil.transaction(graph); |
182 | 218 | } |
183 | 219 |
|
184 | 220 | @Override |
185 | 221 | public <K> void deleteEdge(K id) { |
| 222 | + Objects.requireNonNull(id, "The id is required"); |
| 223 | + |
| 224 | + var traversal = graph.traversal().E(id); |
| 225 | + if (!traversal.hasNext()) { |
| 226 | + throw new EmptyResultException("Edge not found for ID: " + id); |
| 227 | + } |
186 | 228 |
|
| 229 | + traversal.next().remove(); |
| 230 | + GraphTransactionUtil.transaction(graph); |
187 | 231 | } |
188 | 232 |
|
189 | 233 | @Override |
190 | 234 | public <K> Optional<CommunicationEdge> findEdgeById(K id) { |
191 | | - return Optional.empty(); |
| 235 | + Objects.requireNonNull(id, "The id is required"); |
| 236 | + |
| 237 | + var traversal = graph.traversal().E(id); |
| 238 | + if (!traversal.hasNext()) { |
| 239 | + return Optional.empty(); |
| 240 | + } |
| 241 | + |
| 242 | + var edge = traversal.next(); |
| 243 | + var source = CommunicationEntity.of(edge.outVertex().label()); |
| 244 | + source.add(ID_PROPERTY, edge.outVertex().id()); |
| 245 | + |
| 246 | + var target = CommunicationEntity.of(edge.inVertex().label()); |
| 247 | + target.add(ID_PROPERTY, edge.inVertex().id()); |
| 248 | + |
| 249 | + Map<String, Object> properties = new HashMap<>(); |
| 250 | + edge.properties().forEachRemaining(p -> properties.put(p.key(), p.value())); |
| 251 | + |
| 252 | + return Optional.of(new TinkerpopCommunicationEdge(id, source, target, edge.label(), properties)); |
| 253 | + } |
| 254 | + |
| 255 | + private Vertex findOrCreateVertex(CommunicationEntity entity) { |
| 256 | + return entity.find(ID_PROPERTY) |
| 257 | + .flatMap(id -> findVertexById(id.get())) |
| 258 | + .orElseGet(() -> { |
| 259 | + var newVertex = graph.addVertex(entity.name()); |
| 260 | + entity.elements().forEach(e -> newVertex.property(e.name(), ValueUtil.convert(e.value()))); |
| 261 | + newVertex.property(ID_PROPERTY, newVertex.id()); |
| 262 | + entity.add(ID_PROPERTY, newVertex.id()); |
| 263 | + return newVertex; |
| 264 | + }); |
192 | 265 | } |
| 266 | + |
| 267 | + private Optional<Vertex> findVertexById(Object id) { |
| 268 | + Iterator<Vertex> vertices = graph.vertices(id); |
| 269 | + return vertices.hasNext() ? Optional.of(vertices.next()) : Optional.empty(); |
| 270 | + } |
| 271 | + |
193 | 272 | } |
0 commit comments