88import java .lang .reflect .Modifier ;
99import java .net .URLDecoder ;
1010import java .nio .charset .StandardCharsets ;
11+ import java .util .ArrayList ;
1112import java .util .Base64 ;
1213import java .util .Collections ;
1314import java .util .HashMap ;
15+ import java .util .List ;
1416import java .util .Map ;
1517import java .util .Map .Entry ;
1618import java .util .Objects ;
@@ -176,12 +178,41 @@ protected CompletionStage<Iterable<CapabilityProvider<Invocable>>> handleSpec(
176178
177179 // Type
178180 if (invocableRequirement .type () != null ) {
179- return classLoaderCS .thenCompose (classLoader -> handleType (
180- requirement ,
181- invocableRequirement ,
182- classLoader ,
183- loader ,
184- progressMonitor ));
181+ if (invocableRequirement .bind () == null ) {
182+ return classLoaderCS .thenCompose (classLoader -> handleType (
183+ requirement ,
184+ invocableRequirement ,
185+ classLoader ,
186+ Collections .emptyList (),
187+ loader ,
188+ progressMonitor ));
189+ }
190+
191+ CompletionStage <List <Invocable >> bindingsCS = CompletableFuture .completedStage (new ArrayList <>());
192+ for (String binding : invocableRequirement .bind ()) {
193+ URI bindingURI = requirement .uriHandler ().normalize (URI .createURI (binding ));
194+ CompletionStage <Object > bindingRequirementCS = classLoaderCS .thenApply (classLoader -> {
195+ URIInvocableRequirement req = new URIInvocableRequirement (bindingURI , requirement .uriHandler (), classLoader , null );
196+ return ServiceCapabilityFactory .createRequirement (Invocable .class , null , req );
197+ });
198+ CompletionStage <Invocable > bindingCS = bindingRequirementCS .thenCompose (bindingRequirement -> {
199+ return loader .loadOne (bindingRequirement , progressMonitor );
200+ });
201+ bindingsCS = bindingsCS .thenCombine (bindingCS , (bindings , value ) -> {
202+ bindings .add (value );
203+ return bindings ;
204+ });
205+ }
206+
207+ record ClassLoaderAndBindingsListRecord (ClassLoader classLoader , List <Invocable > bindings ) {};
208+ CompletionStage <ClassLoaderAndBindingsListRecord > classLoaderAndBindingsListCS = classLoaderCS .thenCombine (bindingsCS , ClassLoaderAndBindingsListRecord ::new );
209+ return classLoaderAndBindingsListCS .thenCompose (classLoaderAndBindingsMap -> handleType (
210+ requirement ,
211+ invocableRequirement ,
212+ classLoaderAndBindingsMap .classLoader (),
213+ classLoaderAndBindingsMap .bindings (),
214+ loader ,
215+ progressMonitor ));
185216 }
186217
187218 // Script
@@ -212,13 +243,13 @@ protected CompletionStage<Iterable<CapabilityProvider<Invocable>>> handleSpec(
212243 });
213244 }
214245
215- record ClassLoaderAndBindingsRecord (ClassLoader classLoader , Map <String ,Invocable > bindings ) {};
216- CompletionStage <ClassLoaderAndBindingsRecord > classLoaderAndBindingsCS = classLoaderCS .thenCombine (bindingsCS , ClassLoaderAndBindingsRecord ::new );
217- return classLoaderAndBindingsCS .thenCompose (classLoaderAndBindings -> handleScript (
246+ record ClassLoaderAndBindingsMapRecord (ClassLoader classLoader , Map <String ,Invocable > bindings ) {};
247+ CompletionStage <ClassLoaderAndBindingsMapRecord > classLoaderAndBindingsMapCS = classLoaderCS .thenCombine (bindingsCS , ClassLoaderAndBindingsMapRecord ::new );
248+ return classLoaderAndBindingsMapCS .thenCompose (classLoaderAndBindingsMap -> handleScript (
218249 requirement ,
219250 invocableRequirement ,
220- classLoaderAndBindings .classLoader (),
221- classLoaderAndBindings .bindings (),
251+ classLoaderAndBindingsMap .classLoader (),
252+ classLoaderAndBindingsMap .bindings (),
222253 loader ,
223254 progressMonitor ));
224255 }
@@ -370,6 +401,7 @@ protected CompletionStage<Iterable<CapabilityProvider<Invocable>>> handleType(
370401 URIInvocableRequirement requirement ,
371402 InvocableRequirement spec ,
372403 ClassLoader classLoader ,
404+ List <Invocable > bindings ,
373405 Loader loader ,
374406 ProgressMonitor progressMonitor ) {
375407 String typeName = spec .type ();
@@ -396,16 +428,13 @@ protected CompletionStage<Iterable<CapabilityProvider<Invocable>>> handleType(
396428 result = Invocable .of (invocables );
397429 }
398430
399- CompletionStage <Invocable > resultCS = CompletableFuture .completedStage (result .bind (loader , progressMonitor ));
400- if (spec .bind () != null ) {
401- for (int i = 0 ; i < spec .bind ().length ; ++i ) {
402- URI bindingURI = requirement .uriHandler ().normalize (URI .createURI (spec .bind ()[i ]));
403- URIInvocableRequirement bindingRequirement = new URIInvocableRequirement (bindingURI , requirement .uriHandler (), classLoader , null ); // No modules yet
404- CompletionStage <Object > bindingCS = loader .loadOne (bindingRequirement , progressMonitor );
405- resultCS = resultCS .thenCombine (bindingCS , (r ,b ) -> r .bind (b ));
406- }
431+ result = result .bind (loader , progressMonitor );
432+
433+ for (Invocable toBind : bindings ) {
434+ Object value = toBind .invoke ();
435+ result = result .bind (value );
407436 }
408- return wrapCompletionStage ( resultCS );
437+ return wrap ( result );
409438 } catch (ClassNotFoundException e ) {
410439 return wrapError (e );
411440 }
@@ -523,10 +552,11 @@ protected Object loadValue(Class<?> type, byte[] data) {
523552 if (String .class == type ) {
524553 return new String (data );
525554 }
526-
527- // TODO - numbers, date, ...
528-
529- throw new UnsupportedOperationException ();
555+ Object result = DefaultConverter .INSTANCE .convert (data , type );
556+ if (result == null ) {
557+ result = DefaultConverter .INSTANCE .convert (new String (data ), type );
558+ }
559+ return result ;
530560 }
531561
532562}
0 commit comments