15
15
import static org .eclipse .ditto .base .model .common .ConditionChecker .checkNotNull ;
16
16
17
17
import java .util .ArrayList ;
18
- import java .util .Collection ;
19
18
import java .util .List ;
20
19
import java .util .Optional ;
21
20
import java .util .Set ;
24
23
import java .util .concurrent .CompletionStage ;
25
24
import java .util .concurrent .Executor ;
26
25
import java .util .stream .Collectors ;
27
- import java .util .stream .StreamSupport ;
28
26
29
27
import javax .annotation .Nullable ;
30
28
42
40
import org .eclipse .ditto .internal .utils .tracing .DittoTracing ;
43
41
import org .eclipse .ditto .internal .utils .tracing .span .SpanOperationName ;
44
42
import org .eclipse .ditto .json .JsonArray ;
43
+ import org .eclipse .ditto .json .JsonCollectors ;
45
44
import org .eclipse .ditto .json .JsonFactory ;
46
45
import org .eclipse .ditto .json .JsonFieldSelector ;
47
- import org .eclipse .ditto .json .JsonKey ;
48
46
import org .eclipse .ditto .json .JsonObject ;
49
47
import org .eclipse .ditto .json .JsonObjectBuilder ;
50
48
import org .eclipse .ditto .json .JsonPointer ;
@@ -174,44 +172,13 @@ public CompletionStage<JsonObject> retrievePartialThing(final ThingId thingId,
174
172
return performPreDefinedExtraFieldsOptimization (
175
173
thingId , jsonFieldSelector , dittoHeaders , signalHeaders , thingEvents
176
174
);
175
+ } else {
176
+ // as second step only return what was originally requested as fields:
177
+ final var cachingParameters =
178
+ new CachingParameters (jsonFieldSelector , thingEvents , true , 0 );
179
+ return doRetrievePartialThing (thingId , dittoHeaders , null , cachingParameters )
180
+ .thenApply (jsonObject -> applyJsonFieldSelector (jsonObject , jsonFieldSelector ));
177
181
}
178
- // as second step only return what was originally requested as fields:
179
- final var cachingParameters =
180
- new CachingParameters (jsonFieldSelector , thingEvents , true , 0 );
181
-
182
- return doRetrievePartialThing (thingId , dittoHeaders , null , cachingParameters )
183
- .thenApply (jsonObject -> applyJsonFieldSelector (jsonObject , jsonFieldSelector ));
184
- }
185
-
186
- /**
187
- * Retrieve parts of a thing.
188
- *
189
- * @param thingId ID of the thing.
190
- * @param jsonFieldSelector the selected fields of the thing.
191
- * @param dittoHeaders Ditto headers containing authorization information.
192
- * @param concernedSignals the Signals which caused that this partial thing retrieval was triggered
193
- * (e.g. a {@code ThingEvent})
194
- * @param minAcceptableSeqNr minimum sequence number of the concerned signals to not invalidate the cache.
195
- * @return future that completes with the parts of a thing or fails with an error.
196
- */
197
- @ SuppressWarnings ({"java:S1612" , "unused" })
198
- public CompletionStage <JsonObject > retrievePartialThing (final EntityId thingId ,
199
- final JsonFieldSelector jsonFieldSelector ,
200
- final DittoHeaders dittoHeaders ,
201
- final Collection <? extends Signal <?>> concernedSignals ,
202
- final long minAcceptableSeqNr ) {
203
-
204
- final List <ThingEvent <?>> thingEvents = concernedSignals .stream ()
205
- .filter (signal -> signal instanceof ThingEvent && !Signal .isChannelLive (signal ))
206
- .map (signal -> (ThingEvent <?>) signal )
207
- .collect (Collectors .toList ());
208
-
209
- // as second step only return what was originally requested as fields:
210
- final var cachingParameters =
211
- new CachingParameters (jsonFieldSelector , thingEvents , true , minAcceptableSeqNr );
212
-
213
- return doRetrievePartialThing (thingId , dittoHeaders , null , cachingParameters )
214
- .thenApply (jsonObject -> applyJsonFieldSelector (jsonObject , jsonFieldSelector ));
215
182
}
216
183
217
184
private CompletionStage <JsonObject > performPreDefinedExtraFieldsOptimization (final ThingId thingId ,
@@ -230,14 +197,17 @@ private CompletionStage<JsonObject> performPreDefinedExtraFieldsOptimization(fin
230
197
231
198
final JsonObject preDefinedExtraFields =
232
199
JsonObject .of (signalHeaders .get (DittoHeaderDefinition .PRE_DEFINED_EXTRA_FIELDS_OBJECT .getKey ()));
233
- final CompletionStage < JsonObject > filteredPreDefinedExtraFieldsReadGranted =
200
+ final JsonObject filteredPreDefinedExtraFieldsReadGranted =
234
201
filterPreDefinedExtraReadGrantedObject (jsonFieldSelector , dittoHeaders , signalHeaders ,
235
202
preDefinedExtraFields );
236
203
237
204
final boolean allExtraFieldsPresent =
238
205
allConfiguredPredefinedExtraFields .containsAll (jsonFieldSelector .getPointers ());
239
206
if (allExtraFieldsPresent ) {
240
- return filteredPreDefinedExtraFieldsReadGranted ;
207
+ LOGGER .withCorrelationId (dittoHeaders )
208
+ .debug ("All asked for extraFields for thing <{}> we present in pre-defined fields, " +
209
+ "skipping cache retrieval: <{}>" , thingId , jsonFieldSelector );
210
+ return CompletableFuture .completedStage (filteredPreDefinedExtraFieldsReadGranted );
241
211
} else {
242
212
// optimization to only fetch extra fields which were not pre-defined
243
213
final List <JsonPointer > missingFieldsPointers = new ArrayList <>(jsonFieldSelector .getPointers ());
@@ -246,46 +216,51 @@ private CompletionStage<JsonObject> performPreDefinedExtraFieldsOptimization(fin
246
216
final var cachingParameters =
247
217
new CachingParameters (missingFieldsSelector , thingEvents , true , 0 );
248
218
219
+ LOGGER .withCorrelationId (dittoHeaders )
220
+ .debug ("Fetching non pre-defined extraFields for thing <{}>: <{}>" , thingId , missingFieldsPointers );
221
+
249
222
return doRetrievePartialThing (thingId , dittoHeaders , null , cachingParameters )
250
- .thenCompose (jsonObject -> filteredPreDefinedExtraFieldsReadGranted
251
- .thenApply (preDefinedObject ->
252
- JsonFactory .newObject ( // merge
253
- applyJsonFieldSelector (jsonObject , missingFieldsSelector ),
254
- preDefinedObject
255
- )
223
+ .thenApply (jsonObject ->
224
+ JsonFactory .newObject ( // merge
225
+ applyJsonFieldSelector (jsonObject , missingFieldsSelector ),
226
+ filteredPreDefinedExtraFieldsReadGranted
256
227
)
257
228
);
258
229
}
259
230
}
260
231
261
- private static CompletionStage < JsonObject > filterPreDefinedExtraReadGrantedObject (
232
+ private static JsonObject filterPreDefinedExtraReadGrantedObject (
262
233
final JsonFieldSelector jsonFieldSelector ,
263
- final DittoHeaders dittoHeaders , final DittoHeaders signalHeaders , final JsonObject preDefinedExtraFields ) {
234
+ final DittoHeaders dittoHeaders ,
235
+ final DittoHeaders signalHeaders ,
236
+ final JsonObject preDefinedExtraFields
237
+ ) {
264
238
final JsonObject preDefinedExtraFieldsReadGrant = JsonObject .of (
265
239
signalHeaders .get (DittoHeaderDefinition .PRE_DEFINED_EXTRA_FIELDS_READ_GRANT_OBJECT .getKey ())
266
240
);
267
241
final JsonFieldSelector grantedReadJsonFieldSelector = filterAskedForFieldSelectorToGrantedFields (
268
- jsonFieldSelector , preDefinedExtraFieldsReadGrant ,
242
+ jsonFieldSelector ,
243
+ preDefinedExtraFieldsReadGrant ,
269
244
dittoHeaders .getAuthorizationContext ().getAuthorizationSubjectIds ()
270
245
);
271
- return CompletableFuture . completedStage ( preDefinedExtraFields .get (grantedReadJsonFieldSelector ) );
246
+ return preDefinedExtraFields .get (grantedReadJsonFieldSelector );
272
247
}
273
248
274
249
private static JsonFieldSelector filterAskedForFieldSelectorToGrantedFields (
275
250
final JsonFieldSelector jsonFieldSelector ,
276
251
final JsonObject preDefinedExtraFieldsReadGrant ,
277
- final List <String > authorizationSubjectIds )
278
- {
279
- final List <JsonPointer > allowedPointers = StreamSupport .stream (jsonFieldSelector . spliterator (), false )
280
- . filter ( pointer -> preDefinedExtraFieldsReadGrant .getValue ( JsonKey . of ( pointer . toString ()) )
281
- . filter ( JsonValue :: isArray )
282
- . map ( JsonValue :: asArray )
283
- . filter ( readGrantArray -> readGrantArray .stream ()
284
- . filter ( JsonValue :: isString )
285
- . map ( JsonValue :: asString )
286
- . anyMatch ( authorizationSubjectIds :: contains )
287
- ). isPresent ( )
288
- ) .toList ();
252
+ final List <String > authorizationSubjectIds
253
+ ) {
254
+ final List <JsonValue > authSubjects = authorizationSubjectIds .stream (). map ( JsonValue :: of ). toList ();
255
+ final JsonObject scopedPreDefinedExtraFieldsReadGrant = preDefinedExtraFieldsReadGrant .stream ( )
256
+ . filter ( field -> field . getValue (). asArray (). stream (). anyMatch ( authSubjects :: contains ) )
257
+ . collect ( JsonCollectors . fieldsToObject ());
258
+ final List < JsonPointer > allowedPointers = scopedPreDefinedExtraFieldsReadGrant . getKeys () .stream ()
259
+ . filter ( key -> jsonFieldSelector . getPointers (). stream ( )
260
+ . anyMatch ( p -> key . toString (). startsWith ( p . toString ()) )
261
+ )
262
+ . map ( key -> JsonPointer . of ( key . toString (). substring ( 1 )) )
263
+ .toList ();
289
264
return JsonFactory .newFieldSelector (allowedPointers );
290
265
}
291
266
0 commit comments