24
24
import java .util .concurrent .CompletableFuture ;
25
25
import java .util .concurrent .CompletionStage ;
26
26
import java .util .function .Consumer ;
27
+ import java .util .function .Function ;
27
28
28
29
import org .neo4j .driver .internal .handlers .PullAllResponseHandler ;
29
30
import org .neo4j .driver .internal .handlers .RunResponseHandler ;
30
31
import org .neo4j .driver .v1 .Record ;
31
32
import org .neo4j .driver .v1 .StatementResultCursor ;
33
+ import org .neo4j .driver .v1 .exceptions .NoSuchRecordException ;
32
34
import org .neo4j .driver .v1 .summary .ResultSummary ;
33
35
34
36
import static java .util .Objects .requireNonNull ;
@@ -85,18 +87,54 @@ public CompletionStage<Record> peekAsync()
85
87
}
86
88
87
89
@ Override
88
- public CompletionStage <Void > forEachAsync ( Consumer <Record > action )
90
+ public CompletionStage <Record > singleAsync ()
91
+ {
92
+ return nextAsync ().thenCompose ( firstRecord ->
93
+ {
94
+ if ( firstRecord == null )
95
+ {
96
+ throw new NoSuchRecordException ( "Cannot retrieve a single record, because this cursor is empty." );
97
+ }
98
+ return nextAsync ().thenApply ( secondRecord ->
99
+ {
100
+ if ( secondRecord != null )
101
+ {
102
+ throw new NoSuchRecordException ( "Expected a cursor with a single record, but this cursor " +
103
+ "contains at least one more. Ensure your query returns only " +
104
+ "one record." );
105
+ }
106
+ return firstRecord ;
107
+ } );
108
+ } );
109
+ }
110
+
111
+ @ Override
112
+ public CompletionStage <ResultSummary > consumeAsync ()
113
+ {
114
+ return forEachAsync ( record ->
115
+ {
116
+ } );
117
+ }
118
+
119
+ @ Override
120
+ public CompletionStage <ResultSummary > forEachAsync ( Consumer <Record > action )
89
121
{
90
122
CompletableFuture <Void > resultFuture = new CompletableFuture <>();
91
123
internalForEachAsync ( action , resultFuture );
92
- return resultFuture ;
124
+ return resultFuture . thenCompose ( ignore -> summaryAsync () ) ;
93
125
}
94
126
95
127
@ Override
96
128
public CompletionStage <List <Record >> listAsync ()
97
129
{
98
- CompletableFuture <List <Record >> resultFuture = new CompletableFuture <>();
99
- internalListAsync ( new ArrayList <>(), resultFuture );
130
+ return listAsync ( Function .identity () );
131
+ }
132
+
133
+ @ Override
134
+ public <T > CompletionStage <List <T >> listAsync ( Function <Record ,T > mapFunction )
135
+ {
136
+ CompletableFuture <List <T >> resultFuture = new CompletableFuture <>();
137
+ internalListAsync ( new ArrayList <>(), resultFuture , mapFunction );
100
138
return resultFuture ;
101
139
}
102
140
@@ -114,7 +152,15 @@ private void internalForEachAsync( Consumer<Record> action, CompletableFuture<Vo
114
152
}
115
153
else if ( record != null )
116
154
{
117
- action .accept ( record );
155
+ try
156
+ {
157
+ action .accept ( record );
158
+ }
159
+ catch ( Throwable actionError )
160
+ {
161
+ resultFuture .completeExceptionally ( actionError );
162
+ return ;
163
+ }
118
164
internalForEachAsync ( action , resultFuture );
119
165
}
120
166
else
@@ -124,7 +170,8 @@ else if ( record != null )
124
170
} );
125
171
}
126
172
127
- private void internalListAsync ( List <Record > records , CompletableFuture <List <Record >> resultFuture )
173
+ private <T > void internalListAsync ( List <T > result , CompletableFuture <List <T >> resultFuture ,
174
+ Function <Record ,T > mapFunction )
128
175
{
129
176
CompletionStage <Record > recordFuture = nextAsync ();
130
177
@@ -138,12 +185,22 @@ private void internalListAsync( List<Record> records, CompletableFuture<List<Rec
138
185
}
139
186
else if ( record != null )
140
187
{
141
- records .add ( record );
142
- internalListAsync ( records , resultFuture );
188
+ T value ;
189
+ try
190
+ {
191
+ value = mapFunction .apply ( record );
192
+ }
193
+ catch ( Throwable mapError )
194
+ {
195
+ resultFuture .completeExceptionally ( mapError );
196
+ return ;
197
+ }
198
+ result .add ( value );
199
+ internalListAsync ( result , resultFuture , mapFunction );
143
200
}
144
201
else
145
202
{
146
- resultFuture .complete ( records );
203
+ resultFuture .complete ( result );
147
204
}
148
205
} );
149
206
}
0 commit comments