Added: felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ServiceAdapterBuilderImpl.java URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ServiceAdapterBuilderImpl.java?rev=1727869&view=auto ============================================================================== --- felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ServiceAdapterBuilderImpl.java (added) +++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ServiceAdapterBuilderImpl.java Sun Jan 31 23:27:05 2016 @@ -0,0 +1,83 @@ +package org.apache.felix.dm.lambda.impl; + +import java.util.Objects; +import java.util.function.Consumer; + +import org.apache.felix.dm.Component; +import org.apache.felix.dm.DependencyManager; +import org.apache.felix.dm.lambda.ComponentBuilder; +import org.apache.felix.dm.lambda.ServiceAdapterBuilder; + +public class ServiceAdapterBuilderImpl<T> extends ServiceCallbacksBuilderImpl<T, ServiceAdapterBuilder<T>> implements + AdapterBase<ServiceAdapterBuilder<T>>, ServiceAdapterBuilder<T> +{ + private final Class<T> m_adapteeType; + private String m_adapteeFilter; + private boolean m_propagate = true; + private final DependencyManager m_dm; + private boolean m_autoAdd = true; + private Consumer<ComponentBuilder<?>> m_compBuilder = (componentBuilder -> {}); + + public ServiceAdapterBuilderImpl(DependencyManager dm, Class<T> adapterType) { + super(adapterType); + m_dm = dm; + m_adapteeType = adapterType; + } + + @Override + public void andThenBuild(Consumer<ComponentBuilder<?>> after) { + m_compBuilder = m_compBuilder.andThen(after); + } + + @Override + public ServiceAdapterBuilderImpl<T> autoAdd(boolean autoAdd) { + m_autoAdd = autoAdd; + return this; + } + + public ServiceAdapterBuilderImpl<T> autoAdd() { + m_autoAdd = true; + return this; + } + + public boolean isAutoAdd() { + return m_autoAdd; + } + + @Override + public ServiceAdapterBuilder<T> filter(String adapteeFilter) { + m_adapteeFilter = adapteeFilter; + return this; + } + + @Override + public ServiceAdapterBuilder<T> propagate(boolean propagate) { + m_propagate = propagate; + return this; + } + + @Override + public Component build() { + Objects.nonNull(m_adapteeFilter); + + String add = getAdded(), change = getChanged(), remove = getRemoved(), swap = getSwapped(); + Object cbInstance = getCallbackInstance(); + + 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, getAutoConfigField(), 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/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ServiceAspectBuilderImpl.java URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ServiceAspectBuilderImpl.java?rev=1727869&view=auto ============================================================================== --- felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ServiceAspectBuilderImpl.java (added) +++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ServiceAspectBuilderImpl.java Sun Jan 31 23:27:05 2016 @@ -0,0 +1,86 @@ +package org.apache.felix.dm.lambda.impl; + +import java.util.Objects; +import java.util.function.Consumer; + +import org.apache.felix.dm.Component; +import org.apache.felix.dm.DependencyManager; +import org.apache.felix.dm.lambda.ComponentBuilder; +import org.apache.felix.dm.lambda.ServiceAspectBuilder; + +public class ServiceAspectBuilderImpl<T> extends ServiceCallbacksBuilderImpl<T, ServiceAspectBuilder<T>> implements + AdapterBase<ServiceAspectBuilder<T>>, ServiceAspectBuilder<T> +{ + private final DependencyManager m_dm; + private final Class<T> m_aspectType; + private String m_aspectFilter; + private int m_aspectRanking; + private boolean m_autoAdd = true; + private Consumer<ComponentBuilder<?>> m_compBuilder = (componentBuilder -> {}); + + public ServiceAspectBuilderImpl(DependencyManager dm, Class<T> aspectType) { + super(aspectType); + m_dm = dm; + m_aspectType = aspectType; + } + + @Override + public void andThenBuild(Consumer<ComponentBuilder<?>> after) { + m_compBuilder = m_compBuilder.andThen(after); + } + + @Override + public ServiceAspectBuilderImpl<T> autoAdd(boolean autoAdd) { + m_autoAdd = autoAdd; + return this; + } + + public boolean isAutoAdd() { + return m_autoAdd; + } + + @Override + public ServiceAspectBuilder<T> filter(String aspectFilter) { + m_aspectFilter = aspectFilter; + return this; + } + + @Override + public ServiceAspectBuilder<T> rank(int ranking) { + m_aspectRanking = ranking; + return this; + } + + @Override + public Component build() { + Objects.nonNull(m_aspectType); + + if (getAutoConfigField() != null && (hasRefs()|| hasCallbacks())) { + throw new IllegalStateException("Can't mix autoConfig fields and aspect callbacks."); + } + + Component c = null; + if (getAutoConfigField() != null) { + c = m_dm.createAspectService(m_aspectType, m_aspectFilter, m_aspectRanking, getAutoConfigField()); + } 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()) { + String add = getAdded(); + String change = getChanged(); + String remove = getRemoved(); + String swap = getSwapped(); + c = m_dm.createAspectService(m_aspectType, m_aspectFilter, m_aspectRanking, add, change, remove, swap); + } else { + c = m_dm.createAspectService(m_aspectType, m_aspectFilter, m_aspectRanking); + } + 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/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ServiceCallbacksBuilderImpl.java URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ServiceCallbacksBuilderImpl.java?rev=1727869&view=auto ============================================================================== --- felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ServiceCallbacksBuilderImpl.java (added) +++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ServiceCallbacksBuilderImpl.java Sun Jan 31 23:27:05 2016 @@ -0,0 +1,651 @@ +package org.apache.felix.dm.lambda.impl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Stream; + +import org.apache.felix.dm.Component; +import org.apache.felix.dm.lambda.ServiceCallbacksBuilder; +import org.apache.felix.dm.lambda.callbacks.CbComponent; +import org.apache.felix.dm.lambda.callbacks.CbComponentRef; +import org.apache.felix.dm.lambda.callbacks.CbComponentRefService; +import org.apache.felix.dm.lambda.callbacks.CbComponentRefServiceRefService; +import org.apache.felix.dm.lambda.callbacks.CbComponentService; +import org.apache.felix.dm.lambda.callbacks.CbComponentServiceService; +import org.apache.felix.dm.lambda.callbacks.CbRef; +import org.apache.felix.dm.lambda.callbacks.CbRefService; +import org.apache.felix.dm.lambda.callbacks.CbRefServiceRefService; +import org.apache.felix.dm.lambda.callbacks.CbService; +import org.apache.felix.dm.lambda.callbacks.CbServiceDict; +import org.apache.felix.dm.lambda.callbacks.CbServiceMap; +import org.apache.felix.dm.lambda.callbacks.CbServiceService; +import org.apache.felix.dm.lambda.callbacks.CbTypeComponent; +import org.apache.felix.dm.lambda.callbacks.CbTypeComponentRef; +import org.apache.felix.dm.lambda.callbacks.CbTypeComponentRefService; +import org.apache.felix.dm.lambda.callbacks.CbTypeComponentRefServiceRefService; +import org.apache.felix.dm.lambda.callbacks.CbTypeComponentService; +import org.apache.felix.dm.lambda.callbacks.CbTypeComponentServiceService; +import org.apache.felix.dm.lambda.callbacks.CbTypeRef; +import org.apache.felix.dm.lambda.callbacks.CbTypeRefService; +import org.apache.felix.dm.lambda.callbacks.CbTypeRefServiceRefService; +import org.apache.felix.dm.lambda.callbacks.CbTypeService; +import org.apache.felix.dm.lambda.callbacks.CbTypeServiceDict; +import org.apache.felix.dm.lambda.callbacks.CbTypeServiceMap; +import org.apache.felix.dm.lambda.callbacks.CbTypeServiceService; +import org.osgi.framework.ServiceReference; + +/** + * Service Dependency Callback management. + * + * @param <S> the type of the service dependency + * @param <B> the type of the sub-classes which may extend this class + */ +@SuppressWarnings({"unchecked", "unused"}) +public class ServiceCallbacksBuilderImpl<S, B extends ServiceCallbacksBuilder<S, B>> implements ServiceCallbacksBuilder<S, B> { + protected boolean m_autoConfig = true; + protected boolean m_autoConfigInvoked = false; + protected String m_autoConfigField; + protected Object m_callbackInstance; + protected String m_added; + protected String m_changed; + protected String m_removed; + protected String m_swapped; + protected final Class<S> m_serviceClass; + + enum Cb { + ADD, + CHG, + REM + }; + + /** + * List of service (add/change/remove) callbacks. + */ + protected final Map<Cb, List<MethodRef<Object, S>>> m_refs = new HashMap<>(); + + /** + * List of swap callbacks + */ + protected final List<SwapMethodRef<?, S>> m_swapRefs = new ArrayList<>(); + + /** + * This interface (lambda) is called when we want to invoke a method reference. the lambda is called with all necessary service dependency + * informations. + * + * When the lambda is called, it will invoke the proper callback on the given component instance. + * + * @param <I> type of a component instance + * @param <T> service dependency type + */ + @FunctionalInterface + interface MethodRef<I, S> { + public void accept(I instance, Component c, ServiceReference<S> ref, S service); + } + + /** + * This interface (lambda) is called when we want to invoke a swap method reference. the lambda is called with all necessary swap info. + * When the lambda is called, it will invoke the proper swap callback on the given component instance. + * + * @param <I> type of a component instance + * @param <T> service dependency type + */ + @FunctionalInterface + interface SwapMethodRef<I, S> { + public void accept(I instance, Component c, ServiceReference<S> oldRef, S oldService, ServiceReference<S> newRef, S newService); + } + + public ServiceCallbacksBuilderImpl(Class<S> serviceClass) { + m_serviceClass = serviceClass; + } + + public B autoConfig() { + autoConfig(true); + return (B) this; + } + + public B autoConfig(String field) { + m_autoConfigField = field; + m_autoConfigInvoked = true; + return (B) this; + } + + public B autoConfig(boolean autoConfig) { + m_autoConfig = autoConfig; + m_autoConfigInvoked = true; + return (B) this; + } + + public B cb(String ... callbacks) { + return cbi(null, callbacks); + } + + public B cbi(Object callbackInstance, String ... callbacks) { + Objects.nonNull(callbacks); + switch (callbacks.length) { + case 1: + cb(callbackInstance, callbacks[0], null, null, null); + break; + + case 2: + cb(callbackInstance, callbacks[0], null, callbacks[1], null); + break; + + case 3: + cb(callbackInstance, callbacks[0], callbacks[1], callbacks[2], null); + break; + + case 4: + cb(callbackInstance, callbacks[0], callbacks[1], callbacks[2], callbacks[3]); + break; + + default: + throw new IllegalArgumentException("wrong number of arguments: " + callbacks.length + ". " + + "Possible arguments: [add], [add, remove], [add, change, remove], or [add, change, remove, swap]"); + } + return (B) this; + } + + private B cb(Object callbackInstance, String added, String changed, String removed, String swapped) { + requiresNoMethodRefs(); + m_callbackInstance = callbackInstance; + m_added = added != null ? added : m_added; + m_changed = changed != null ? changed : m_changed; + m_removed = removed != null ? removed : m_removed; + m_swapped = swapped != null ? swapped : m_swapped; + if (! m_autoConfigInvoked) m_autoConfig = false; + return (B) this; + } + + public <T> B cb(CbTypeService<T, S> add) { + return cb(add, null, null); + } + + public <T> B cb(CbTypeService<T, S> add, CbTypeService<T, S> remove) { + return cb(add, null, remove); + } + + public <T> B cb(CbTypeService<T, S> add, CbTypeService<T, S> change, CbTypeService<T, S> remove) { + if (add != null) + setComponentCallbackRef(Cb.ADD, Helpers.getLambdaArgType(add, 0), (inst, comp, ref, srv) -> add.accept((T) inst, srv)); + if (change != null) + setComponentCallbackRef(Cb.CHG, Helpers.getLambdaArgType(change, 0), (inst, comp, ref, srv) -> change.accept((T) inst, srv)); + if (remove != null) + setComponentCallbackRef(Cb.REM, Helpers.getLambdaArgType(remove, 0), (inst, comp, ref, srv) -> remove.accept((T) inst, srv)); + return (B) this; + } + + public B cbi(CbService<S> add) { + return cbi(add, null, null); + } + + public B cbi(CbService<S> add, CbService<S> remove) { + return cbi(add, null, remove); + } + + public B cbi(CbService<S> add, CbService<S> change, CbService<S> remove) { + if (add != null) + setInstanceCallbackRef(Cb.ADD, (inst, comp, ref, srv) -> add.accept(srv)); + if (change != null) + setInstanceCallbackRef(Cb.CHG, (inst, comp, ref, srv) -> change.accept(srv)); + if (remove != null) + setInstanceCallbackRef(Cb.REM, (inst, comp, ref, srv) -> remove.accept(srv)); + return (B) this; + } + + public <T> B cb(CbTypeServiceMap<T, S> add) { + return cb(add, null, null); + } + + public <T> B cb(CbTypeServiceMap<T, S> add, CbTypeServiceMap<T, S> remove) { + return cb(add, null, remove); + } + + public <T> B cb(CbTypeServiceMap<T, S> add, CbTypeServiceMap<T, S> change, CbTypeServiceMap<T, S> remove) { + if (add != null) + setComponentCallbackRef(Cb.ADD, Helpers.getLambdaArgType(add, 0), (inst, comp, ref, srv) -> add.accept((T) inst, srv, new SRefAsMap(ref))); + if (change != null) + setComponentCallbackRef(Cb.CHG, Helpers.getLambdaArgType(change, 0), (inst, comp, ref, srv) -> change.accept((T) inst, srv, new SRefAsMap(ref))); + if (remove != null) + setComponentCallbackRef(Cb.REM, Helpers.getLambdaArgType(remove, 0), (inst, comp, ref, srv) -> remove.accept((T) inst, srv, new SRefAsMap(ref))); + return (B) this; + } + + public B cbi(CbServiceMap<S> add) { + return cbi(add, null, null); + } + + public B cbi(CbServiceMap<S> add, CbServiceMap<S> remove) { + return cbi(add, null, remove); + } + + public B cbi(CbServiceMap<S> add, CbServiceMap<S> change, CbServiceMap<S> remove) { + if (add != null) + setInstanceCallbackRef(Cb.ADD, (inst, comp, ref, srv) -> add.accept(srv, new SRefAsMap(ref))); + if (change != null) + setInstanceCallbackRef(Cb.CHG, (inst, comp, ref, srv) -> change.accept(srv, new SRefAsMap(ref))); + if (remove != null) + setInstanceCallbackRef(Cb.REM, (inst, comp, ref, srv) -> remove.accept(srv, new SRefAsMap(ref))); + return (B) this; + } + + public <T> B cb(CbTypeServiceDict<T, S> add) { + return cb(add, null, null); + } + + public <T> B cb(CbTypeServiceDict<T, S> add, CbTypeServiceDict<T, S> remove) { + return cb(add, null, remove); + } + + public <T> B cb(CbTypeServiceDict<T, S> add, CbTypeServiceDict<T, S> change, CbTypeServiceDict<T, S> remove) { + if (add != null) + setComponentCallbackRef(Cb.ADD, Helpers.getLambdaArgType(add, 0), (inst, comp, ref, srv) -> add.accept((T) inst, srv, new SRefAsDictionary(ref))); + if (change != null) + setComponentCallbackRef(Cb.CHG, Helpers.getLambdaArgType(change, 0), (inst, comp, ref, srv) -> change.accept((T) inst, srv, new SRefAsDictionary(ref))); + if (remove != null) + setComponentCallbackRef(Cb.REM, Helpers.getLambdaArgType(remove, 0), (inst, comp, ref, srv) -> remove.accept((T) inst, srv, new SRefAsDictionary(ref))); + return (B) this; + } + + public B cbi(CbServiceDict<S> add) { + return cbi(add, null, null); + } + + public B cbi(CbServiceDict<S> add, CbServiceDict<S> remove) { + return cbi(add, null, remove); + } + + public B cbi(CbServiceDict<S> add, CbServiceDict<S> change, CbServiceDict<S> remove) { + if (add != null) + setInstanceCallbackRef(Cb.ADD, (inst, comp, ref, srv) -> add.accept(srv, new SRefAsDictionary(ref))); + if (change != null) + setInstanceCallbackRef(Cb.CHG, (inst, comp, ref, srv) -> change.accept(srv, new SRefAsDictionary(ref))); + if (remove != null) + setInstanceCallbackRef(Cb.REM, (inst, comp, ref, srv) -> remove.accept(srv, new SRefAsDictionary(ref))); + return (B) this; + } + + public <T> B cb(CbTypeRefService<T, S> add) { + return cb(add, null, null); + } + + public <T> B cb(CbTypeRefService<T, S> add, CbTypeRefService<T, S> remove) { + return cb(add, null, remove); + } + + public <T> B cb(CbTypeRefService<T, S> add, CbTypeRefService<T, S> change, CbTypeRefService<T, S> remove) { + if (add != null) + setComponentCallbackRef(Cb.ADD, Helpers.getLambdaArgType(add, 0), (inst, comp, ref, srv) -> add.accept((T) inst, ref, srv)); + if (change != null) + setComponentCallbackRef(Cb.CHG, Helpers.getLambdaArgType(change, 0), (inst, comp, ref, srv) -> change.accept((T) inst, ref, srv)); + if (remove != null) + setComponentCallbackRef(Cb.REM, Helpers.getLambdaArgType(remove, 0), (inst, comp, ref, srv) -> remove.accept((T) inst, ref, srv)); + return (B) this; + } + + public B cbi(CbRefService<S> add) { + return cbi(add, null, null); + } + + public B cbi(CbRefService<S> add, CbRefService<S> remove) { + return cbi(add, null, remove); + } + + public B cbi(CbRefService<S> add, CbRefService<S> change, CbRefService<S> remove) { + if (add != null) + setInstanceCallbackRef(Cb.ADD, (inst, comp, ref, srv) -> add.accept(ref, srv)); + if (change != null) + setInstanceCallbackRef(Cb.CHG, (inst, comp, ref, srv) -> change.accept(ref, srv)); + if (remove != null) + setInstanceCallbackRef(Cb.REM, (inst, comp, ref, srv) -> remove.accept(ref, srv)); + return (B) this; + } + + public <T> B cb(CbTypeRef<T, S> add) { + return cb(add, null, null); + } + + public <T> B cb(CbTypeRef<T, S> add, CbTypeRef<T, S> remove) { + return cb(add, null, remove); + } + + public <T> B cb(CbTypeRef<T, S> add, CbTypeRef<T, S> change, CbTypeRef<T, S> remove) { + if (add != null) + setComponentCallbackRef(Cb.ADD, Helpers.getLambdaArgType(add, 0), (inst, comp, ref, srv) -> add.accept((T) inst, ref)); + if (change != null) + setComponentCallbackRef(Cb.CHG, Helpers.getLambdaArgType(change, 0), (inst, comp, ref, srv) -> change.accept((T) inst, ref)); + if (remove != null) + setComponentCallbackRef(Cb.REM, Helpers.getLambdaArgType(remove, 0), (inst, comp, ref, srv) -> remove.accept((T) inst, ref)); + return (B) this; + } + + public B cbi(CbRef<S> add) { + return cbi(add, null, null); + } + + public B cbi(CbRef<S> add, CbRef<S> remove) { + return cbi(add, null, remove); + } + + public B cbi(CbRef<S> add, CbRef<S> change, CbRef<S> remove) { + if (add != null) + setInstanceCallbackRef(Cb.ADD, (inst, comp, ref, srv) -> add.accept(ref)); + if (change != null) + setInstanceCallbackRef(Cb.CHG, (inst, comp, ref, srv) -> change.accept(ref)); + if (remove != null) + setInstanceCallbackRef(Cb.REM, (inst, comp, ref, srv) -> remove.accept(ref)); + return (B) this; + } + + public <T> B cb(CbTypeComponent<T> add) { + return cb(add, null, null); + } + + public <T> B cb(CbTypeComponent<T> add, CbTypeComponent<T> remove) { + return cb(add, null, remove); + } + + public <T> B cb(CbTypeComponent<T> add, CbTypeComponent<T> change, CbTypeComponent<T> remove) { + if (add != null) + setComponentCallbackRef(Cb.ADD, Helpers.getLambdaArgType(add, 0), (inst, comp, ref, srv) -> add.accept((T) inst, comp)); + if (change != null) + setComponentCallbackRef(Cb.CHG, Helpers.getLambdaArgType(change, 0), (inst, comp, ref, srv) -> change.accept((T) inst, comp)); + if (remove != null) + setComponentCallbackRef(Cb.REM, Helpers.getLambdaArgType(remove, 0), (inst, comp, ref, srv) -> remove.accept((T) inst, comp)); + return (B) this; + } + + public B cbi(CbComponent add) { + return cbi(add, null, null); + } + + public B cbi(CbComponent add, CbComponent remove) { + return cbi(add, null, remove); + } + + public B cbi(CbComponent add, CbComponent change, CbComponent remove) { + if (add != null) + setInstanceCallbackRef(Cb.ADD, (inst, comp, ref, srv) -> add.accept(comp)); + if (change != null) + setInstanceCallbackRef(Cb.CHG, (inst, comp, ref, srv) -> change.accept(comp)); + if (remove != null) + setInstanceCallbackRef(Cb.REM, (inst, comp, ref, srv) -> remove.accept(comp)); + return (B) this; + } + + public <T> B cb(CbTypeComponentRef<T, S> add) { + return cb(add, null, null); + } + + public <T> B cb(CbTypeComponentRef<T, S> add, CbTypeComponentRef<T, S> remove) { + return cb(add, null, remove); + } + + public <T> B cb(CbTypeComponentRef<T, S> add, CbTypeComponentRef<T, S> change, CbTypeComponentRef<T, S> remove) { + if (add != null) + setComponentCallbackRef(Cb.ADD, Helpers.getLambdaArgType(add, 0), (inst, comp, ref, srv) -> add.accept((T) inst, comp, ref)); + if (change != null) + setComponentCallbackRef(Cb.CHG, Helpers.getLambdaArgType(change, 0), (inst, comp, ref, srv) -> change.accept((T) inst, comp, ref)); + if (remove != null) + setComponentCallbackRef(Cb.REM, Helpers.getLambdaArgType(remove, 0), (inst, comp, ref, srv) -> remove.accept((T) inst, comp, ref)); + return (B) this; + } + + public B cbi(CbComponentRef<S> add) { + return cbi(add, null, null); + } + + public B cbi(CbComponentRef<S> add, CbComponentRef<S> remove) { + return cbi(add, null, remove); + } + + public B cbi(CbComponentRef<S> add, CbComponentRef<S> change, CbComponentRef<S> remove) { + if (add != null) + setInstanceCallbackRef(Cb.ADD, (inst, comp, ref, srv) -> add.accept(comp, ref)); + if (change != null) + setInstanceCallbackRef(Cb.CHG, (inst, comp, ref, srv) -> change.accept(comp, ref)); + if (remove != null) + setInstanceCallbackRef(Cb.REM, (inst, comp, ref, srv) -> remove.accept(comp, ref)); + return (B) this; + } + + public <T> B cb(CbTypeComponentService<T, S> add) { + return cb(add, null, null); + } + + public <T> B cb(CbTypeComponentService<T, S> add, CbTypeComponentService<T, S> remove) { + return cb(add, null, remove); + } + + public <T> B cb(CbTypeComponentService<T, S> add, CbTypeComponentService<T, S> change, CbTypeComponentService<T, S> remove) { + if (add != null) + setComponentCallbackRef(Cb.ADD, Helpers.getLambdaArgType(add, 0), (inst, comp, ref, srv) -> add.accept((T) inst, comp, srv)); + if (change != null) + setComponentCallbackRef(Cb.CHG, Helpers.getLambdaArgType(change, 0), (inst, comp, ref, srv) -> change.accept((T) inst, comp, srv)); + if (remove != null) + setComponentCallbackRef(Cb.REM, Helpers.getLambdaArgType(remove, 0), (inst, comp, ref, srv) -> remove.accept((T) inst, comp, srv)); + return (B) this; + } + + public B cbi(CbComponentService<S> add) { + return cbi(add, null, null); + } + + public B cbi(CbComponentService<S> add, CbComponentService<S> remove) { + return cbi(add, null, remove); + } + + public B cbi(CbComponentService<S> add, CbComponentService<S> change, CbComponentService<S> remove) { + if (add != null) + setInstanceCallbackRef(Cb.ADD, (inst, comp, ref, srv) -> add.accept(comp, srv)); + if (change != null) + setInstanceCallbackRef(Cb.CHG, (inst, comp, ref, srv) -> change.accept(comp, srv)); + if (remove != null) + setInstanceCallbackRef(Cb.REM, (inst, comp, ref, srv) -> remove.accept(comp, srv)); + return (B) this; + } + + public <T> B cb(CbTypeComponentRefService<T, S> add) { + return cb(add, null, null); + } + + public <T> B cb(CbTypeComponentRefService<T, S> add, CbTypeComponentRefService<T, S> remove) { + return cb(add, null, remove); + } + + public <T> B cb(CbTypeComponentRefService<T, S> add, CbTypeComponentRefService<T, S> change, CbTypeComponentRefService<T, S> remove) { + if (add != null) + setComponentCallbackRef(Cb.ADD, Helpers.getLambdaArgType(add, 0), (inst, comp, ref, srv) -> add.accept((T) inst, comp, ref, srv)); + if (change != null) + setComponentCallbackRef(Cb.CHG, Helpers.getLambdaArgType(change, 0), (inst, comp, ref, srv) -> change.accept((T) inst, comp, ref, srv)); + if (remove != null) + setComponentCallbackRef(Cb.REM, Helpers.getLambdaArgType(remove, 0), (inst, comp, ref, srv) -> remove.accept((T) inst, comp, ref, srv)); + return (B) this; + } + + public B cbi(CbComponentRefService<S> add) { + return cbi(add, null, null); + } + + public B cbi(CbComponentRefService<S> add, CbComponentRefService<S> remove) { + return cbi(add, null, remove); + } + + public B cbi(CbComponentRefService<S> add, CbComponentRefService<S> change, CbComponentRefService<S> remove) { + if (add != null) + setInstanceCallbackRef(Cb.ADD, (inst, comp, ref, srv) -> add.accept(comp, ref, srv)); + if (change != null) + setInstanceCallbackRef(Cb.CHG, (inst, comp, ref, srv) -> change.accept(comp, ref, srv)); + if (remove != null) + setInstanceCallbackRef(Cb.REM, (inst, comp, ref, srv) -> remove.accept(comp, ref, srv)); + return (B) this; + } + + public <T> B sw(CbTypeServiceService<T, S> swap) { + Class<T> type = Helpers.getLambdaArgType(swap, 0); + return setComponentSwapCallbackRef(type, (inst, component, oref, oserv, nref, nserv) -> + swap.accept((T) inst, oserv, nserv)); + } + + public <T> B sw(CbTypeComponentServiceService<T, S> swap) { + Class<T> type = Helpers.getLambdaArgType(swap, 0); + return setComponentSwapCallbackRef(type, (inst, component, oref, oserv, nref, nserv) -> + swap.accept((T) inst, component, oserv, nserv)); + } + + public <T> B sw(CbTypeRefServiceRefService<T, S> swap) { + Class<T> type = Helpers.getLambdaArgType(swap, 0); + return setComponentSwapCallbackRef(type, (inst, component, oref, oserv, nref, nserv) -> + swap.accept((T) inst, oref, oserv, nref, nserv)); + } + + public <T> B sw(CbTypeComponentRefServiceRefService<T, S> swap) { + Class<T> type = Helpers.getLambdaArgType(swap, 0); + return setComponentSwapCallbackRef(type, (inst, component, oref, oserv, nref, nserv) -> + swap.accept((T) inst, component, oref, oserv, nref, nserv)); + } + + public B swi(CbServiceService<S> swap) { + return setInstanceSwapCallbackRef((inst, component, oref, oserv, nref, nserv) -> swap.accept(oserv, nserv)); + } + + public B swi(CbComponentServiceService<S> swap) { + return setInstanceSwapCallbackRef((inst, component, oref, oserv, nref, nserv) -> swap.accept(component, oserv, nserv)); + } + + public B swi(CbRefServiceRefService<S> swap) { + return setInstanceSwapCallbackRef((inst, component, oref, oserv, nref, nserv) -> swap.accept(oref, oserv, nref, nserv)); + } + + public B swi(CbComponentRefServiceRefService<S> swap) { + return setInstanceSwapCallbackRef((inst, component, oref, oserv, nref, nserv) -> swap.accept(component, oref, oserv, nref, nserv)); + } + + protected <I> B setComponentCallbackRef(Cb cbType, Class<I> type, MethodRef<I, S> ref) { + requiresNoCallbacks(); + if (! m_autoConfigInvoked) m_autoConfig = false; + List<MethodRef<Object, S>> list = m_refs.computeIfAbsent(cbType, l -> new ArrayList<>()); + list.add((instance, component, sref, service) -> { + Object componentImpl = Stream.of(component.getInstances()) + .filter(impl -> Helpers.getClass(impl).equals(type)) + .findFirst() + .orElseThrow(() -> new IllegalStateException("The method reference " + ref + " does not match any available component impl classes.")); + ref.accept((I) componentImpl, component, sref, service); + }); + return (B) this; + } + + protected <T> B setInstanceCallbackRef(Cb cbType, MethodRef<T, S> ref) { + requiresNoCallbacks(); + if (! m_autoConfigInvoked) m_autoConfig = false; + List<MethodRef<Object, S>> list = m_refs.computeIfAbsent(cbType, l -> new ArrayList<>()); + list.add((instance, component, sref, service) -> { + ref.accept((T) component.getInstance(), component, sref, service); + }); + return (B) this; + } + + public <I> B setComponentSwapCallbackRef(Class<I> type, SwapMethodRef<I, S> ref) { + requiresNoCallbacks(); + if (! m_autoConfigInvoked) m_autoConfig = false; + m_swapRefs.add((instance, component, oref, oservice, nref, nservice) -> { + Object componentImpl = Stream.of(component.getInstances()) + .filter(impl -> Helpers.getClass(impl).equals(type)) + .findFirst() + .orElseThrow(() -> new IllegalStateException("The method reference " + ref + " does not match any available component impl classes.")); + ref.accept((I) componentImpl, component, oref, oservice, nref, nservice); + }); + return (B) this; + } + + public <I> B setInstanceSwapCallbackRef(SwapMethodRef<I, S> ref) { + requiresNoCallbacks(); + if (! m_autoConfigInvoked) m_autoConfig = false; + m_swapRefs.add((instance, component, oref, oservice, nref, nservice) -> { + ref.accept((I) component.getInstance(), component, oref, oservice, nref, nservice); + }); + return (B) this; + } + + Object createCallbackInstance() { + Object cb = null; + + cb = new Object() { + void add(Component c, ServiceReference<S> ref, Object service) { + invokeMethodRefs(Cb.ADD, c, ref, (S) service); + } + + void change(Component c, ServiceReference<S> ref, Object service) { + invokeMethodRefs(Cb.CHG, c, ref, (S) service); + } + + void remove(Component c, ServiceReference<S> ref, Object service) { + invokeMethodRefs(Cb.REM, c, ref, (S) service); + } + + void swap(Component c, ServiceReference<S> oldRef, Object oldSrv, ServiceReference<S> newRef, Object newSrv) { + invokeSwapMethodRefs(c, oldRef, (S) oldSrv, newRef, (S) newSrv); + } + }; + + return cb; + } + + boolean hasRefs() { + return m_refs.size() > 0 || m_swapRefs.size() > 0; + } + + boolean hasCallbacks() { + return m_callbackInstance != null || m_added != null || m_changed != null || m_removed != null || m_swapped != null; + } + + String getAutoConfigField() { + return m_autoConfigField; + } + + Object getCallbackInstance() { + return m_callbackInstance; + } + + String getAdded() { + return m_added; + } + + String getChanged() { + return m_changed; + } + + String getRemoved() { + return m_removed; + } + + String getSwapped() { + return m_swapped; + } + + private void invokeMethodRefs(Cb cbType, Component comp, ServiceReference<S> ref, S service) { + m_refs.computeIfPresent(cbType, (k, mrefs) -> { + mrefs.forEach(mref -> mref.accept(null, comp, ref, service)); + return mrefs; + }); + } + + private void invokeSwapMethodRefs(Component c, ServiceReference<S> oref, S osrv, ServiceReference<S> nref, S nsrv) { + m_swapRefs.forEach(ref -> ref.accept(null, c, oref, osrv, nref, nsrv)); + } + + private void requiresNoCallbacks() { + if (hasCallbacks()) { + throw new IllegalStateException("can't mix method references and string callbacks."); + } + } + + private void requiresNoMethodRefs() { + if (hasRefs()) { + throw new IllegalStateException("can't mix method references and string callbacks."); + } + } +} Added: felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ServiceDependencyBuilderImpl.java URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ServiceDependencyBuilderImpl.java?rev=1727869&view=auto ============================================================================== --- felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ServiceDependencyBuilderImpl.java (added) +++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ServiceDependencyBuilderImpl.java Sun Jan 31 23:27:05 2016 @@ -0,0 +1,148 @@ +package org.apache.felix.dm.lambda.impl; + +import java.util.Dictionary; +import java.util.function.BiFunction; +import java.util.function.Function; + +import org.apache.felix.dm.Component; +import org.apache.felix.dm.DependencyManager; +import org.apache.felix.dm.ServiceDependency; +import org.apache.felix.dm.lambda.ServiceDependencyBuilder; +import org.osgi.framework.ServiceReference; + +public class ServiceDependencyBuilderImpl<S> extends ServiceCallbacksBuilderImpl<S, ServiceDependencyBuilder<S>> implements ServiceDependencyBuilder<S> { + private final Class<S> m_serviceIface; + private final Component m_component; + private String m_filter; + private ServiceReference<S> m_ref; + private boolean m_required = true; + private String m_debug; + private boolean m_propagate; + private Object m_propagateInstance; + private String m_propagateMethod; + private Object m_defaultImpl; + private long m_timeout = -1; + + public ServiceDependencyBuilderImpl(Component component, Class<S> service) { + super(service); + m_serviceIface = service; + m_component = component; + } + + public ServiceDependencyBuilder<S> filter(String filter) { + m_filter = filter; + return this; + } + + public ServiceDependencyBuilder<S> ref(ServiceReference<S> ref) { + m_ref = ref; + return this; + } + + public ServiceDependencyBuilder<S> optional() { + return required(false); + } + + public ServiceDependencyBuilder<S> required() { + return required(true); + } + + public ServiceDependencyBuilder<S> required(boolean required) { + m_required = required; + return this; + } + + public ServiceDependencyBuilder<S> debug(String label) { + m_debug = label; + return this; + } + + public ServiceDependencyBuilder<S> propagate() { + return propagate(true); + } + + public ServiceDependencyBuilder<S> propagate(boolean propagate) { + m_propagate = propagate; + return this; + } + + public ServiceDependencyBuilder<S> propagate(Object instance, String method) { + m_propagateInstance = instance; + m_propagateMethod = method; + return this; + } + + public ServiceDependencyBuilder<S> propagate(Function<ServiceReference<S>, Dictionary<String, Object>> propagate) { + Object wrappedCallback = new Object() { + @SuppressWarnings("unused") + Dictionary<String, Object> propagate(ServiceReference<S> ref) { + return propagate.apply(ref); + } + }; + propagate(wrappedCallback, "propagate"); + return this; + } + + public ServiceDependencyBuilder<S> propagate(BiFunction<ServiceReference<S>, S, Dictionary<String, Object>> propagate) { + Object wrappedCallback = new Object() { + @SuppressWarnings("unused") + Dictionary<String, Object> propagate(ServiceReference<S> ref, S service) { + return propagate.apply(ref, service); + } + }; + propagate(wrappedCallback, "propagate"); + return this; + } + + public ServiceDependencyBuilder<S> defImpl(Object defaultImpl) { + m_defaultImpl = defaultImpl; + return this; + } + + public ServiceDependencyBuilder<S> timeout(long timeout) { + m_timeout = timeout; + return this; + } + + // Build final ServiceDependency object. + @Override + public ServiceDependency build() { + DependencyManager dm = m_component.getDependencyManager(); + if (m_ref != null && m_filter != null) { + throw new IllegalArgumentException("Can not set ref and filter at the same time"); + } + ServiceDependency sd = m_timeout > -1 ? dm.createTemporalServiceDependency(m_timeout) : dm.createServiceDependency(); + if (m_ref != null) { + sd.setService(m_serviceIface, m_ref); + } else { + sd.setService(m_serviceIface, m_filter); + } + sd.setRequired(m_required); + sd.setDefaultImplementation(m_defaultImpl); + if (m_debug != null) { + sd.setDebug(m_debug); + } + if (m_propagate) { + sd.setPropagate(true); + } else if (m_propagateInstance != null) { + if (m_propagateMethod == null) { + throw new IllegalArgumentException("propagate instance can't be null"); + } + sd.setPropagate(m_propagateInstance, m_propagateMethod); + } + if (hasCallbacks()) { + sd.setCallbacks(m_callbackInstance, m_added, m_changed, m_removed, m_swapped); + } else if (hasRefs()) { + Object cb = createCallbackInstance(); + sd.setCallbacks(cb, "add", "change", "remove", m_swapRefs.size() > 0 ? "swap" : null); + } + + if (m_autoConfigField != null) { + sd.setAutoConfig(m_autoConfigField); + } else { + sd.setAutoConfig(m_autoConfig); + } + return sd; + } + +} Added: felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/packageinfo URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/packageinfo?rev=1727869&view=auto ============================================================================== --- felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/packageinfo (added) +++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/packageinfo Sun Jan 31 23:27:05 2016 @@ -0,0 +1 @@ +version 1.0.0 \ No newline at end of file Added: felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/test/.gitignore URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/test/.gitignore?rev=1727869&view=auto ============================================================================== (empty) Modified: felix/trunk/dependencymanager/org.apache.felix.dependencymanager.runtime.itest/bnd.bnd URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.runtime.itest/bnd.bnd?rev=1727869&r1=1727868&r2=1727869&view=diff ============================================================================== --- felix/trunk/dependencymanager/org.apache.felix.dependencymanager.runtime.itest/bnd.bnd (original) +++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager.runtime.itest/bnd.bnd Sun Jan 31 23:27:05 2016 @@ -32,7 +32,7 @@ org.apache.felix.dependencymanager.shell;version=latest,\ biz.aQute.junit;version=3.0.0 -runee: JavaSE-1.7 --runfw: org.apache.felix.framework;version='[4.4.0,4.4.0]' +-runfw: org.apache.felix.framework;version='[5.2.0,5.2.0]' -runsystempackages: \ sun.reflect -runvm:-ea @@ -42,6 +42,11 @@ Private-Package: \ org.apache.felix.dm.itest.util -plugin: org.apache.felix.dm.annotation.plugin.bnd.AnnotationPlugin;log=debug;\ path:=${workspace}/org.apache.felix.dependencymanager.annotation/generated/org.apache.felix.dependencymanager.annotation.jar +-runproperties: \ + org.apache.felix.dependencymanager.loglevel=2,\ + org.apache.felix.log.maxSize=100000,\ + org.apache.felix.log.storeDebug=true,\ + gosh.args=--noshutdown Test-Cases: \ ${classes;CONCRETE;EXTENDS;junit.framework.TestCase} Bundle-Name: Apache Felix Dependency Manager Runtime integration tests
