Modified: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/BundleDependencyBuilderImpl.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/BundleDependencyBuilderImpl.java?rev=1724333&r1=1724332&r2=1724333&view=diff ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/BundleDependencyBuilderImpl.java (original) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/BundleDependencyBuilderImpl.java Tue Jan 12 22:45:36 2016 @@ -13,11 +13,14 @@ import org.apache.felix.dm.BundleDepende import org.apache.felix.dm.Component; import org.apache.felix.dm.DependencyManager; import org.apache.felix.dm.builder.lambda.BundleDependencyBuilder; -import org.apache.felix.dm.builder.lambda.Functions.Consumer; -import org.apache.felix.dm.builder.lambda.Functions.Consumer2; +import org.apache.felix.dm.builder.lambda.Functions.CbBundle; +import org.apache.felix.dm.builder.lambda.Functions.CbComponentBundle; +import org.apache.felix.dm.builder.lambda.Functions.CbTypeBundle; +import org.apache.felix.dm.builder.lambda.Functions.CbTypeComponentBundle; import org.osgi.framework.Bundle; -public class BundleDependencyBuilderImpl implements BundleDependencyBuilder { +@SuppressWarnings("unchecked") +public class BundleDependencyBuilderImpl<T> implements BundleDependencyBuilder<T> { private String m_added; private String m_changed; private String m_removed; @@ -33,7 +36,7 @@ public class BundleDependencyBuilderImpl private String m_propagateMethod; private Supplier<Dictionary<?, ?>> m_propagateSupplier; private final Component m_component; - + /** * This interface (lambda) is called when we want to invoke a method reference. the lambda is called with all necessary dependency * informations. @@ -67,192 +70,229 @@ public class BundleDependencyBuilderImpl } @Override - public BundleDependencyBuilder onAdd(String callback) { - return callbacks(callback, null, null); - } + public BundleDependencyBuilder<T> autoConfig(boolean autoConfig) { + m_autoConfig = autoConfig; + m_autoConfigInvoked = true; + return this; + } @Override - public BundleDependencyBuilder onChange(String callback) { - return callbacks(null, callback, null); - } + public BundleDependencyBuilder<T> autoConfig() { + autoConfig(true); + return this; + } @Override - public BundleDependencyBuilder onRemove(String callback) { - return callbacks(null, null, callback); - } + public BundleDependencyBuilder<T> required(boolean required) { + m_required = required; + return this; + } @Override - public BundleDependencyBuilder callbacks(String added, String removed) { - return callbacks(added, null, removed); - } + public BundleDependencyBuilder<T> required() { + required(true); + return this; + } @Override - public BundleDependencyBuilder callbacks(String added, String changed, String removed) { - requiresNoMethodRefs(); - m_added = added != null ? added : m_added; - m_changed = changed != null ? changed : m_changed; - m_removed = removed != null ? removed : m_removed; - if (! m_autoConfigInvoked) m_autoConfig = false; - return this; - } + public BundleDependencyBuilder<T> bundle(Bundle bundle) { + m_bundle = bundle; + return this; + } - @Override - public BundleDependencyBuilder callbacks(Object instance, String added, String changed, String removed) { - callbacks(added, changed, removed); - m_instance = instance; - return this; - } + @Override + public BundleDependencyBuilder<T> filter(String filter) throws IllegalArgumentException { + m_filter = filter; + return this; + } - @Override - public BundleDependencyBuilder onAdd(Consumer<Bundle> add) { - return setCallbackRef("add", (instance, component, bundle) -> add.accept(bundle)); - } + @Override + public BundleDependencyBuilder<T> mask(int mask) { + m_stateMask = mask; + return this; + } - @Override - public BundleDependencyBuilder onAdd(Consumer2<Component, Bundle> add) { - return setCallbackRef("add", (instance, component, bundle) -> add.accept(component, bundle)); - } + @Override + public BundleDependencyBuilder<T> propagate(boolean propagate) { + m_propagate = propagate; + return this; + } - @SuppressWarnings("unchecked") - @Override - public <I> BundleDependencyBuilder onAdd(InstanceBundle<I> add) { - String type = Helpers.getLambdaGenericType(add); - return setComponentInstanceCallbackRef("add", type, - (inst, component, bundle) -> add.call((I) inst, bundle)); - } + @Override + public BundleDependencyBuilder<T> propagate() { + propagate(true); + return this; + } - @SuppressWarnings("unchecked") - @Override - public <I> BundleDependencyBuilder onAdd(InstanceComponentBundle<I> add) { - String type = Helpers.getLambdaGenericType(add); - return setComponentInstanceCallbackRef("add", type, - (inst, component, bundle) -> add.call((I) inst, component, bundle)); - } - - @Override - public BundleDependencyBuilder onChange(Consumer<Bundle> add) { - return setCallbackRef("change", (instance, component, bundle) -> add.accept(bundle)); - } + @Override + public BundleDependencyBuilder<T> propagate(Object instance, String method) { + if (m_propagateSupplier != null || m_propagate) throw new IllegalStateException("Propagate callback already set."); + Objects.nonNull(method); + Objects.nonNull(instance); + m_propagateInstance = instance; + m_propagateMethod = method; + return this; + } - @Override - public BundleDependencyBuilder onChange(Consumer2<Component, Bundle> change) { - return setCallbackRef("change", (instance, component, bundle) -> change.accept(component, bundle)); - } + @Override + public BundleDependencyBuilder<T> propagate(Supplier<Dictionary<?, ?>> instance) { + if (m_propagateInstance != null || m_propagate) throw new IllegalStateException("Propagate callback already set."); + m_propagateSupplier = instance; + return this; + } + + @Override + public BundleDependencyBuilder<T> cb(String add) { + cb(add, null, null); + return this; + } + + @Override + public BundleDependencyBuilder<T> cb(String add, String remove) { + cb(add, null, remove); + return this; + } + + public BundleDependencyBuilder cb(String added, String changed, String removed) { + requiresNoMethodRefs(); + m_added = added != null ? added : m_added; + m_changed = changed != null ? changed : m_changed; + m_removed = removed != null ? removed : m_removed; + if (! m_autoConfigInvoked) m_autoConfig = false; + return this; + } - @SuppressWarnings("unchecked") - @Override - public <I> BundleDependencyBuilder onChange(InstanceBundle<I> change) { - String type = Helpers.getLambdaGenericType(change); - return setComponentInstanceCallbackRef("change", type, - (inst, component, bundle) -> change.call((I) inst, bundle)); - } + @Override + public BundleDependencyBuilder<T> cbInst(Object instance) { + m_instance = instance; + return this; + } - @SuppressWarnings("unchecked") - @Override - public <I> BundleDependencyBuilder onChange(InstanceComponentBundle<I> change) { - String type = Helpers.getLambdaGenericType(change); - return setComponentInstanceCallbackRef("change", type, - (inst, component, bundle) -> change.call((I) inst, component, bundle)); - } - - @Override - public BundleDependencyBuilder onRemove(Consumer<Bundle> remove) { - return setCallbackRef("remove", (instance, component, bundle) -> remove.accept(bundle)); - } + @Override + public BundleDependencyBuilder<T> cb(CbTypeBundle<T> add) { + return cb(add, null, null); + } - @Override - public BundleDependencyBuilder onRemove(Consumer2<Component, Bundle> remove) { - return setCallbackRef("remove", (instance, component, bundle) -> remove.accept(component, bundle)); - } + @Override + public BundleDependencyBuilder<T> cb(CbTypeBundle<T> add, CbTypeBundle<T> remove) { + return cb(add, null, remove); + } - @SuppressWarnings("unchecked") - @Override - public <I> BundleDependencyBuilder onRemove(InstanceBundle<I> remove) { - String type = Helpers.getLambdaGenericType(remove); - return setComponentInstanceCallbackRef("remove", type, - (inst, component, bundle) -> remove.call((I) inst, bundle)); - } + @Override + public BundleDependencyBuilder<T> cb(CbTypeBundle<T> add, CbTypeBundle<T> change, CbTypeBundle<T> remove) { + if (add != null) { + setComponentCallbackRef("add", + (inst, component, bundle) -> add.accept ((T) inst, bundle)); + } + if (change != null) { + setComponentCallbackRef("change", + (inst, component, bundle) -> change.accept ((T) inst, bundle)); + } + if (remove != null) { + setComponentCallbackRef("remove", + (inst, component, bundle) -> remove.accept ((T) inst, bundle)); + } + return this; + } - @SuppressWarnings("unchecked") - @Override - public <I> BundleDependencyBuilder onRemove(InstanceComponentBundle<I> remove) { - String type = Helpers.getLambdaGenericType(remove); - return setComponentInstanceCallbackRef("remove", type, - (inst, component, bundle) -> remove.call((I) inst, component, bundle)); - } - - @Override - public BundleDependencyBuilder autoConfig(boolean autoConfig) { - m_autoConfig = autoConfig; - m_autoConfigInvoked = true; - return this; - } + @Override + public BundleDependencyBuilder<T> cb(CbTypeComponentBundle<T> add) { + return cb(add, null, null); + } + + @Override + public BundleDependencyBuilder<T> cb(CbTypeComponentBundle<T> add, CbTypeComponentBundle<T> remove) { + return cb(add, null, remove); + } - @Override - public BundleDependencyBuilder autoConfig() { - autoConfig(true); - return this; - } + @Override + public BundleDependencyBuilder<T> cb(CbTypeComponentBundle<T> add, CbTypeComponentBundle<T> change, CbTypeComponentBundle<T> remove) { + if (add != null) { + setComponentCallbackRef("add", (inst, component, bundle) -> add.accept ((T) inst, component, bundle)); + } + if (change != null) { + setComponentCallbackRef("change", (inst, component, bundle) -> change.accept ((T) inst, component, bundle)); + } + if (remove != null) { + setComponentCallbackRef("remove", (inst, component, bundle) -> remove.accept ((T) inst, component, bundle)); + } + return this; + } - @Override - public BundleDependencyBuilder required(boolean required) { - m_required = required; - return this; - } + @Override + public BundleDependencyBuilder<T> cb(CbBundle add) { + return cb (add, null, null); + } - @Override - public BundleDependencyBuilder required() { - required(true); - return this; - } + @Override + public BundleDependencyBuilder<T> cb(CbBundle add, CbBundle remove) { + return cb (add, null, remove); + } - @Override - public BundleDependencyBuilder bundle(Bundle bundle) { - m_bundle = bundle; - return this; - } + @Override + public BundleDependencyBuilder<T> cb(CbBundle add, CbBundle change, CbBundle remove) { + if (add != null) setCallbackRef("add", (inst, component, bundle) -> add.accept(bundle)); + if (change != null) setCallbackRef("change", (inst, component, bundle) -> change.accept(bundle)); + if (remove != null) setCallbackRef("remove", (inst, component, bundle) -> remove.accept(bundle)); + return this; + } - @Override - public BundleDependencyBuilder filter(String filter) throws IllegalArgumentException { - m_filter = filter; - return this; - } + @Override + public BundleDependencyBuilder<T> cb(CbComponentBundle add) { + return cb(add, null, null); + } - @Override - public BundleDependencyBuilder mask(int mask) { - m_stateMask = mask; - return this; - } + @Override + public BundleDependencyBuilder<T> cb(CbComponentBundle add, CbComponentBundle remove) { + return cb(add, null, remove); + } - @Override - public BundleDependencyBuilder propagate(boolean propagate) { - m_propagate = propagate; - return this; - } + @Override + public BundleDependencyBuilder<T> cb(CbComponentBundle add, CbComponentBundle change, CbComponentBundle remove) { + if (add != null) setCallbackRef("add", (inst, component, bundle) -> add.accept(component, bundle)); + if (change != null) setCallbackRef("change", (inst, component, bundle) -> change.accept(component, bundle)); + if (remove != null) setCallbackRef("remove", (inst, component, bundle) -> remove.accept(component, bundle)); + return this; + } - @Override - public BundleDependencyBuilder propagate() { - propagate(true); - return this; - } + @Override + public <U> BundleDependencyBuilder<T> compositeCb(CbTypeBundle<U> add) { + return compositeCb(add, null, null); + } - @Override - public BundleDependencyBuilder propagate(Object instance, String method) { - if (m_propagateSupplier != null || m_propagate) throw new IllegalStateException("Propagate callback already set."); - Objects.nonNull(method); - Objects.nonNull(instance); - m_propagateInstance = instance; - m_propagateMethod = method; - return this; - } + @Override + public <U> BundleDependencyBuilder<T> compositeCb(CbTypeBundle<U> add, CbTypeBundle<U> remove) { + return compositeCb(add, null, remove); + } + + @Override + public <U> BundleDependencyBuilder<T> compositeCb(CbTypeBundle<U> add, CbTypeBundle<U> change, CbTypeBundle<U> remove) { + Class<U> type = Helpers.getLambdaGenericType(add, 0); + if (add != null) setCompositeCallbackRef("add", type, (inst, component, bundle) -> add.accept ((U) inst, bundle)); + if (change != null) setCompositeCallbackRef("change", type, (inst, component, bundle) -> change.accept ((U) inst, bundle)); + if (remove != null) setCompositeCallbackRef("remove", type, (inst, component, bundle) -> remove.accept ((U) inst, bundle)); + return this; + } + + @Override + public <U> BundleDependencyBuilder<T> compositeCb(CbTypeComponentBundle<U> add) { + return compositeCb(add, null, null); + } + + @Override + public <U> BundleDependencyBuilder<T> compositeCb(CbTypeComponentBundle<U> add, CbTypeComponentBundle<U> remove) { + return compositeCb(add, null, remove); + } + + @Override + public <U> BundleDependencyBuilder<T> compositeCb(CbTypeComponentBundle<U> add, CbTypeComponentBundle<U> change, CbTypeComponentBundle<U> remove) { + Class<U> type = Helpers.getLambdaGenericType(add, 0); + if (add != null) setCompositeCallbackRef("add", type, (inst, component, bundle) -> add.accept ((U) inst, component, bundle)); + if (change != null) setCompositeCallbackRef("change", type, (inst, component, bundle) -> change.accept ((U) inst, component, bundle)); + if (remove != null) setCompositeCallbackRef("remove", type, (inst, component, bundle) -> remove.accept ((U) inst, component, bundle)); + return this; + } - @Override - public BundleDependencyBuilder propagate(Supplier<Dictionary<?, ?>> instance) { - if (m_propagateInstance != null || m_propagate) throw new IllegalStateException("Propagate callback already set."); - m_propagateSupplier = instance; - return this; - } - @Override public BundleDependency build() { DependencyManager dm = m_component.getDependencyManager(); @@ -291,7 +331,7 @@ public class BundleDependencyBuilderImpl return dep; } - private <I> BundleDependencyBuilder setCallbackRef(String cb, MethodRef<I> ref) { + private <U> BundleDependencyBuilder<T> setCallbackRef(String cb, MethodRef<U> ref) { requiresNoStringCallbacks(); if (! m_autoConfigInvoked) m_autoConfig = false; List<MethodRef<Object>> list = m_refs.computeIfAbsent(cb, l -> new ArrayList<>()); @@ -299,21 +339,31 @@ public class BundleDependencyBuilderImpl return this; } - @SuppressWarnings("unchecked") - private <I> BundleDependencyBuilder setComponentInstanceCallbackRef(String cb, String type, MethodRef<I> ref) { + private BundleDependencyBuilder<T> setComponentCallbackRef(String cb, MethodRef<T> ref) { requiresNoStringCallbacks(); if (! m_autoConfigInvoked) m_autoConfig = false; List<MethodRef<Object>> list = m_refs.computeIfAbsent(cb, l -> new ArrayList<>()); list.add((instance, component, bundle) -> { - Stream.of(component.getInstances()).forEach(inst -> { - if (Helpers.getClassName(inst).equals(type)) { - ref.accept((I) inst, component, bundle); - } - }); + Object inst = component.getInstance(); + ref.accept((T) inst, component, bundle); }); return this; } + private <I> BundleDependencyBuilder<T> setCompositeCallbackRef(String cb, Class<I> type, MethodRef<I> ref) { + requiresNoStringCallbacks(); + if (! m_autoConfigInvoked) m_autoConfig = false; + List<MethodRef<Object>> list = m_refs.computeIfAbsent(cb, l -> new ArrayList<>()); + list.add((instance, component, bundle) -> { + Stream.of(component.getInstances()).forEach(inst -> { + if (Helpers.getClass(inst).equals(type)) { + ref.accept((I) inst, component, bundle); + } + }); + }); + return this; + } + @SuppressWarnings("unused") private Object createCallbackInstance() { Object cb = null;
Modified: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/CompletableFutureDependencyImpl.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/CompletableFutureDependencyImpl.java?rev=1724333&r1=1724332&r2=1724333&view=diff ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/CompletableFutureDependencyImpl.java (original) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/CompletableFutureDependencyImpl.java Tue Jan 12 22:45:36 2016 @@ -6,8 +6,8 @@ import java.util.stream.Stream; import org.apache.felix.dm.Component; import org.apache.felix.dm.Dependency; -import org.apache.felix.dm.builder.lambda.Functions.Consumer; -import org.apache.felix.dm.builder.lambda.Functions.Consumer2; +import org.apache.felix.dm.builder.lambda.Functions.CbFuture; +import org.apache.felix.dm.builder.lambda.Functions.CbTypeFuture; import org.apache.felix.dm.builder.lambda.FutureDependencyBuilder; import org.apache.felix.dm.context.AbstractDependency; import org.apache.felix.dm.context.DependencyContext; @@ -15,17 +15,17 @@ import org.apache.felix.dm.context.Event import org.apache.felix.dm.context.EventType; import org.osgi.service.log.LogService; -public class CompletableFutureDependencyImpl<T> extends AbstractDependency<CompletableFutureDependencyImpl<T>> - implements FutureDependencyBuilder<T> { +public class CompletableFutureDependencyImpl<T, F> extends AbstractDependency<CompletableFutureDependencyImpl<T, F>> implements FutureDependencyBuilder<T, F> { - private final CompletableFuture<T> m_future; - private Consumer<? super T> m_accept; - private Consumer2<Object, ? super T> m_accept2; + private final CompletableFuture<F> m_future; private Component m_comp; private boolean m_async; private Executor m_exec; - - public CompletableFutureDependencyImpl(Component c, CompletableFuture<T> future) { + private CbFuture<F> m_accept = (future) -> {}; + private CbTypeFuture<Object, F> m_accept2; + private Class<?> m_accept2Type; + + public CompletableFutureDependencyImpl(Component c, CompletableFuture<F> future) { super.setRequired(true); m_future = future; m_comp = c; @@ -37,7 +37,7 @@ public class CompletableFutureDependency * @param prototype * the existing PathDependency. */ - public CompletableFutureDependencyImpl(Component component, CompletableFutureDependencyImpl<T> prototype) { + public CompletableFutureDependencyImpl(Component component, CompletableFutureDependencyImpl<T, F> prototype) { super(prototype); m_future = prototype.m_future; m_comp = component; @@ -48,50 +48,68 @@ public class CompletableFutureDependency return this; } - @SuppressWarnings("unchecked") @Override - public FutureDependencyBuilder<T> thenAccept(Consumer<? super T> consumer) { - m_accept = (Consumer<T>) consumer; + public FutureDependencyBuilder<T, F> cb(CbFuture<? super F> consumer) { + cb(consumer, false); return this; } + + @Override + public FutureDependencyBuilder<T, F> cb(CbFuture<? super F> consumer, boolean async) { + m_accept = m_accept.andThen(future -> consumer.accept(future)); + m_async = async; + return this; + } + + @Override + public FutureDependencyBuilder<T, F> cb(CbFuture<? super F> consumer, Executor executor) { + cb(consumer, true /* async */); + m_exec = executor; + return this; + } + - @SuppressWarnings("unchecked") @Override - public <I> FutureDependencyBuilder<T> thenAccept(Consumer2<I, ? super T> consumer) { - m_accept2 = (Consumer2<Object, T>) consumer; + public FutureDependencyBuilder<T, F> cb(CbTypeFuture<T, ? super F> consumer) { + cb(consumer, false); return this; } @SuppressWarnings("unchecked") - @Override - public FutureDependencyBuilder<T> thenAcceptAsync(Consumer<? super T> consumer) { - m_accept = (Consumer<T>) consumer; - m_async = true; + @Override + public FutureDependencyBuilder<T, F> cb(CbTypeFuture<T, ? super F> consumer, boolean async) { + m_accept2 = (instance, result) -> consumer.accept((T) instance, result); + m_async = async; return this; } - @Override - public <I> FutureDependencyBuilder<T> thenAcceptAsync(Consumer2<I, ? super T> consumer) { - thenAccept(consumer); - m_async = true; - return this; - } - @SuppressWarnings("unchecked") @Override - public FutureDependencyBuilder<T> thenAcceptAsync(Consumer<? super T> consumer, Executor executor) { - m_accept = (Consumer<T>) consumer; - m_async = true; + public FutureDependencyBuilder<T, F> cb(CbTypeFuture<T, ? super F> consumer, Executor executor) { + cb(consumer, true /* async */); m_exec = executor; return this; } - @Override - public <I> FutureDependencyBuilder<T> thenAcceptAsync(Consumer2<I, ? super T> consumer, Executor executor) { - thenAccept(consumer); - m_async = true; - m_exec = executor; - return this; + public <C> FutureDependencyBuilder<T, F> compositeCb(CbTypeFuture<C, ? super F> consumer) { + compositeCb(consumer, false); + return this; + } + + @SuppressWarnings("unchecked") + @Override + public <C> FutureDependencyBuilder<T, F> compositeCb(CbTypeFuture<C, ? super F> consumer, boolean async) { + m_async = async; + m_accept2Type = Helpers.getLambdaGenericType(consumer, 0);; + m_accept2 = (instance, result) -> consumer.accept((C) instance, result); + return this; + } + + @Override + public <C> FutureDependencyBuilder<T, F> compositeCb(CbTypeFuture<C, ? super F> consumer, Executor executor) { + compositeCb(consumer, true /* async */); + m_exec = executor; + return this; } // ---------- DependencyContext interface ---------- @@ -116,7 +134,7 @@ public class CompletableFutureDependency @Override public DependencyContext createCopy() { - return new CompletableFutureDependencyImpl<T>(m_comp, this); + return new CompletableFutureDependencyImpl<T, F>(m_comp, this); } @Override @@ -144,33 +162,57 @@ public class CompletableFutureDependency public String getType() { return "future"; } + + /** + * Called by DM component implementation when all required dependencies are satisfied. + */ + @Override + public void invokeCallback(EventType type, Event ... events) { + try { + switch (type) { + case ADDED: + F result = events[0].getEvent(); + if (m_accept2 != null) { + if (m_accept2Type != null) { + // find the component instance that matches the given type + Object componentInstance = Stream.of(getComponentContext().getInstances()) + .filter(instance -> Helpers.getClass(instance).equals(m_accept2Type)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException( + "accept callback is not on one of the component instances: " + m_accept2 + " (type=" + m_accept2Type + ")")); + + m_accept2.accept(componentInstance, result); + } else { + // invoke a method in the main component instance that will handle the completed future. + m_accept2.accept(getComponentContext().getInstance(), result); + } + } else { + // Just invoke the Consumer with the completed future + m_accept.accept(result); + } + break; + + default: + break; + } + } catch (Throwable exc) { + super.getComponentContext().getLogger().log(LogService.LOG_ERROR, "completable future failed", exc); + } + } // ---------- Private methods ----------- - private void completed(T result, Throwable error) { + /** + * Triggers component activation when the future has completed. + * @param result + * @param error + */ + private void completed(F result, Throwable error) { if (error != null) { super.getComponentContext().getLogger().log(LogService.LOG_ERROR, "completable future failed", error); } else { - try { - if (m_accept != null) { - m_accept.accept(result); - } else if (m_accept2 != null) { - // If using a bi consumer, we need to find one of the component instance which type is compatible - // with the first type of the bi consumer method reference. - String type = Helpers.getLambdaGenericType(m_accept2); - Object componentInstance = Stream.of(getComponentContext().getInstances()) - .filter(instance -> Helpers.getClassName(instance).equals(type)) - .findFirst() - .orElseThrow(() -> new IllegalArgumentException("accept callback is not on one of the component instances: " + m_accept2 + " (type=" + type + ")")); - - m_accept2.accept(componentInstance, result); - } - m_component.handleEvent(this, EventType.ADDED, new Event("")); - } - - catch (Throwable exc) { - super.getComponentContext().getLogger().log(LogService.LOG_ERROR, "completable future failed", exc); - } + // Will trigger component activation (if other dependencies are satisfied), and our invokeCallback method will then be called. + m_component.handleEvent(this, EventType.ADDED, new Event(result)); } } } Modified: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/ComponentBuilderImpl.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/ComponentBuilderImpl.java?rev=1724333&r1=1724332&r2=1724333&view=diff ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/ComponentBuilderImpl.java (original) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/ComponentBuilderImpl.java Tue Jan 12 22:45:36 2016 @@ -9,6 +9,8 @@ import java.util.Map; import java.util.Objects; import java.util.Properties; import java.util.concurrent.CompletableFuture; +import java.util.function.BiConsumer; +import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Stream; @@ -20,13 +22,12 @@ import org.apache.felix.dm.builder.lambd import org.apache.felix.dm.builder.lambda.ComponentBuilder; import org.apache.felix.dm.builder.lambda.ConfigurationDependencyBuilder; import org.apache.felix.dm.builder.lambda.DependencyBuilder; -import org.apache.felix.dm.builder.lambda.Functions; -import org.apache.felix.dm.builder.lambda.Functions.Consumer; +import org.apache.felix.dm.builder.lambda.Functions.CbComponent; import org.apache.felix.dm.builder.lambda.Functions.FluentProperties; import org.apache.felix.dm.builder.lambda.FutureDependencyBuilder; import org.apache.felix.dm.builder.lambda.ServiceDependencyBuilder; -public class ComponentBuilderImpl implements ComponentBuilder<ComponentBuilderImpl> { +public class ComponentBuilderImpl<T> implements ComponentBuilder<T> { private final List<DependencyBuilder<?>> m_dependencyBuilders = new ArrayList<>(); private final Component m_component; private final boolean m_componentUpdated; @@ -49,37 +50,38 @@ public class ComponentBuilderImpl implem } @Override - public <T> ComponentBuilderImpl autoInject(Class<T> clazz, boolean autoConfig) { + public <U> ComponentBuilderImpl<T> autoInject(Class<U> clazz, boolean autoConfig) { m_component.setAutoConfig(clazz, autoConfig); return this; } @Override - public <T> ComponentBuilderImpl autoInject(Class<T> clazz, String instanceName) { + public <U> ComponentBuilderImpl<T> autoInject(Class<U> clazz, String instanceName) { m_component.setAutoConfig(clazz, instanceName); return this; } @Override - public ComponentBuilderImpl provides(Class<?>... ifaces) { + public ComponentBuilderImpl<T> provides(Class<?>... ifaces) { m_serviceNames = Stream.of(ifaces).map(c -> c.getName()).toArray(String[]::new); return this; } - public ComponentBuilderImpl provides(String... ifaces) { + @Override + public ComponentBuilderImpl<T> provides(String... ifaces) { m_serviceNames = ifaces; return this; } @SuppressWarnings("unchecked") @Override - public ComponentBuilderImpl properties(Dictionary<?, ?> properties) { + public ComponentBuilderImpl<T> properties(Dictionary<?, ?> properties) { m_properties = (Dictionary<Object, Object>) properties; return this; } @Override - public ComponentBuilderImpl properties(String name, Object value, Object ... rest) { + public ComponentBuilderImpl<T> properties(String name, Object value, Object ... rest) { Objects.nonNull(name); Objects.nonNull(value); Properties props = new Properties(); @@ -97,7 +99,7 @@ public class ComponentBuilderImpl implem } @Override - public ComponentBuilderImpl properties(FluentProperties ... properties) { + public ComponentBuilderImpl<T> properties(FluentProperties ... properties) { Dictionary<Object, Object> props = new Hashtable<>(); Stream.of(properties).forEach(property -> { String name = Helpers.getLambdaParameterName(property, 0); @@ -112,67 +114,43 @@ public class ComponentBuilderImpl implem } @Override - public ComponentBuilderImpl debug(String label) { + public ComponentBuilderImpl<T> debug(String label) { m_component.setDebug(label); return this; } @Override - public ComponentBuilderImpl autoAdd(boolean autoAdd) { + public ComponentBuilderImpl<T> autoAdd(boolean autoAdd) { m_autoAdd = autoAdd; return this; } - public boolean autoAdd() { - return m_autoAdd; + public ComponentBuilderImpl<T> autoAdd() { + m_autoAdd = true; + return this; } - @Override - public <T> ComponentBuilderImpl withService(Class<T> service) { - ServiceDependencyBuilder<T> dep = new ServiceDependencyBuilderImpl<T>(m_component, service); - m_dependencyBuilders.add(dep); - return this; - } - - @Override - public <T> ComponentBuilderImpl withService(Class<T> service, Consumer<ServiceDependencyBuilder<T>> consumer) { - ServiceDependencyBuilder<T> dep = new ServiceDependencyBuilderImpl<T>(m_component, service); - consumer.accept(dep); - m_dependencyBuilders.add(dep); - return this; - } - - @Override - public ComponentBuilderImpl withConfiguration(Consumer<ConfigurationDependencyBuilder> consumer) { - ConfigurationDependencyBuilder dep = new ConfigurationDependencyBuilderImpl(m_component); - consumer.accept(dep); - m_dependencyBuilders.add(dep); - return this; + public boolean isAutoAdd() { + return m_autoAdd; } - + + @SuppressWarnings("unchecked") @Override - public ComponentBuilderImpl withBundle(Consumer<BundleDependencyBuilder> consumer) { - BundleDependencyBuilder dep = new BundleDependencyBuilderImpl(m_component); - consumer.accept(dep); - m_dependencyBuilders.add(dep); - return this; - } - - public <U> ComponentBuilderImpl withFuture(CompletableFuture<U> future, Consumer<FutureDependencyBuilder<U>> consumer) { - FutureDependencyBuilder<U> dep = new CompletableFutureDependencyImpl<U>(m_component, future); - consumer.accept(dep); - m_dependencyBuilders.add(dep); - return this; + public <U> ComponentBuilder<U> impl(U instance) { + m_impl = instance; + return (ComponentBuilder<U>) this; } + @SuppressWarnings("unchecked") @Override - public ComponentBuilderImpl impl(Object instance) { - m_impl = instance; - return this; + public <U> ComponentBuilder<U> impl(Class<U> implClass) { + m_impl = implClass; + return (ComponentBuilder<U>) this; } + @SuppressWarnings("unchecked") @Override - public <T> ComponentBuilderImpl factory(Supplier<T> create) { + public <U> ComponentBuilder<U> factory(Supplier<U> create) { Objects.nonNull(create); m_factory = new Object() { @SuppressWarnings("unused") @@ -180,26 +158,28 @@ public class ComponentBuilderImpl implem return create.get(); } }; - return this; + return (ComponentBuilder<U>) this; } + @SuppressWarnings("unchecked") @Override - public <T> ComponentBuilderImpl factory(Supplier<T> supplier, Function<T, Object> create) { + public <U, V> ComponentBuilder<V> factory(Supplier<U> supplier, Function<U, V> create) { Objects.nonNull(supplier); Objects.nonNull(create); m_factory = new Object() { @SuppressWarnings("unused") public Object create() { - T factoryImpl = supplier.get(); + U factoryImpl = supplier.get(); return create.apply(factoryImpl); } }; - return this; + return (ComponentBuilder<V>) this; } + @SuppressWarnings("unchecked") @Override - public <T> ComponentBuilderImpl factory(Supplier<T> create, Supplier<Object[]> getComposite) { + public <U> ComponentBuilder<U> factory(Supplier<U> create, Supplier<Object[]> getComposite) { Objects.nonNull(create); Objects.nonNull(getComposite); @@ -215,17 +195,17 @@ public class ComponentBuilderImpl implem } }; m_factoryHasComposite = true; - return this; + return (ComponentBuilder<U>) this; } @Override - public <T> ComponentBuilderImpl factory(Supplier<T> factorySupplier, Function<T, Object> factoryCreate, Function<T, Object[]> factoryGetComposite) { + public <U, V> ComponentBuilder<V> factory(Supplier<U> factorySupplier, Function<U, V> factoryCreate, Function<U, Object[]> factoryGetComposite) { Objects.nonNull(factorySupplier); Objects.nonNull(factoryCreate); Objects.nonNull(factoryGetComposite); m_factory = new Object() { - T m_factoryInstance; + U m_factoryInstance; @SuppressWarnings("unused") public Object create() { @@ -239,67 +219,176 @@ public class ComponentBuilderImpl implem } }; m_factoryHasComposite = true; + return (ComponentBuilder<V>) this; + } + + @Override + public ComponentBuilderImpl<T> withService(Class<?> service, Class<?> ... services) { + doWithService(service); + for (Class<?> s : services) { + doWithService(s); + } + return this; + } + + private <U> void doWithService(Class<U> service) { + ServiceDependencyBuilder<U> dep = new ServiceDependencyBuilderImpl<>(m_component, service); + m_dependencyBuilders.add(dep); + } + + @Override + public <U> ComponentBuilderImpl<T> withService(Class<U> service, Consumer<ServiceDependencyBuilder<U>> consumer) { + ServiceDependencyBuilder<U> dep = new ServiceDependencyBuilderImpl<>(m_component, service); + consumer.accept(dep); + m_dependencyBuilders.add(dep); + return this; + } + + @Override + public ComponentBuilderImpl<T> withConfiguration(Consumer<ConfigurationDependencyBuilder<T>> consumer) { + ConfigurationDependencyBuilder<T> dep = new ConfigurationDependencyBuilderImpl<>(m_component); + consumer.accept(dep); + m_dependencyBuilders.add(dep); return this; } @Override - public ComponentBuilderImpl onInit(Runnable callback) { - return setLifecycleCallback("init", callback); + public ComponentBuilderImpl<T> withBundle(Consumer<BundleDependencyBuilder<T>> consumer) { + BundleDependencyBuilder<T> dep = new BundleDependencyBuilderImpl<>(m_component); + consumer.accept(dep); + m_dependencyBuilders.add(dep); + return this; + } + + @Override + public <V> ComponentBuilder<T> withFuture(CompletableFuture<V> future, Consumer<FutureDependencyBuilder<T, V>> consumer) { + FutureDependencyBuilder<T, V> dep = new CompletableFutureDependencyImpl<>(m_component, future); + consumer.accept(dep); + m_dependencyBuilders.add(dep); + return this; + } + + @Override + public final ComponentBuilderImpl<T> init(Consumer<T> callback) { + return setLifecycleComponentCallback("init", callback); + } + + @Override + public final ComponentBuilderImpl<T> init(BiConsumer<T, Component> callback) { + return setLifecycleComponentCallback("init", callback); + } + + @Override + public <U> ComponentBuilderImpl<T> init(Class<U> type, Consumer<U> callback) { + return setLifecycleCompositeCallback("init", type, callback); + } + + @Override + public <U> ComponentBuilderImpl<T> init(Class<U> type, BiConsumer<U, Component> callback) { + return setLifecycleCompositeCallback("init", type, callback); + } + + @Override + public ComponentBuilderImpl<T> init(Runnable callback) { + return setLifecycleCallback("init", callback); + } + + @Override + public final ComponentBuilderImpl<T> init(CbComponent callback) { + m_lfclCallbacks.put("init", component -> callback.accept(component)); + return this; } @Override - public final <T> ComponentBuilderImpl onInit(Functions.Consumer<T> callback) { - return setLifecycleCallback("init", callback); + public final ComponentBuilderImpl<T> start(Consumer<T> callback) { + return setLifecycleComponentCallback("start", callback); } @Override - public final <T> ComponentBuilderImpl onInit(Functions.Consumer2<T, Component> callback) { - return setLifecycleCallback("init", callback); + public final ComponentBuilderImpl<T> start(BiConsumer<T, Component> callback) { + return setLifecycleComponentCallback("start", callback); + } + + @Override + public <U> ComponentBuilderImpl<T> start(Class<U> type, Consumer<U> callback) { + return setLifecycleCompositeCallback("start", type, callback); + } + + @Override + public <U> ComponentBuilderImpl<T> start(Class<U> type, BiConsumer<U, Component> callback) { + return setLifecycleCompositeCallback("start", type, callback); } @Override - public ComponentBuilderImpl onStart(Runnable callback) { - return setLifecycleCallback("start", callback); + public ComponentBuilderImpl<T> start(Runnable callback) { + return setLifecycleCallback("start", callback); } @Override - public final <T> ComponentBuilderImpl onStart(Functions.Consumer<T> callback) { - return setLifecycleCallback("start", callback); + public final ComponentBuilderImpl<T> start(CbComponent callback) { + m_lfclCallbacks.put("start", component -> callback.accept(component)); + return this; + } + + @Override + public final ComponentBuilderImpl<T> stop(Consumer<T> callback) { + return setLifecycleComponentCallback("stop", callback); + } + + @Override + public final ComponentBuilderImpl<T> stop(BiConsumer<T, Component> callback) { + return setLifecycleComponentCallback("stop", callback); } @Override - public final <T> ComponentBuilderImpl onStart(Functions.Consumer2<T, Component> callback) { - return setLifecycleCallback("start", callback); + public <U> ComponentBuilderImpl<T> stop(Class<U> type, Consumer<U> callback) { + return setLifecycleCompositeCallback("stop", type, callback); + } + + @Override + public <U> ComponentBuilderImpl<T> stop(Class<U> type, BiConsumer<U, Component> callback) { + return setLifecycleCompositeCallback("stop", type, callback); } @Override - public ComponentBuilderImpl onStop(Runnable callback) { - return setLifecycleCallback("stop", callback); + public ComponentBuilderImpl stop(Runnable callback) { + return setLifecycleCallback("stop", callback); } @Override - public final <T> ComponentBuilderImpl onStop(Functions.Consumer<T> callback) { - return setLifecycleCallback("stop", callback); + public final ComponentBuilderImpl<T> stop(CbComponent callback) { + m_lfclCallbacks.put("stop", component -> callback.accept(component)); + return this; } @Override - public final <T> ComponentBuilderImpl onStop(Functions.Consumer2<T, Component> callback) { - return setLifecycleCallback("stop", callback); + public final ComponentBuilderImpl<T> destroy(Consumer<T> callback) { + return setLifecycleComponentCallback("destroy", callback); } @Override - public ComponentBuilderImpl onDestroy(Runnable callback) { - return setLifecycleCallback("destroy", callback); + public final ComponentBuilderImpl<T> destroy(BiConsumer<T, Component> callback) { + return setLifecycleComponentCallback("destroy", callback); + } + + public <U> ComponentBuilderImpl<T> destroy(Class<U> type, Consumer<U> callback) { + return setLifecycleCompositeCallback("destroy", type, callback); + } + + @Override + public <U> ComponentBuilderImpl<T> destroy(Class<U> type, BiConsumer<U, Component> callback) { + return setLifecycleCompositeCallback("destroy", type, callback); } @Override - public final <T> ComponentBuilderImpl onDestroy(Functions.Consumer<T> callback) { - return setLifecycleCallback("destroy", callback); + public ComponentBuilderImpl<T> destroy(Runnable callback) { + return setLifecycleCallback("destroy", callback); } @Override - public final <T> ComponentBuilderImpl onDestroy(Functions.Consumer2<T, Component> callback) { - return setLifecycleCallback("destroy", callback); + public final ComponentBuilderImpl<T> destroy(CbComponent callback) { + m_lfclCallbacks.put("destroy", component -> callback.accept(component)); + return this; } public Component build() { @@ -336,47 +425,51 @@ public class ComponentBuilderImpl implem return m_component; } - private ComponentBuilderImpl setLifecycleCallback(String method, Runnable callback) { - m_lfclCallbacks.put(method, component -> callback.run()); + @SuppressWarnings("unchecked") + private ComponentBuilderImpl<T> setLifecycleComponentCallback(String method, Consumer<T> callback) { + m_lfclCallbacks.put(method, component -> { + callback.accept((T) component.getInstance()); + }); return this; } - + @SuppressWarnings("unchecked") - private <T> ComponentBuilderImpl setLifecycleCallback(String method, Functions.Consumer<T> callback) { - m_lfclCallbacks.put(method, component -> { - String type = Helpers.getLambdaGenericType(callback); - // If the lambda generic type is Component, simply pass our component to the lambda's accept method. - // If the type is Object, it means that we are in front of a corner case where a Consumer is defined with a wildcard type. - // In this case, assume that the consumer accepts a Component. Notice that this may happen may using RxJava. - // Else if the type is another classe, then assumes that the lambda is a Consumer<T> where T is one of the component instance classes. - if (type.equals(Component.class.getName()) || type.equals(Object.class.getName())) { - callback.accept((T) component); - } else { - for (Object instance : component.getInstances()) { - if (Helpers.getClassName(instance).equals(type)) { - callback.accept((T) instance); - break; - } - } - } - }); + private ComponentBuilderImpl<T> setLifecycleComponentCallback(String method, BiConsumer<T, Component> callback) { + m_lfclCallbacks.put(method, component -> { + callback.accept((T) component.getInstance(), component); + }); return this; } - @SuppressWarnings("unchecked") - private <T> ComponentBuilderImpl setLifecycleCallback(String method, Functions.Consumer2<T, Component> callback) { - m_lfclCallbacks.put(method, component -> { - String type = Helpers.getLambdaGenericType(callback); - for (Object instance : component.getInstances()) { - if (Helpers.getClassName(instance).equals(type)) { - callback.accept((T) instance, component); - break; - } - } - }); + private <U> ComponentBuilderImpl<T> setLifecycleCompositeCallback(String method, Class<U> type, Consumer<U> callback) { + m_lfclCallbacks.put("init", component -> { + for (Object instance : component.getInstances()) { + if (Helpers.getClass(instance).equals(type)) { + callback.accept((U) instance); + break; + } + } + }); + return this; + } + + private <U> ComponentBuilderImpl<T> setLifecycleCompositeCallback(String method, Class<U> type, BiConsumer<U, Component> callback) { + m_lfclCallbacks.put("init", component -> { + for (Object instance : component.getInstances()) { + if (Helpers.getClass(instance).equals(type)) { + callback.accept((U) instance, component); + break; + } + } + }); return this; } + private ComponentBuilderImpl<T> setLifecycleCallback(String method, Runnable callback) { + m_lfclCallbacks.put(method, component -> callback.run()); + return this; + } + @SuppressWarnings("unused") private void setLifecycleMethodRefs() { Object cb = new Object() { Modified: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/ConfigurationDependencyBuilderImpl.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/ConfigurationDependencyBuilderImpl.java?rev=1724333&r1=1724332&r2=1724333&view=diff ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/ConfigurationDependencyBuilderImpl.java (original) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/ConfigurationDependencyBuilderImpl.java Tue Jan 12 22:45:36 2016 @@ -1,71 +1,100 @@ package org.apache.felix.dm.builder.lambda.impl; import java.util.Dictionary; -import java.util.HashMap; -import java.util.Map; import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Stream; +import java.util.function.BiConsumer; import org.apache.felix.dm.Component; import org.apache.felix.dm.ConfigurationDependency; import org.apache.felix.dm.builder.lambda.ConfigurationDependencyBuilder; -import org.apache.felix.dm.builder.lambda.Functions.Consumer; -import org.apache.felix.dm.builder.lambda.Functions.Consumer2; -import org.apache.felix.dm.context.ComponentContext; +import org.apache.felix.dm.builder.lambda.Functions.CbComponentDictionary; +import org.apache.felix.dm.builder.lambda.Functions.CbDictionary; +import org.apache.felix.dm.builder.lambda.Functions.CbTypeComponentDictionary; +import org.apache.felix.dm.builder.lambda.Functions.CbTypeDictionary; -public class ConfigurationDependencyBuilderImpl implements ConfigurationDependencyBuilder { +public class ConfigurationDependencyBuilderImpl<T> implements ConfigurationDependencyBuilder<T> { private String m_pid; private boolean m_propagate; - private Consumer<Dictionary<String, Object>> m_updatedConsumers = (props -> {}); - private boolean m_updatedConsumersSet; private final Component m_component; - - /** - * Mapping between component instances and corresponding "updated" method references. - */ - private final Map<String, Consumer2<?, Dictionary<String, Object>>> m_componentInstanceCbks = new HashMap<>(); + private String m_updateMethodName; + private Object m_updateCallbackInstance; + private boolean m_hasMethodRefs; + private boolean m_hasReflectionCallback; + private BiConsumer<Component, Dictionary<String, Object>> m_callbacks = (component, props) -> {}; + public ConfigurationDependencyBuilderImpl(Component component) { m_component = component; } @Override - public ConfigurationDependencyBuilder pid(String pid) { + public ConfigurationDependencyBuilder<T> pid(String pid) { m_pid = pid; return this; } @Override - public ConfigurationDependencyBuilder pid(Class<?> pidClass) { + public ConfigurationDependencyBuilder<T> pid(Class<?> pidClass) { m_pid = pidClass.getName(); return this; } @Override - public ConfigurationDependencyBuilder propagate() { + public ConfigurationDependencyBuilder<T> propagate() { m_propagate = true; return this; } @Override - public ConfigurationDependencyBuilder propagate(boolean propagate) { + public ConfigurationDependencyBuilder<T> propagate(boolean propagate) { m_propagate = propagate; return this; } - @Override - public <T> ConfigurationDependencyBuilder onUpdate(Consumer2<T, Dictionary<String, Object>> updatedRef) { - String instanceType = Helpers.getLambdaGenericType(updatedRef); - m_componentInstanceCbks.put(instanceType, updatedRef); + public ConfigurationDependencyBuilder<T> cb(String update) { + checkHasNoMethodRefs(); + m_hasReflectionCallback = true; + m_updateMethodName = update; + return this; + } + + public ConfigurationDependencyBuilder<T> cb(Object callbackInstance, String update) { + cb(update); + m_updateCallbackInstance = callbackInstance; return this; } @Override - public ConfigurationDependencyBuilder onUpdate(Consumer<Dictionary<String, Object>> updatedConsumer) { - m_updatedConsumers = m_updatedConsumers.andThen(props -> updatedConsumer.accept(props)); - m_updatedConsumersSet = true; - return null; + public ConfigurationDependencyBuilder<T> cb(CbTypeDictionary<T> callback) { + return addMethodRef((component, props) -> { callback.accept(component.getInstance(), props); }); + } + + @Override + public <U> ConfigurationDependencyBuilder<T> compositeCb(CbTypeDictionary<U> callback) { + Class<U> type = Helpers.getLambdaGenericType(callback, 0); + return addMethodRef((component, props) -> { + U instance = Helpers.findCompositeInstance(component, type); + callback.accept(instance, props); + }); + } + + @Override + public <U> ConfigurationDependencyBuilder<T> compositeCb(CbTypeComponentDictionary<U> callback) { + Class<U> type = Helpers.getLambdaGenericType(callback, 0); + return addMethodRef((component, props) -> { + U instance = Helpers.findCompositeInstance(component, type); + callback.accept(instance, component, props); + }); + } + + @Override + public ConfigurationDependencyBuilder<T> cb(CbDictionary callback) { + return addMethodRef((component, props) -> { callback.accept(props); }); + } + + @Override + public ConfigurationDependencyBuilder<T> cb(CbComponentDictionary callback) { + return addMethodRef((component, props) -> { callback.accept(component, props); }); } @Override @@ -74,30 +103,35 @@ public class ConfigurationDependencyBuil Objects.nonNull(m_pid); dep.setPid(m_pid); dep.setPropagate(m_propagate); - - if (m_componentInstanceCbks.size() > 0) { - // Some method refs have been added on some component instances. + if (m_updateMethodName != null) { + dep.setCallback(m_updateCallbackInstance, m_updateMethodName); + } else { dep.setCallback(new Object() { - @SuppressWarnings({ "unused", "unchecked" }) + @SuppressWarnings("unused") void updated(Component comp, Dictionary<String, Object> props) { - Stream.of(comp.getInstances()).forEach(instance -> { - Consumer2<Object, Dictionary<String, Object>> updatedRef = (Consumer2<Object, Dictionary<String, Object>>) m_componentInstanceCbks.get(Helpers.getClassName(instance)); - if (updatedRef != null) { - updatedRef.accept(instance, props); - } - }); - m_updatedConsumers.accept(props); + m_callbacks.accept(comp, props); } }, "updated", true /* we need component instances before updated is called */); - } else if (m_updatedConsumersSet) { - // Some consumers have been configured, call them on any updated properties. - dep.setCallback(new Object() { - @SuppressWarnings("unused") - void updated(Dictionary<String, Object> props) { - m_updatedConsumers.accept(props); - } - }, "updated"); - } + } return dep; } + + private ConfigurationDependencyBuilder<T> addMethodRef(BiConsumer<Component, Dictionary<String, Object>> callback) { + checkHasNoReflectionCallbacks(); + m_hasMethodRefs = true; + m_callbacks = m_callbacks.andThen(callback); + return this; + } + + private void checkHasNoMethodRefs() { + if (m_hasMethodRefs) { + throw new IllegalStateException("Can't mix method references with reflection based callbacks"); + } + } + + private void checkHasNoReflectionCallbacks() { + if (m_hasReflectionCallback) { + throw new IllegalStateException("Can't mix method references with reflection based callbacks"); + } + } } Modified: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/FactoryPidAdapterBuilderImpl.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/FactoryPidAdapterBuilderImpl.java?rev=1724333&r1=1724332&r2=1724333&view=diff ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/FactoryPidAdapterBuilderImpl.java (original) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/FactoryPidAdapterBuilderImpl.java Tue Jan 12 22:45:36 2016 @@ -1,98 +1,216 @@ package org.apache.felix.dm.builder.lambda.impl; import java.util.Dictionary; -import java.util.HashMap; -import java.util.Map; import java.util.Objects; -import java.util.stream.Stream; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; import org.apache.felix.dm.Component; import org.apache.felix.dm.DependencyManager; +import org.apache.felix.dm.builder.lambda.ComponentBuilder; import org.apache.felix.dm.builder.lambda.FactoryPidAdapterBuilder; -import org.apache.felix.dm.builder.lambda.Functions.Consumer2; - -public class FactoryPidAdapterBuilderImpl - extends ExtendedComponentBase<Object, FactoryPidAdapterBuilderImpl> - implements FactoryPidAdapterBuilder +import org.apache.felix.dm.builder.lambda.Functions.CbComponentDictionary; +import org.apache.felix.dm.builder.lambda.Functions.CbDictionary; +import org.apache.felix.dm.builder.lambda.Functions.CbTypeComponentDictionary; +import org.apache.felix.dm.builder.lambda.Functions.CbTypeDictionary; + +public class FactoryPidAdapterBuilderImpl<T> implements + AdapterBase<T, FactoryPidAdapterBuilder<T>>, + FactoryPidAdapterBuilder<T> { - protected final Map<String, Consumer2<?, Dictionary<String, Object>>> m_callbacks = new HashMap<>(); private String m_factoryPid; private boolean m_propagate; private final DependencyManager m_dm; private boolean m_autoAdd = true; + private BiConsumer<Component, Dictionary<String, Object>> m_callbacks = (component, props) -> {}; + private String m_updateMethodName; + private Object m_updateCallbackInstance; + private boolean m_hasMethodRefs; + private boolean m_hasReflectionCallback; + private Consumer<ComponentBuilder<T>> m_compBuilder = (componentBuilder -> {}); public FactoryPidAdapterBuilderImpl(DependencyManager dm) { m_dm = dm; } + + public void andThenBuild(Consumer<ComponentBuilder<T>> builder) { + m_compBuilder = m_compBuilder.andThen(builder); + } + + @SuppressWarnings("unchecked") + public <U> FactoryPidAdapterBuilder<U> impl(U impl) { + m_compBuilder = m_compBuilder.andThen(compBuilder -> compBuilder.impl(impl)); + return (FactoryPidAdapterBuilder<U>) this; + } + + @SuppressWarnings("unchecked") + public <U> FactoryPidAdapterBuilder<U> impl(Class<U> implClass) { + m_compBuilder = m_compBuilder.andThen(compBuilder -> compBuilder.impl(implClass)); + return (FactoryPidAdapterBuilder<U>) this; + } + + @SuppressWarnings("unchecked") + public <U> FactoryPidAdapterBuilder<U> factory(Supplier<U> create) { + m_compBuilder = m_compBuilder.andThen(compBuilder -> compBuilder.factory(create)); + return (FactoryPidAdapterBuilder<U>) this; + } + + @SuppressWarnings("unchecked") + public <U, V> FactoryPidAdapterBuilder<V> factory(Supplier<U> factory, Function<U, V> create) { + m_compBuilder = m_compBuilder.andThen(compBuilder -> compBuilder.factory(factory, create)); + return (FactoryPidAdapterBuilder<V>) this; + } + + @SuppressWarnings("unchecked") + public <U> FactoryPidAdapterBuilder<U> factory(Supplier<U> factory, Supplier<Object[]> getComposition) { + m_compBuilder = m_compBuilder.andThen(compBuilder -> compBuilder.factory(factory, getComposition)); + return (FactoryPidAdapterBuilder<U>) this; + } + + @SuppressWarnings("unchecked") + public <U, V> FactoryPidAdapterBuilder<V> factory(Supplier<U> factory, Function<U, V> create, Function<U, Object[]> getComposition) { + m_compBuilder = m_compBuilder.andThen(compBuilder -> compBuilder.factory(factory, create, getComposition)); + return (FactoryPidAdapterBuilder<V>) this; + } @Override - public FactoryPidAdapterBuilderImpl autoAdd(boolean autoAdd) { + public FactoryPidAdapterBuilderImpl<T> autoAdd(boolean autoAdd) { m_autoAdd = autoAdd; return this; } - public boolean autoAdd() { - return m_autoAdd; + @Override + public FactoryPidAdapterBuilderImpl<T> autoAdd() { + m_autoAdd = true; + return this; } + public boolean isAutoAdd() { + return m_autoAdd; + } + @Override - public FactoryPidAdapterBuilder factoryPid(String pid) { + public FactoryPidAdapterBuilder<T> factoryPid(String pid) { m_factoryPid = pid; return this; } @Override - public FactoryPidAdapterBuilder factoryPid(Class<?> pidClass) { + public FactoryPidAdapterBuilder<T> factoryPid(Class<?> pidClass) { m_factoryPid = pidClass.getName(); return this; } @Override - public FactoryPidAdapterBuilder propagate() { + public FactoryPidAdapterBuilder<T> propagate() { m_propagate = true; return this; } @Override - public FactoryPidAdapterBuilder propagate(boolean propagate) { + public FactoryPidAdapterBuilder<T> propagate(boolean propagate) { m_propagate = propagate; return this; } - @Override - public <T> FactoryPidAdapterBuilder onUpdate(Consumer2<T, Dictionary<String, Object>> callback) { - String instanceType = Helpers.getLambdaGenericType(callback); - setUpdateRef(instanceType, (T instance, Dictionary<String, Object> conf) -> callback.accept(instance, conf)); + public FactoryPidAdapterBuilder<T> cb(String update) { + checkHasNoMethodRefs(); + m_hasReflectionCallback = true; + m_updateMethodName = update; + return this; + } + + public FactoryPidAdapterBuilder<T> cb(Object callbackInstance, String update) { + cb(update); + m_updateCallbackInstance = callbackInstance; return this; } + + @Override + public FactoryPidAdapterBuilder<T> cb(CbTypeDictionary<T> callback) { + return addMethodRef((component, props) -> { + callback.accept(component.getInstance(), props); + }); + } + + @Override + public FactoryPidAdapterBuilder<T> cb(CbDictionary callback) { + return addMethodRef((component, props) -> { + callback.accept(props); + }); + } + + @Override + public FactoryPidAdapterBuilder<T> cb(CbComponentDictionary callback) { + return addMethodRef((component, props) -> { + callback.accept(component, props); + }); + } + + @Override + public FactoryPidAdapterBuilder<T> cb(CbTypeComponentDictionary<T> callback) { + return addMethodRef((component, props) -> { + callback.accept(component.getInstance(), component, props); + }); + } @Override + public <U> FactoryPidAdapterBuilder<T> compositeCb(CbTypeDictionary<U> callback) { + Class<U> type = Helpers.getLambdaGenericType(callback, 0); + return addMethodRef((component, props) -> { + U instance = Helpers.findCompositeInstance(component, type); + callback.accept(instance, props); + }); + } + + @Override + public <U> FactoryPidAdapterBuilder<T> compositeCb(CbTypeComponentDictionary<U> callback) { + Class<U> type = Helpers.getLambdaGenericType(callback, 0); + return addMethodRef((component, props) -> { + U instance = Helpers.findCompositeInstance(component, type); + callback.accept(instance, component, props); + }); + } + + @Override public Component build() { Objects.nonNull(m_factoryPid); - if (m_callbacks.size() == 0) { - throw new IllegalStateException("No callbacks configured in factory pid adapter"); + Component c = null; + + if (m_hasMethodRefs) { + Object wrapCallback = new Object() { + @SuppressWarnings("unused") + public void updated(Component comp, Dictionary<String, Object> conf) { + m_callbacks.accept(comp, conf); + } + }; + c = m_dm.createFactoryConfigurationAdapterService(m_factoryPid, "updated", m_propagate, wrapCallback); + } else { + c = m_dm.createFactoryConfigurationAdapterService(m_factoryPid, m_updateMethodName, m_propagate, m_updateCallbackInstance); } - Object wrapCallback = new Object() { - @SuppressWarnings({ "unused", "unchecked" }) - public void updated(Component comp, Dictionary<String, Object> conf) { - Stream.of(comp.getInstances()).forEach(instance -> { - Consumer2<Object, Dictionary<String, Object>> updateCB = - (Consumer2<Object, Dictionary<String, Object>>) m_callbacks.get(Helpers.getClassName(instance)); - if (updateCB != null) { - updateCB.accept(instance, conf); - } - }); - - } - }; - Component c = m_dm.createFactoryConfigurationAdapterService(m_factoryPid, "updated", m_propagate, wrapCallback); - ComponentBuilderImpl cb = new ComponentBuilderImpl(c, false); + ComponentBuilderImpl<T> cb = new ComponentBuilderImpl<>(c, false); m_compBuilder.accept (cb); return cb.build(); } - - public <T> FactoryPidAdapterBuilder setUpdateRef(String instanceType, Consumer2<T, Dictionary<String, Object>> updateCB) { - m_callbacks.put(instanceType, updateCB); + + private FactoryPidAdapterBuilder<T> addMethodRef(BiConsumer<Component, Dictionary<String, Object>> callback) { + checkHasNoReflectionCallbacks(); + m_hasMethodRefs = true; + m_callbacks = m_callbacks.andThen(callback); return this; } + + private void checkHasNoMethodRefs() { + if (m_hasMethodRefs) { + throw new IllegalStateException("Can't mix method references with reflection based callbacks"); + } + } + + private void checkHasNoReflectionCallbacks() { + if (m_hasReflectionCallback) { + throw new IllegalStateException("Can't mix method references with reflection based callbacks"); + } + } } Modified: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/Helpers.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/Helpers.java?rev=1724333&r1=1724332&r2=1724333&view=diff ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/Helpers.java (original) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/Helpers.java Tue Jan 12 22:45:36 2016 @@ -11,68 +11,45 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Stream; +import org.apache.felix.dm.Component; import org.apache.felix.dm.builder.lambda.Functions.SerializableLambda; - /** - * Helpers related to generics + * Various helper methods related to generics and lambda expressions. */ public class Helpers { private final static Pattern LAMBDA_INSTANCE_METHOD_TYPE = Pattern.compile("(L[^;]+)+"); /** * Gets the class name of a given object. + * @param obj the object whose class has to be returned. */ - public static String getClassName(Object obj) { + public static Class<?> getClass(Object obj) { Class<?> clazz = obj.getClass(); if (Proxy.isProxyClass(clazz)) { - return Proxy.getProxyClass(clazz.getClassLoader(), clazz).getName(); + return Proxy.getProxyClass(clazz.getClassLoader(), clazz); } - return clazz.getName(); + return clazz; } /** - * Extracts the first actual types of lambda generic parameters. + * Extracts the type of a given generic lambda parameter. + * Example: for "BiConsumer<String, Integer>", and with genericParamIndex=0, this method returns java.lang.String class. * - * @param lambda - * @return - * @throws Exception - */ - public static String getLambdaGenericType(SerializableLambda lambda) { - return getLambdaGenericTypes(lambda)[0]; - } - - /** - * Extracts the actual types of all lambda generic parameters. + * @param lambda a lambda expression, which must extends @link {@link SerializableLambda} interface. + * @param genericParamIndex the index of a given lambda generic parameter. + * @return the type of the lambda generic parameter that corresponds to the <code>genericParamIndex</code> */ - public static String[] getLambdaGenericTypes(SerializableLambda lambda) { - // The only portable way to get the actual lambda generic parameters can be done using SerializedLambda. - SerializedLambda sl = getSerializedLambda(lambda); - String lambdaMethodType = sl.getInstantiatedMethodType(); - Matcher m = LAMBDA_INSTANCE_METHOD_TYPE.matcher(lambdaMethodType); - List<String> results = new ArrayList<>(); - while (m.find()) { - results.add(m.group().substring(1).replace("/", ".")); - } - return results.toArray(new String[0]); - } - - /** - * Extracts the actual java method from a given lambda. - */ - public static Method getLambdaMethod(SerializedLambda lambda, ClassLoader loader) { - String implClassName = lambda.getImplClass().replace('/', '.'); - Class<?> implClass; - try { - implClass = loader.loadClass(implClassName); - } catch (ClassNotFoundException e) { - throw new RuntimeException("Lambda Method not found (can not instantiate class " + implClassName); - } - - return Stream.of(implClass.getDeclaredMethods()) - .filter(method -> Objects.equals(method.getName(), lambda.getImplMethodName())) - .findFirst() - .orElseThrow(() -> new RuntimeException("Lambda Method not found")); + @SuppressWarnings("unchecked") + public static <T> Class<T> getLambdaGenericType(SerializableLambda lambda, int genericParamIndex) { + String[] lambdaParams = getGenericTypeStrings(lambda); + Class<?> clazz; + try { + clazz = lambda.getClass().getClassLoader().loadClass(lambdaParams[genericParamIndex]); + } catch (ClassNotFoundException e) { + throw new RuntimeException("Can't load class " + lambdaParams[genericParamIndex]); + } + return (Class<T>) clazz; } /** @@ -118,4 +95,53 @@ public class Helpers { throw new RuntimeException("writeReplace method not found"); } + /** + * Finds a composite + * @param component + * @param type + * @return + */ + @SuppressWarnings("unchecked") + public static <U> U findCompositeInstance(Component component, Class<U> type) { + U instance = (U) Stream.of(component.getInstances()) + .filter(inst -> Objects.equals(Helpers.getClass(inst), type)) + .findFirst() + .orElseThrow(() -> new RuntimeException("Did not find a component instance matching type " + type)); + return instance; + } + + /** + * Extracts the actual types of all lambda generic parameters. + * Example: for "BiConsumer<String, Integer>", this method returns ["java.lang.String", "java.lang.Integer"]. + */ + private static String[] getGenericTypeStrings(SerializableLambda lambda) { + // The only portable way to get the actual lambda generic parameters can be done using SerializedLambda. + SerializedLambda sl = getSerializedLambda(lambda); + String lambdaMethodType = sl.getInstantiatedMethodType(); + Matcher m = LAMBDA_INSTANCE_METHOD_TYPE.matcher(lambdaMethodType); + List<String> results = new ArrayList<>(); + while (m.find()) { + results.add(m.group().substring(1).replace("/", ".")); + } + return results.toArray(new String[0]); + } + + /** + * Extracts the actual java method from a given lambda. + */ + private static Method getLambdaMethod(SerializedLambda lambda, ClassLoader loader) { + String implClassName = lambda.getImplClass().replace('/', '.'); + Class<?> implClass; + try { + implClass = loader.loadClass(implClassName); + } catch (ClassNotFoundException e) { + throw new RuntimeException("Lambda Method not found (can not instantiate class " + implClassName); + } + + return Stream.of(implClass.getDeclaredMethods()) + .filter(method -> Objects.equals(method.getName(), lambda.getImplMethodName())) + .findFirst() + .orElseThrow(() -> new RuntimeException("Lambda Method not found")); + } + } Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/ServiceAdapterBuilderImpl.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/ServiceAdapterBuilderImpl.java?rev=1724333&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/ServiceAdapterBuilderImpl.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/ServiceAdapterBuilderImpl.java Tue Jan 12 22:45:36 2016 @@ -0,0 +1,128 @@ +package org.apache.felix.dm.builder.lambda.impl; + +import java.util.Objects; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +import org.apache.felix.dm.Component; +import org.apache.felix.dm.DependencyManager; +import org.apache.felix.dm.builder.lambda.ComponentBuilder; +import org.apache.felix.dm.builder.lambda.ServiceAdapterBuilder; + +public class ServiceAdapterBuilderImpl<T, C> extends ServiceCallbacksBuilderImpl<T, ServiceAdapterBuilderImpl<T, C>> implements + AdapterBase<C, ServiceAdapterBuilder<T, C>>, + ServiceAdapterBuilder<T, C> +{ + private final Class<?> m_adapteeType; + private String m_adapteeFilter; + private boolean m_propagate = true; + private final DependencyManager m_dm; + private boolean m_autoAdd = true; + private Consumer<ComponentBuilder<C>> m_compBuilder = (componentBuilder -> {}); + + public ServiceAdapterBuilderImpl(DependencyManager dm, Class<T> type) { + super(type); + m_dm = dm; + m_adapteeType = type; + } + + @Override + public void andThenBuild(Consumer<ComponentBuilder<C>> after) { + m_compBuilder = m_compBuilder.andThen(after); + } + + @SuppressWarnings("unchecked") + public <U> ServiceAdapterBuilder<T, U> impl(U impl) { + m_compBuilder = m_compBuilder.andThen(compBuilder -> compBuilder.impl(impl)); + return (ServiceAdapterBuilder<T, U>) this; + } + + @SuppressWarnings("unchecked") + public <U> ServiceAdapterBuilder<T, U> impl(Class<U> impl) { + m_compBuilder = m_compBuilder.andThen(compBuilder -> compBuilder.impl(impl)); + return (ServiceAdapterBuilder<T, U>) this; + } + + @SuppressWarnings("unchecked") + public <U> ServiceAdapterBuilder<T, U> factory(Supplier<U> create) { + m_compBuilder = m_compBuilder.andThen(compBuilder -> compBuilder.factory(create)); + return (ServiceAdapterBuilder<T, U>) this; + } + + @SuppressWarnings("unchecked") + public <U, V> ServiceAdapterBuilder<T, V> factory(Supplier<U> factory, Function<U, V> create) { + m_compBuilder = m_compBuilder.andThen(compBuilder -> compBuilder.factory(factory, create)); + return (ServiceAdapterBuilder<T, V>) this; + } + + @SuppressWarnings("unchecked") + public <U> ServiceAdapterBuilder<T, U> factory(Supplier<U> factory, Supplier<Object[]> getComposition) { + m_compBuilder = m_compBuilder.andThen(compBuilder -> compBuilder.factory(factory, getComposition)); + return (ServiceAdapterBuilder<T, U>) this; + } + + @SuppressWarnings("unchecked") + public <U, V> ServiceAdapterBuilder<T, V> factory(Supplier<U> factory, Function<U, V> create, Function<U, Object[]> getComposition) { + m_compBuilder = m_compBuilder.andThen(compBuilder -> compBuilder.factory(factory, create, getComposition)); + return (ServiceAdapterBuilder<T, V>) this; + } + + @Override + public ServiceAdapterBuilderImpl<T, C> autoAdd(boolean autoAdd) { + m_autoAdd = autoAdd; + return this; + } + + public ServiceAdapterBuilderImpl<T, C> autoAdd() { + m_autoAdd = true; + return this; + } + + public boolean isAutoAdd() { + return m_autoAdd; + } + + @Override + public ServiceAdapterBuilder<T, C> filter(String adapteeFilter) { + m_adapteeFilter = adapteeFilter; + return this; + } + + @Override + public ServiceAdapterBuilder<T, C> propagate() { + m_propagate = true; + return this; + } + + @Override + public ServiceAdapterBuilder<T, C> propagate(boolean propagate) { + m_propagate = propagate; + return this; + } + + @Override + public Component build() { + Objects.nonNull(m_adapteeFilter); + + String add = m_added, change = m_changed, remove = m_removed, swap = m_swapped; + Object cbInstance = m_callbackInstance; + + if (hasRefs()) { + // if some method references have been set, use our own callback proxy to redispatch events to method refs. + cbInstance = createCallbackInstance(); + add = "add"; + change = "change"; + remove = "remove"; + swap = m_swapRefs.size() > 0 ? "swap" : null; + } + + Component c = m_dm.createAdapterService + (m_adapteeType, m_adapteeFilter, m_autoConfigField, cbInstance, add, change, remove, swap, m_propagate); + + ComponentBuilderImpl cb = new ComponentBuilderImpl(c, false); + // m_compBuilder is a composed consumer that calls in sequence all necessary component builder methods. + m_compBuilder.accept (cb); + return cb.build(); + } +} Added: felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/ServiceAspectBuilderImpl.java URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/ServiceAspectBuilderImpl.java?rev=1724333&view=auto ============================================================================== --- felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/ServiceAspectBuilderImpl.java (added) +++ felix/sandbox/pderop/dependencymanager-lambda/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/builder/lambda/impl/ServiceAspectBuilderImpl.java Tue Jan 12 22:45:36 2016 @@ -0,0 +1,127 @@ +package org.apache.felix.dm.builder.lambda.impl; + +import java.util.Objects; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +import org.apache.felix.dm.Component; +import org.apache.felix.dm.DependencyManager; +import org.apache.felix.dm.builder.lambda.ComponentBuilder; +import org.apache.felix.dm.builder.lambda.ServiceAspectBuilder; + +public class ServiceAspectBuilderImpl<T, C> extends ServiceCallbacksBuilderImpl<T, ServiceAspectBuilderImpl<T, C>> implements + AdapterBase<C, ServiceAspectBuilder<T, C>>, + ServiceAspectBuilder<T, C> +{ + private final DependencyManager m_dm; + private final Class<?> m_aspectType; + private String m_aspectFilter; + private int m_aspectRanking; + private boolean m_autoAdd = true; + private Consumer<ComponentBuilder<C>> m_compBuilder = (componentBuilder -> {}); + + public ServiceAspectBuilderImpl(DependencyManager dm, Class<T> type) { + super(type); + m_dm = dm; + m_aspectType = type; + } + + @Override + public void andThenBuild(Consumer<ComponentBuilder<C>> after) { + m_compBuilder = m_compBuilder.andThen(after); + } + + @SuppressWarnings("unchecked") + public <U> ServiceAspectBuilderImpl<T, U> impl(U impl) { + m_compBuilder = m_compBuilder.andThen(compBuilder -> compBuilder.impl(impl)); + return (ServiceAspectBuilderImpl<T, U>) this; + } + + @SuppressWarnings("unchecked") + public <U> ServiceAspectBuilderImpl<T, U> impl(Class<U> impl) { + m_compBuilder = m_compBuilder.andThen(compBuilder -> compBuilder.impl(impl)); + return (ServiceAspectBuilderImpl<T, U>) this; + } + + @SuppressWarnings("unchecked") + public <U> ServiceAspectBuilderImpl<T, U> factory(Supplier<U> create) { + m_compBuilder = m_compBuilder.andThen(compBuilder -> compBuilder.factory(create)); + return (ServiceAspectBuilderImpl<T, U>) this; + } + + @SuppressWarnings("unchecked") + public <U, V> ServiceAspectBuilderImpl<T, V> factory(Supplier<U> factory, Function<U, V> create) { + m_compBuilder = m_compBuilder.andThen(compBuilder -> compBuilder.factory(factory, create)); + return (ServiceAspectBuilderImpl<T, V>) this; + } + + @SuppressWarnings("unchecked") + public <U> ServiceAspectBuilderImpl<T, U> factory(Supplier<U> factory, Supplier<Object[]> getComposition) { + m_compBuilder = m_compBuilder.andThen(compBuilder -> compBuilder.factory(factory, getComposition)); + return (ServiceAspectBuilderImpl<T, U>) this; + } + + @SuppressWarnings("unchecked") + public <U, V> ServiceAspectBuilderImpl<T, V> factory(Supplier<U> factory, Function<U, V> create, Function<U, Object[]> getComposition) { + m_compBuilder = m_compBuilder.andThen(compBuilder -> compBuilder.factory(factory, create, getComposition)); + return (ServiceAspectBuilderImpl<T, V>) this; + } + + @Override + public ServiceAspectBuilderImpl<T, C> autoAdd(boolean autoAdd) { + m_autoAdd = autoAdd; + return this; + } + + @Override + public ServiceAspectBuilderImpl<T, C> autoAdd() { + m_autoAdd = true; + return this; + } + + public boolean isAutoAdd() { + return m_autoAdd; + } + + @Override + public ServiceAspectBuilder<T, C> filter(String aspectFilter) { + m_aspectFilter = aspectFilter; + return this; + } + + @Override + public ServiceAspectBuilder<T, C> rank(int ranking) { + m_aspectRanking = ranking; + return this; + } + + @Override + public Component build() { + Objects.nonNull(m_aspectType); + + if (m_autoConfigField != null && (hasRefs()|| hasCallbacks())) { + throw new IllegalStateException("Can't mix autoConfig fields and aspect callbacks."); + } + + Component c = null; + if (m_autoConfigField != null) { + c = m_dm.createAspectService(m_aspectType, m_aspectFilter, m_aspectRanking, m_autoConfigField); + } else if (hasRefs()) { + Object cbInstance = createCallbackInstance(); + String add = "add"; + String change = "change"; + String remove = "remove"; + String swap = m_swapRefs.size() > 0 ? "swap" : null; + c = m_dm.createAspectService(m_aspectType, m_aspectFilter, m_aspectRanking, cbInstance, add, change, remove, swap); + } else if (hasCallbacks()) { + c = m_dm.createAspectService(m_aspectType, m_aspectFilter, m_aspectRanking, m_added, m_changed, m_removed, m_swapped); + } else { + c = m_dm.createAspectService(m_aspectType, m_aspectFilter, m_aspectRanking); + } + ComponentBuilderImpl<C> cb = new ComponentBuilderImpl<>(c, false); + // m_compBuilder is a composed consumer that calls in sequence all necessary component builder methods. + m_compBuilder.accept (cb); + return cb.build(); + } +}
