1111 * Contributors:
1212 *
1313 * Otavio Santana
14+ * Michele Rastelli
1415 */
1516package org .eclipse .jnosql .databases .arangodb .communication ;
1617
1718import com .arangodb .ArangoCursor ;
1819import com .arangodb .ArangoDB ;
19- import com .arangodb .entity . BaseDocument ;
20+ import com .arangodb .ArangoDatabase ;
2021import com .arangodb .entity .DocumentCreateEntity ;
2122import com .arangodb .entity .DocumentUpdateEntity ;
2223import jakarta .json .JsonObject ;
24+ import org .eclipse .jnosql .communication .graph .CommunicationEdge ;
2325import org .eclipse .jnosql .communication .semistructured .CommunicationEntity ;
2426import org .eclipse .jnosql .communication .semistructured .DeleteQuery ;
2527import org .eclipse .jnosql .communication .semistructured .Element ;
2628import org .eclipse .jnosql .communication .semistructured .SelectQuery ;
2729
2830import java .time .Duration ;
2931import java .util .Map ;
32+ import java .util .Objects ;
3033import java .util .Optional ;
3134import java .util .logging .Level ;
3235import java .util .logging .Logger ;
@@ -45,28 +48,27 @@ class DefaultArangoDBDocumentManager implements ArangoDBDocumentManager {
4548 public static final String KEY = "_key" ;
4649 public static final String ID = "_id" ;
4750 public static final String REV = "_rev" ;
51+ public static final String FROM = "_from" ;
52+ public static final String TO = "_to" ;
4853
49- private final String database ;
50-
51- private final ArangoDB arangoDB ;
54+ private final ArangoDatabase db ;
5255
5356 DefaultArangoDBDocumentManager (String database , ArangoDB arangoDB ) {
54- this .database = database ;
55- this .arangoDB = arangoDB ;
57+ db = arangoDB .db (database );
5658 }
5759
5860 @ Override
5961 public String name () {
60- return database ;
62+ return db . name () ;
6163 }
6264
6365 @ Override
64- public CommunicationEntity insert (CommunicationEntity entity ) {
66+ public CommunicationEntity insert (CommunicationEntity entity ) {
6567 requireNonNull (entity , "entity is required" );
6668 String collectionName = entity .name ();
6769 checkCollection (collectionName );
6870 JsonObject jsonObject = ArangoDBUtil .toJsonObject (entity );
69- DocumentCreateEntity <Void > arangoDocument = arangoDB . db ( database )
71+ DocumentCreateEntity <Void > arangoDocument = db
7072 .collection (collectionName ).insertDocument (jsonObject );
7173 updateEntity (entity , arangoDocument .getKey (), arangoDocument .getId (), arangoDocument .getRev ());
7274 return entity ;
@@ -77,22 +79,10 @@ public CommunicationEntity update(CommunicationEntity entity) {
7779 requireNonNull (entity , "entity is required" );
7880 String collectionName = entity .name ();
7981 checkCollection (collectionName );
80- Optional <String > keyElement = entity .find (KEY , String .class );
81- Optional <String > idElement = entity .find (ID , String .class );
82- if (keyElement .isEmpty () && idElement .isEmpty ()) {
83- throw new IllegalArgumentException ("To update an entity is necessary to have either " + KEY + " or " + ID );
84- }
85- var key = keyElement .orElseGet (() -> {
86- String id = idElement .orElseThrow ();
87- var elements = id .split ("/" );
88- if (elements .length == 2 ) {
89- return elements [1 ];
90- } else {
91- return elements [0 ];
92- }
93- });
9482 JsonObject jsonObject = ArangoDBUtil .toJsonObject (entity );
95- DocumentUpdateEntity <Void > arangoDocument = arangoDB .db (database )
83+ String key = extractKey (entity ).orElseThrow (() ->
84+ new IllegalArgumentException ("To update an entity is necessary to have either " + KEY + " or " + ID ));
85+ DocumentUpdateEntity <Void > arangoDocument = db
9686 .collection (collectionName ).updateDocument (key , jsonObject );
9787 updateEntity (entity , arangoDocument .getKey (), arangoDocument .getId (), arangoDocument .getRev ());
9888 return entity ;
@@ -114,13 +104,12 @@ public void delete(DeleteQuery query) {
114104 checkCollection (query .name ());
115105 if (query .condition ().isEmpty ()) {
116106 AQLQueryResult delete = QueryAQLConverter .delete (query );
117- arangoDB . db ( database ) .query (delete .query (), BaseDocument .class );
107+ db .query (delete .query (), Void .class );
118108 return ;
119109 }
120110
121111 AQLQueryResult delete = QueryAQLConverter .delete (query );
122- arangoDB .db (database ).query (delete .query (), BaseDocument .class , delete .values (),
123- null );
112+ db .query (delete .query (), Void .class , delete .values (), null );
124113 } catch (com .arangodb .ArangoDBException exception ) {
125114 if (ERROR_ARANGO_DATA_SOURCE_NOT_FOUND .equals (exception .getErrorNum ())) {
126115 LOGGER .log (Level .FINEST , exception , () -> "An error to run query, that is related to delete " +
@@ -137,7 +126,7 @@ public Stream<CommunicationEntity> select(SelectQuery query) throws NullPointerE
137126 checkCollection (query .name ());
138127 AQLQueryResult result = QueryAQLConverter .select (query );
139128 LOGGER .finest ("Executing AQL: " + result .query ());
140- ArangoCursor <JsonObject > documents = arangoDB . db ( database ) .query (result .query (),
129+ ArangoCursor <JsonObject > documents = db .query (result .query (),
141130 JsonObject .class ,
142131 result .values (), null );
143132
@@ -149,7 +138,7 @@ public Stream<CommunicationEntity> select(SelectQuery query) throws NullPointerE
149138 public long count (String documentCollection ) {
150139 requireNonNull (documentCollection , "document collection is required" );
151140 String aql = "RETURN LENGTH(" + documentCollection + ")" ;
152- ArangoCursor <Object > query = arangoDB . db ( database ) .query (aql , Object .class , emptyMap (), null );
141+ ArangoCursor <Object > query = db .query (aql , Object .class , emptyMap (), null );
153142 return StreamSupport .stream (query .spliterator (), false ).findFirst ().map (Number .class ::cast )
154143 .map (Number ::longValue ).orElse (0L );
155144 }
@@ -159,7 +148,7 @@ public long count(String documentCollection) {
159148 public Stream <CommunicationEntity > aql (String query , Map <String , Object > params ) throws NullPointerException {
160149 requireNonNull (query , "query is required" );
161150 requireNonNull (params , "values is required" );
162- ArangoCursor <JsonObject > result = arangoDB . db ( database ) .query (query , JsonObject .class , params , null );
151+ ArangoCursor <JsonObject > result = db .query (query , JsonObject .class , params , null );
163152 return StreamSupport .stream (result .spliterator (), false )
164153 .map (ArangoDBUtil ::toEntity );
165154 }
@@ -169,27 +158,30 @@ public <T> Stream<T> aql(String query, Map<String, Object> params, Class<T> type
169158 requireNonNull (query , "query is required" );
170159 requireNonNull (params , "values is required" );
171160 requireNonNull (type , "typeClass is required" );
172- ArangoCursor <T > result = arangoDB . db ( database ) .query (query , type , params , null );
161+ ArangoCursor <T > result = db .query (query , type , params , null );
173162 return StreamSupport .stream (result .spliterator (), false );
174163 }
175164
176165 @ Override
177166 public <T > Stream <T > aql (String query , Class <T > type ) {
178167 requireNonNull (query , "query is required" );
179168 requireNonNull (type , "typeClass is required" );
180- ArangoCursor <T > result = arangoDB .db (database ).query (query , type , emptyMap (), null );
181- return StreamSupport .stream (result .spliterator (), false );
169+ return db .query (query , type , emptyMap (), null ).stream ();
182170 }
183171
184172
185173 @ Override
186174 public void close () {
187- arangoDB .shutdown ();
175+ db . arango () .shutdown ();
188176 }
189177
190178
191179 private void checkCollection (String collectionName ) {
192- ArangoDBUtil .checkCollection (database , arangoDB , collectionName );
180+ ArangoDBUtil .checkCollection (db .name (), db .arango (), collectionName );
181+ }
182+
183+ private void checkEdgeCollection (String collectionName ) {
184+ ArangoDBUtil .checkEdgeCollection (db .name (), db .arango (), collectionName );
193185 }
194186
195187 @ Override
@@ -216,7 +208,7 @@ public Iterable<CommunicationEntity> insert(Iterable<CommunicationEntity> entiti
216208
217209 @ Override
218210 public ArangoDB getArangoDB () {
219- return arangoDB ;
211+ return db . arango () ;
220212 }
221213
222214 private void updateEntity (CommunicationEntity entity , String key , String id , String rev ) {
@@ -225,4 +217,72 @@ private void updateEntity(CommunicationEntity entity, String key, String id, Str
225217 entity .add (Element .of (REV , rev ));
226218 }
227219
220+ @ Override
221+ public CommunicationEdge edge (CommunicationEntity source , String label , CommunicationEntity target , Map <String , Object > properties ) {
222+ requireNonNull (source , "Source entity is required" );
223+ requireNonNull (target , "Target entity is required" );
224+ requireNonNull (label , "Relationship type is required" );
225+ requireNonNull (properties , "Properties map is required" );
226+
227+ checkCollection (source .name ());
228+ checkCollection (target .name ());
229+ checkEdgeCollection (label );
230+
231+ source = ensureEntityExists (source );
232+ target = ensureEntityExists (target );
233+
234+ CommunicationEntity entity = CommunicationEntity .of (label );
235+ entity .add (FROM , extractId (source ));
236+ entity .add (TO , extractId (target ));
237+ properties .forEach (entity ::add );
238+
239+ JsonObject jsonObject = ArangoDBUtil .toJsonObject (entity );
240+ String key = db .collection (label ).insertDocument (jsonObject ).getKey ();
241+ return new ArangoDBCommunicationEdge (key , source , target , label , properties );
242+ }
243+
244+ private CommunicationEntity ensureEntityExists (CommunicationEntity entity ) {
245+ return extractKey (entity )
246+ .filter (key -> db .collection (entity .name ()).documentExists (key ))
247+ .map (id -> entity )
248+ .orElseGet (() -> insert (entity ));
249+ }
250+
251+ @ Override
252+ public void remove (CommunicationEntity source , String label , CommunicationEntity target ) {
253+ throw new UnsupportedOperationException ("TODO" );
254+ }
255+
256+ @ Override
257+ public <K > void deleteEdge (K id ) {
258+ throw new UnsupportedOperationException ("TODO" );
259+ }
260+
261+ @ Override
262+ public <K > Optional <CommunicationEdge > findEdgeById (K id ) {
263+ throw new UnsupportedOperationException ("TODO" );
264+ }
265+
266+ private Optional <String > extractId (CommunicationEntity entity ) {
267+ Objects .requireNonNull (entity , "entity is required" );
268+ Objects .requireNonNull (entity .name (), "entity name is required" );
269+ if (entity .name ().isEmpty ()) {
270+ throw new IllegalArgumentException ("entity name cannot be empty" );
271+ }
272+ return extractKey (entity ).map (key -> entity .name () + "/" + key );
273+ }
274+
275+ private Optional <String > extractKey (CommunicationEntity entity ) {
276+ return entity .find (KEY , String .class ).or (() ->
277+ entity .find (ID , String .class )
278+ .map (id -> {
279+ var elements = id .split ("/" );
280+ if (elements .length == 2 ) {
281+ return elements [1 ];
282+ } else {
283+ return elements [0 ];
284+ }
285+ }));
286+ }
287+
228288}
0 commit comments