Added: 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/BundleAdapterBuilderImpl.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/BundleAdapterBuilderImpl.java?rev=1727869&view=auto
==============================================================================
--- 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/BundleAdapterBuilderImpl.java
 (added)
+++ 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/BundleAdapterBuilderImpl.java
 Sun Jan 31 23:27:05 2016
@@ -0,0 +1,260 @@
+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.function.Consumer;
+import java.util.stream.Stream;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.lambda.BundleAdapterBuilder;
+import org.apache.felix.dm.lambda.ComponentBuilder;
+import org.apache.felix.dm.lambda.callbacks.CbBundle;
+import org.apache.felix.dm.lambda.callbacks.CbComponentBundle;
+import org.apache.felix.dm.lambda.callbacks.CbTypeBundle;
+import org.apache.felix.dm.lambda.callbacks.CbTypeComponentBundle;
+import org.osgi.framework.Bundle;
+
+public class BundleAdapterBuilderImpl implements 
AdapterBase<BundleAdapterBuilder>, BundleAdapterBuilder {
+    private Consumer<ComponentBuilder<?>> m_compBuilder = (compBuilder -> {});
+    protected final Map<Cb, List<MethodRef<Object>>> m_refs = new HashMap<>();
+    private DependencyManager m_dm;
+    private boolean m_autoAdd;
+    private String m_added;
+    private String m_changed;
+    private String m_removed;
+    private String m_filter;
+    private int m_stateMask = -1;
+    private boolean m_propagate;
+    private Object m_callbackInstance;
+    private String m_add;
+    private String m_change;
+    private String m_remove;
+
+    enum Cb {
+        ADD,        
+        CHG,        
+        REM
+    };
+
+    @FunctionalInterface
+    interface MethodRef<I> {
+        public void accept(I instance, Component c, Bundle b);
+    }
+
+    public BundleAdapterBuilderImpl(DependencyManager dm) {
+        m_dm = dm;
+    }
+    
+    public void andThenBuild(Consumer<ComponentBuilder<?>> builder) {
+        m_compBuilder = m_compBuilder.andThen(builder);
+    }
+
+    @Override
+    public BundleAdapterBuilderImpl autoAdd(boolean autoAdd) {
+        m_autoAdd = autoAdd;
+        return this;
+    }
+        
+    public boolean isAutoAdd() {
+        return m_autoAdd;
+    }
+
+    public BundleAdapterBuilder mask(int mask) {
+        m_stateMask = mask;
+        return this;
+    }
+    
+    public BundleAdapterBuilder filter(String filter) {
+        m_filter = filter;
+        return this;
+    }
+
+    public BundleAdapterBuilder propagate(boolean propagate) {
+        m_propagate = propagate;
+        return this;
+    }
+    
+    public BundleAdapterBuilder propagate() {
+        m_propagate = true;
+        return this;
+    }
+
+    public BundleAdapterBuilder cb(String ... callbacks) {
+        return cbi(null, callbacks);
+    }
+    
+    public BundleAdapterBuilder cbi(Object callbackInstance, String ... 
callbacks) {
+        switch (callbacks.length) {
+        case 1:
+            return cbi(callbackInstance, callbacks[0], null, null);
+            
+        case 2:
+            return cbi(callbackInstance, callbacks[0], null, callbacks[1]);
+            
+        case 3:
+            return cbi(callbackInstance, callbacks[0], callbacks[1], 
callbacks[2]);
+            
+        default:
+            throw new IllegalArgumentException("wrong number of arguments: " + 
callbacks.length + ". " +
+                "Possible arguments: [add], [add, remove] or [add, change, 
remove]");
+        }
+    }
+    
+    private BundleAdapterBuilder cbi(Object callbackInstance, String add, 
String change, String remove) {
+        checkHasNoMethodRefs();
+        m_callbackInstance = callbackInstance;
+        m_add = add;
+        m_change = change;
+        m_remove = remove;
+        return this;
+    }
+    
+    public <T> BundleAdapterBuilder cb(CbTypeBundle<T> add) {
+        return cb(add, (CbTypeBundle<T>) null, (CbTypeBundle<T>) null);
+    }
+
+    public <T> BundleAdapterBuilder cb(CbTypeBundle<T> add, CbTypeBundle<T> 
remove) {
+        return cb(add, null, remove);
+    }
+
+    public <T> BundleAdapterBuilder cb(CbTypeBundle<T> add, CbTypeBundle<T> 
change, CbTypeBundle<T> remove) {
+        if (add != null) {
+            Class<T> type = Helpers.getLambdaArgType(add, 0);
+            setComponentCallbackRef(Cb.ADD, type, (instance, component, 
bundle) -> { add.accept((T) instance, bundle); });
+        }
+        if (change != null) {
+            Class<T> type = Helpers.getLambdaArgType(change, 0);
+            setComponentCallbackRef(Cb.CHG, type, (instance, component, 
bundle) -> { change.accept((T) instance, bundle); });
+        }
+        if (remove != null) {
+            Class<T> type = Helpers.getLambdaArgType(remove, 0);
+            setComponentCallbackRef(Cb.REM, type, (instance, component, 
bundle) -> { remove.accept((T) instance, bundle); });
+        }
+        return this;
+    }
+    
+    public BundleAdapterBuilder cbi(CbBundle add) {
+        return cbi(add, null, null);
+    }
+
+    public BundleAdapterBuilder cbi(CbBundle add, CbBundle remove) {
+        return cbi(add, null, remove);
+    }
+    
+    public BundleAdapterBuilder cbi(CbBundle add, CbBundle change, CbBundle 
remove) {
+        if (add != null) setInstanceCallbackRef(Cb.ADD, (instance, component, 
bundle) -> { add.accept(bundle); });
+        if (change != null) setInstanceCallbackRef(Cb.CHG, (instance, 
component, bundle) -> { change.accept(bundle); });
+        if (remove != null) setInstanceCallbackRef(Cb.REM, (instance, 
component, bundle) -> { remove.accept(bundle); });
+        return this;
+    }
+    
+    public <T> BundleAdapterBuilder cb(CbTypeComponentBundle<T> add) {
+        return cb((CbTypeComponentBundle<T>) add, (CbTypeComponentBundle<T>) 
null, (CbTypeComponentBundle<T>) null);
+    }
+    
+    public <T> BundleAdapterBuilder cb(CbTypeComponentBundle<T> add, 
CbTypeComponentBundle<T> remove) {
+        return cb(add, null, remove);
+    }
+    
+    public <T> BundleAdapterBuilder cb(CbTypeComponentBundle<T> add, 
CbTypeComponentBundle<T> change, CbTypeComponentBundle<T> remove) {
+        if (add != null) {
+            Class<T> type = Helpers.getLambdaArgType(add, 0);
+            return setComponentCallbackRef(Cb.ADD, type, (instance, component, 
bundle) -> { add.accept((T) instance, component, bundle); });
+        }
+        if (change != null) {
+            Class<T> type = Helpers.getLambdaArgType(change, 0);
+            return setComponentCallbackRef(Cb.CHG, type, (instance, component, 
bundle) -> { change.accept((T) instance, component, bundle); });
+        }
+        if (remove != null) {
+            Class<T> type = Helpers.getLambdaArgType(remove, 0);
+            return setComponentCallbackRef(Cb.ADD, type, (instance, component, 
bundle) -> { remove.accept((T) instance, component, bundle); });
+        }
+        return this;
+    }
+    
+    public BundleAdapterBuilder cbi(CbComponentBundle add) {
+        return cbi(add, null, null);
+    }
+    
+    public BundleAdapterBuilder cbi(CbComponentBundle add, CbComponentBundle 
remove) {
+        return cbi(add, null, remove);
+    }
+
+    public BundleAdapterBuilder cbi(CbComponentBundle add, CbComponentBundle 
change, CbComponentBundle remove) {
+        if (add != null) setInstanceCallbackRef(Cb.ADD, (instance, component, 
bundle) -> { add.accept(component, bundle); });
+        if (change != null) setInstanceCallbackRef(Cb.CHG, (instance, 
component, bundle) -> { change.accept(component, bundle); });
+        if (remove != null) setInstanceCallbackRef(Cb.REM, (instance, 
component, bundle) -> { remove.accept(component, bundle); });
+        return this;
+    }
+
+    @Override
+    public Component build() { 
+        Component c = null;
+        
+        if (m_refs.size() > 0) {
+            @SuppressWarnings("unused")
+            Object wrapCallback = new Object() {
+                public void add(Component comp, Bundle bundle) {
+                    invokeMethodRefs(Cb.ADD, comp, bundle);
+                }
+                
+                public void change(Component comp, Bundle bundle) {
+                    invokeMethodRefs(Cb.CHG, comp, bundle);
+                }
+
+                public void remove(Component comp, Bundle bundle) {
+                    invokeMethodRefs(Cb.REM, comp, bundle);
+                }
+            };
+            c = m_dm.createBundleAdapterService(m_stateMask, m_filter, 
m_propagate, wrapCallback, "add", "change", "remove");
+        } else {
+            c = m_dm.createBundleAdapterService(m_stateMask, m_filter, 
m_propagate, m_callbackInstance, m_add, m_change, m_remove);
+        }
+        ComponentBuilderImpl cb = new ComponentBuilderImpl(c, false);
+        m_compBuilder.accept (cb);
+        return cb.build();        
+    }
+    
+    private <U> BundleAdapterBuilder setInstanceCallbackRef(Cb cbType, 
MethodRef<U> ref) {
+        checkHasNoReflectionCallbacks();
+        List<MethodRef<Object>> list = m_refs.computeIfAbsent(cbType, l -> new 
ArrayList<>());
+        list.add((instance, component, bundle) -> ref.accept(null, component, 
bundle));
+        return this;
+    }
+    
+    @SuppressWarnings("unchecked")
+    private <U> BundleAdapterBuilder setComponentCallbackRef(Cb cbType, 
Class<U> type, MethodRef<U> ref) {
+        checkHasNoReflectionCallbacks();
+        List<MethodRef<Object>> list = m_refs.computeIfAbsent(cbType, l -> new 
ArrayList<>());
+        list.add((instance, component, bundle) -> {
+            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((U) componentImpl, component, bundle);
+        });
+        return this;
+    }
+    
+    private void invokeMethodRefs(Cb cbType, Component comp, Bundle bundle) {
+        m_refs.computeIfPresent(cbType, (k, mrefs) -> {
+            mrefs.forEach(mref -> mref.accept(null, comp, bundle));
+            return mrefs;
+         });
+     }
+
+    private void checkHasNoMethodRefs() {
+        if (m_refs.size() > 0) {
+            throw new IllegalStateException("Can't mix method references with 
reflection based callbacks");
+        }
+    }
+    
+    private void checkHasNoReflectionCallbacks() {
+        if (m_added != null || m_changed != null || m_removed != null) {
+            throw new IllegalStateException("Can't mix method references with 
reflection based callbacks");
+        }
+    }
+}

Added: 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/BundleDependencyBuilderImpl.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/BundleDependencyBuilderImpl.java?rev=1727869&view=auto
==============================================================================
--- 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/BundleDependencyBuilderImpl.java
 (added)
+++ 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/BundleDependencyBuilderImpl.java
 Sun Jan 31 23:27:05 2016
@@ -0,0 +1,359 @@
+package org.apache.felix.dm.lambda.impl;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Supplier;
+import java.util.stream.Stream;
+
+import org.apache.felix.dm.BundleDependency;
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.lambda.BundleDependencyBuilder;
+import org.apache.felix.dm.lambda.callbacks.CbBundle;
+import org.apache.felix.dm.lambda.callbacks.CbComponentBundle;
+import org.apache.felix.dm.lambda.callbacks.CbTypeBundle;
+import org.apache.felix.dm.lambda.callbacks.CbTypeComponentBundle;
+import org.osgi.framework.Bundle;
+
+@SuppressWarnings("unchecked")
+public class BundleDependencyBuilderImpl implements BundleDependencyBuilder {
+       private String m_added;
+       private String m_changed;
+       private String m_removed;
+       private Object m_instance;
+       private boolean m_autoConfig = true;
+       private boolean m_autoConfigInvoked = false;
+       private boolean m_required = true;
+       private Bundle m_bundle;
+       private String m_filter;
+       private int m_stateMask = -1;
+       private boolean m_propagate;
+       private Object m_propagateInstance;
+       private String m_propagateMethod;
+       private Supplier<Dictionary<?, ?>> m_propagateSupplier;
+       private final Component m_component;
+    
+    enum Cb {
+        ADD,        
+        CHG,        
+        REM
+    };
+
+       private final Map<Cb, List<MethodRef<Object>>> m_refs = new HashMap<>();
+
+    @FunctionalInterface
+    interface MethodRef<I> {
+        public void accept(I instance, Component c, Bundle bundle);
+    }
+
+       /**
+        * Class used to call a supplier that returns Propagated properties
+        */
+       private class Propagate {
+               @SuppressWarnings("unused")
+               Dictionary<?, ?> propagate() {
+                       return m_propagateSupplier.get();
+               }
+       }
+
+    public BundleDependencyBuilderImpl (Component component) {
+        m_component = component;
+    }
+
+    @Override
+    public BundleDependencyBuilder autoConfig(boolean autoConfig) {
+        m_autoConfig = autoConfig;
+        m_autoConfigInvoked = true;
+        return this;
+    }
+
+    @Override
+    public BundleDependencyBuilder autoConfig() {
+        autoConfig(true);
+        return this;
+    }
+
+    @Override
+    public BundleDependencyBuilder required(boolean required) {
+        m_required = required;
+        return this;
+    }
+
+    @Override
+    public BundleDependencyBuilder required() {
+        required(true);
+        return this;
+    }
+
+    @Override
+    public BundleDependencyBuilder bundle(Bundle bundle) {
+        m_bundle = bundle;
+        return this;
+    }
+
+    @Override
+    public BundleDependencyBuilder filter(String filter) throws 
IllegalArgumentException {
+        m_filter = filter;
+        return this;
+    }
+
+    @Override
+    public BundleDependencyBuilder mask(int mask) {
+        m_stateMask = mask;
+        return this;
+    }
+
+    @Override
+    public BundleDependencyBuilder propagate(boolean propagate) {
+        m_propagate = propagate;
+        return this;
+    }
+
+    @Override
+    public BundleDependencyBuilder propagate() {
+        propagate(true);
+        return this;
+    }
+
+    @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 BundleDependencyBuilder propagate(Supplier<Dictionary<?, ?>> 
instance) {
+        if (m_propagateInstance != null || m_propagate) throw new 
IllegalStateException("Propagate callback already set.");
+        m_propagateSupplier = instance;
+        return this;
+    }
+        
+    public BundleDependencyBuilder cb(String ... callbacks) {
+        return cb(null, callbacks);
+    }
+    
+    @Override
+    public BundleDependencyBuilder cb(Object callbackInstance, String ... 
callbacks) {
+        switch (callbacks.length) {
+        case 1:
+            cbi(callbackInstance, callbacks[0], null, null);
+            break;
+            
+        case 2:
+            cbi(callbackInstance, callbacks[0], null, callbacks[1]);
+            break;
+            
+        case 3:
+            cbi(callbackInstance, callbacks[0], callbacks[1], callbacks[2]);
+            break;
+            
+        default:
+            throw new IllegalArgumentException("wrong number of arguments: " + 
callbacks.length + ". " +
+                "Possible arguments: [add], [add, remove] or [add, change, 
remove]");
+        }
+
+        return this;
+    }
+    
+    private BundleDependencyBuilder cbi(Object callbackInstance, String added, 
String changed, String removed) {
+        requiresNoMethodRefs();
+        m_instance = callbackInstance;
+        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;
+    }
+
+    @Override
+    public <T> BundleDependencyBuilder cb(CbTypeBundle<T> add) {
+        return cb(add, null, null);
+    }
+    
+    @Override
+    public <T> BundleDependencyBuilder cb(CbTypeBundle<T> add, CbTypeBundle<T> 
remove) {
+        return cb(add, null, remove);
+    }
+    
+    @Override
+    public <T> BundleDependencyBuilder cb(CbTypeBundle<T> add, CbTypeBundle<T> 
change, CbTypeBundle<T> remove) {
+        if (add != null) {
+            setComponentCallbackRef(Cb.ADD, Helpers.getLambdaArgType(add, 0), 
(inst, component, bundle) -> add.accept ((T) inst, bundle));
+        }
+        if (change != null) {
+            setComponentCallbackRef(Cb.CHG, Helpers.getLambdaArgType(change, 
0), (inst, component, bundle) -> change.accept ((T) inst, bundle));
+        }
+        if (remove != null) {
+            setComponentCallbackRef(Cb.REM, Helpers.getLambdaArgType(remove, 
0), (inst, component, bundle) -> remove.accept ((T) inst, bundle));
+        }
+        return this;
+    }
+
+    @Override
+    public <T> BundleDependencyBuilder cb(CbTypeComponentBundle<T> add) {
+        return cb(add, null, null);
+    }
+    
+    @Override
+    public <T> BundleDependencyBuilder cb(CbTypeComponentBundle<T> add, 
CbTypeComponentBundle<T> remove) {
+        return cb(add, null, remove);
+    }
+    
+    @Override
+    public <T> BundleDependencyBuilder cb(CbTypeComponentBundle<T> add, 
CbTypeComponentBundle<T> change, CbTypeComponentBundle<T> remove) {
+        if (add != null) {
+            setComponentCallbackRef(Cb.ADD, Helpers.getLambdaArgType(add, 0), 
(inst, component, bundle) -> add.accept ((T) inst, component, bundle));
+        }
+        if (change != null) {
+            setComponentCallbackRef(Cb.CHG, Helpers.getLambdaArgType(change, 
0), (inst, component, bundle) -> change.accept ((T) inst, component, bundle));
+        }
+        if (remove != null) {
+            setComponentCallbackRef(Cb.REM, Helpers.getLambdaArgType(remove, 
0), (inst, component, bundle) -> remove.accept ((T) inst, component, bundle));
+        }
+        return this;  
+    }
+    
+    @Override
+    public BundleDependencyBuilder cbi(CbBundle add) {
+        return cbi(add, null, null);
+    }
+    
+    @Override
+    public BundleDependencyBuilder cbi(CbBundle add, CbBundle remove) {
+        return cbi(add, null, remove);
+    }
+    
+    @Override
+    public BundleDependencyBuilder cbi(CbBundle add, CbBundle change, CbBundle 
remove) {
+        if (add != null) setInstanceCallbackRef(Cb.ADD, (inst, component, 
bundle) -> add.accept(bundle));
+        if (change != null) setInstanceCallbackRef(Cb.CHG, (inst, component, 
bundle) -> change.accept(bundle));
+        if (remove != null) setInstanceCallbackRef(Cb.REM, (inst, component, 
bundle) -> remove.accept(bundle));
+        return this;
+    }
+
+    @Override
+    public BundleDependencyBuilder cbi(CbComponentBundle add) {
+        return cbi(add, null, null);
+    }
+    
+    @Override
+    public BundleDependencyBuilder cbi(CbComponentBundle add, 
CbComponentBundle remove) {
+        return cbi(add, null, remove);
+    }
+    
+    @Override
+    public BundleDependencyBuilder cbi(CbComponentBundle add, 
CbComponentBundle change, CbComponentBundle remove) {
+        if (add != null) setInstanceCallbackRef(Cb.ADD, (inst, component, 
bundle) -> add.accept(component, bundle));
+        if (change != null) setInstanceCallbackRef(Cb.CHG, (inst, component, 
bundle) -> change.accept(component, bundle));
+        if (remove != null) setInstanceCallbackRef(Cb.REM, (inst, component, 
bundle) -> remove.accept(component, bundle));
+        return this;
+    }
+
+       @Override
+       public BundleDependency build() {
+        DependencyManager dm = m_component.getDependencyManager();
+
+        BundleDependency dep = dm.createBundleDependency();
+        dep.setRequired(m_required);
+        
+        if (m_filter != null) {
+               dep.setFilter(m_filter);
+        }
+        
+        if (m_bundle != null) {
+               dep.setBundle(m_bundle);
+        }
+        
+        if (m_stateMask != -1) {
+               dep.setStateMask(m_stateMask);
+        }
+        
+        if (m_propagate) {
+            dep.setPropagate(true);
+        } else if (m_propagateInstance != null) {
+            dep.setPropagate(m_propagateInstance, m_propagateMethod);
+        } else if (m_propagateSupplier != null) {
+               dep.setPropagate(new Propagate(), "propagate");
+        }
+        
+        if (m_added != null || m_changed != null || m_removed != null) {
+            dep.setCallbacks(m_instance, m_added, m_changed, m_removed);
+        } else if (m_refs.size() > 0) {
+            Object cb = createCallbackInstance();
+            dep.setCallbacks(cb, "add", "change", "remove");
+        } 
+        
+        dep.setAutoConfig(m_autoConfig);
+        return dep;
+       }
+
+       private <T> BundleDependencyBuilder setInstanceCallbackRef(Cb cbType, 
MethodRef<T> ref) {
+               requiresNoStringCallbacks();
+               if (! m_autoConfigInvoked) m_autoConfig = false;
+               List<MethodRef<Object>> list = m_refs.computeIfAbsent(cbType, l 
-> new ArrayList<>());
+               list.add((instance, component, bundle) -> ref.accept(null, 
component, bundle));
+               return this;
+       }
+       
+       private <T> BundleDependencyBuilder setComponentCallbackRef(Cb cbType, 
Class<T> type, MethodRef<T> ref) {
+           requiresNoStringCallbacks();
+               if (! m_autoConfigInvoked) m_autoConfig = false;
+               List<MethodRef<Object>> list = m_refs.computeIfAbsent(cbType, l 
-> new ArrayList<>());
+               list.add((instance, component, bundle) -> {
+            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((T) componentImpl, component, bundle);
+               });
+               return this;
+       }
+           
+       @SuppressWarnings("unused")
+       private Object createCallbackInstance() {
+               Object cb = null;
+
+               cb = new Object() {
+                       void add(Component c, Bundle bundle) {
+                               invokeMethodRefs(Cb.ADD, c, bundle);
+                       }
+
+                       void change(Component c, Bundle bundle) {
+                               invokeMethodRefs(Cb.CHG, c, bundle);
+                       }
+
+                       void remove(Component c, Bundle bundle) {
+                               invokeMethodRefs(Cb.REM, c, bundle);
+                       }
+               };
+
+               return cb;
+       }
+
+       private void invokeMethodRefs(Cb cbType, Component c, Bundle bundle) {
+               m_refs.computeIfPresent(cbType, (k, mrefs) -> {
+                       mrefs.forEach(mref -> mref.accept(null, c, bundle));
+                       return mrefs;
+               });
+       }
+       
+       private void requiresNoStringCallbacks() {
+               if (m_added != null || m_changed != null || m_removed != null) {
+                       throw new IllegalStateException("can't mix method 
references and string callbacks.");
+               }
+       }
+       
+       private void requiresNoMethodRefs() {
+               if (m_refs.size() > 0) {
+                       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/CompletableFutureDependencyImpl.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/CompletableFutureDependencyImpl.java?rev=1727869&view=auto
==============================================================================
--- 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/CompletableFutureDependencyImpl.java
 (added)
+++ 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/CompletableFutureDependencyImpl.java
 Sun Jan 31 23:27:05 2016
@@ -0,0 +1,241 @@
+package org.apache.felix.dm.lambda.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
+import java.util.stream.Stream;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.Dependency;
+import org.apache.felix.dm.context.AbstractDependency;
+import org.apache.felix.dm.context.DependencyContext;
+import org.apache.felix.dm.context.Event;
+import org.apache.felix.dm.context.EventType;
+import org.apache.felix.dm.lambda.FutureDependencyBuilder;
+import org.apache.felix.dm.lambda.callbacks.CbFuture;
+import org.apache.felix.dm.lambda.callbacks.CbTypeFuture;
+import org.osgi.service.log.LogService;
+
+public class CompletableFutureDependencyImpl<F> extends 
AbstractDependency<CompletableFutureDependencyImpl<F>> implements 
FutureDependencyBuilder<F> {
+
+       private final CompletableFuture<F> m_future;
+       private Component m_comp;
+       private boolean m_async;
+       private Executor m_exec;
+    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;
+       }
+
+       /**
+        * Create a new PathDependency from an existing prototype.
+        * 
+        * @param prototype
+        *            the existing PathDependency.
+        */
+       public CompletableFutureDependencyImpl(Component component, 
CompletableFutureDependencyImpl<F> prototype) {
+               super(prototype);
+               m_future = prototype.m_future;
+               m_comp = component;
+       }
+
+       @Override
+       public Dependency build() {
+               return this;
+       }
+
+       @Override
+    public FutureDependencyBuilder<F> cb(String callback) {
+           return cbi(null, callback);
+       }
+       
+       @Override
+    public FutureDependencyBuilder<F> cbi(Object callbackInstance, String 
callback) {
+           super.setCallbacks(callbackInstance, callback, null);
+           return this;
+       }
+
+       @Override
+       public <T> FutureDependencyBuilder<F> cb(CbTypeFuture<T, ? super F> 
consumer) {
+           return cb(consumer, false);
+       }
+
+       @SuppressWarnings("unchecked")
+       @Override
+       public <T> FutureDependencyBuilder<F> cb(CbTypeFuture<T, ? super F> 
consumer, boolean async) {
+           m_accept2Type = Helpers.getLambdaArgType(consumer, 0);;
+           m_accept2 = (instance, result) -> consumer.accept((T) instance, 
result);
+           m_async = async;
+           return this;
+       }   
+
+       @Override
+       public <T> FutureDependencyBuilder<F> cb(CbTypeFuture<T, ? super F> 
consumer, Executor executor) {
+           cb(consumer, true /* async */);
+           m_exec = executor;
+           return this;
+       }
+
+       @Override
+       public FutureDependencyBuilder<F> cbi(CbFuture<? super F> consumer) {
+           cbi(consumer, false);
+               return this;
+       }
+       
+       @Override
+       public FutureDependencyBuilder<F> cbi(CbFuture<? super F> consumer, 
boolean async) {
+           m_accept = m_accept.andThen(future -> consumer.accept(future));
+           m_async = async;
+           return this;
+       }   
+
+    @Override
+    public FutureDependencyBuilder<F> cbi(CbFuture<? super F> consumer, 
Executor executor) {
+        cbi(consumer, true /* async */);
+        m_exec = executor;
+        return this;
+    }
+
+       // ---------- DependencyContext interface ----------
+
+       @Override
+       public void start() {
+               try {
+                       if (m_async) {
+                               if (m_exec != null) {
+                                       m_future.whenCompleteAsync((result, 
error) -> completed(result, error), m_exec);
+                               } else {
+                                       m_future.whenCompleteAsync((result, 
error) -> completed(result, error));
+                               }
+                       } else {
+                               m_future.whenComplete((result, error) -> 
completed(result, error));
+                       }
+               } catch (Throwable error) {
+                       
super.getComponentContext().getLogger().log(LogService.LOG_ERROR, "completable 
future failed", error);
+               }
+               super.start();
+       }
+
+       @Override
+       public DependencyContext createCopy() {
+               return new CompletableFutureDependencyImpl<F>(m_comp, this);
+       }
+
+       @Override
+       public Class<?> getAutoConfigType() {
+               return null; // we don't support auto config mode
+       }
+
+       // ---------- ComponentDependencyDeclaration interface -----------
+
+       /**
+        * Returns the name of this dependency (a generic name with optional 
info
+        * separated by spaces). The DM Shell will use this method when 
displaying
+        * the dependency
+        **/
+       @Override
+       public String getSimpleName() {
+               return m_future.toString();
+       }
+
+       /**
+        * Returns the name of the type of this dependency. Used by the DM shell
+        * when displaying the dependency.
+        **/
+       @Override
+       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:
+                if (m_add != null) {
+                    // Inject result by reflection on a method name
+                    injectByReflection(events[0].getEvent());
+                    return;
+                }
+                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 -----------
+
+    /**
+     * 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 {
+                   // 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));
+               }
+       }
+    
+    /**
+     * Injects the completed fiture result in a method by reflection.
+     * We try to find a method which has in its signature a parameter that is 
compatible with the future result
+     * (including any interfaces the result may implements).
+     * 
+     * @param result the result of the completable future.
+     */
+    private void injectByReflection(Object result) {
+        List<Class<?>> types = new ArrayList<>();
+        Class<?> currentClazz = result.getClass();
+        
+        while (currentClazz != null && currentClazz != Object.class) {
+            types.add(currentClazz);
+            Stream.of(currentClazz.getInterfaces()).forEach(types::add);
+            currentClazz = currentClazz.getSuperclass();
+        }
+        
+        Class<?>[][] classes = new Class<?>[types.size() + 1][1];
+        Object[][] results = new Object[types.size() + 1][1];
+        for (int i = 0; i < types.size(); i ++) {
+            classes[i] = new Class<?>[] { types.get(i) };
+            results[i] = new Object[] { result };
+        }
+        classes[types.size()] = new Class<?>[0];
+        results[types.size()] = new Object[0];        
+        m_component.invokeCallbackMethod(getInstances(), m_add, classes, 
results);
+    }
+}

Added: 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ComponentBuilderImpl.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ComponentBuilderImpl.java?rev=1727869&view=auto
==============================================================================
--- 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ComponentBuilderImpl.java
 (added)
+++ 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ComponentBuilderImpl.java
 Sun Jan 31 23:27:05 2016
@@ -0,0 +1,728 @@
+package org.apache.felix.dm.lambda.impl;
+
+import static 
org.apache.felix.dm.lambda.impl.ComponentBuilderImpl.ComponentCallback.DESTROY;
+import static 
org.apache.felix.dm.lambda.impl.ComponentBuilderImpl.ComponentCallback.INIT;
+import static 
org.apache.felix.dm.lambda.impl.ComponentBuilderImpl.ComponentCallback.START;
+import static 
org.apache.felix.dm.lambda.impl.ComponentBuilderImpl.ComponentCallback.STOP;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Properties;
+import java.util.concurrent.CompletableFuture;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Stream;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.Dependency;
+import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.lambda.BundleDependencyBuilder;
+import org.apache.felix.dm.lambda.ComponentBuilder;
+import org.apache.felix.dm.lambda.ConfigurationDependencyBuilder;
+import org.apache.felix.dm.lambda.DependencyBuilder;
+import org.apache.felix.dm.lambda.FluentProperties;
+import org.apache.felix.dm.lambda.FutureDependencyBuilder;
+import org.apache.felix.dm.lambda.ServiceDependencyBuilder;
+import org.apache.felix.dm.lambda.callbacks.CbComponent;
+import org.apache.felix.dm.lambda.callbacks.CbConsumer;
+import org.apache.felix.dm.lambda.callbacks.CbTypeComponent;
+
+public class ComponentBuilderImpl implements 
ComponentBuilder<ComponentBuilderImpl> {
+    private final List<DependencyBuilder<?>> m_dependencyBuilders = new 
ArrayList<>();
+    private final Component m_component;
+    private final boolean m_componentUpdated;
+    private String[] m_serviceNames;
+    private Dictionary<Object, Object> m_properties;
+    private Object m_impl;
+    private Object m_factory;
+    private boolean m_factoryHasComposite;     
+    private boolean m_autoAdd = true;
+    protected final Map<ComponentCallback, List<MethodRef<Object>>> m_refs = 
new HashMap<>();
+    private Object m_compositionInstance;
+    private String m_compositionMethod;
+    private String m_init;
+    private String m_stop;
+    private String m_start;
+    private String m_destroy;
+    private Object m_callbackInstance;
+    private String m_factoryCreateMethod;
+    private boolean m_hasFactoryRef;   
+    private boolean m_hasFactory;   
+    
+    enum ComponentCallback { INIT, START, STOP, DESTROY };
+    
+    @FunctionalInterface
+    interface MethodRef<I> {
+        public void accept(I instance, Component c);
+    }
+
+    public ComponentBuilderImpl(DependencyManager dm) {
+        m_component = dm.createComponent();
+        m_componentUpdated = false;
+    }
+    
+    public ComponentBuilderImpl(Component component, boolean update) {
+        m_component = component;
+        m_componentUpdated = update;
+    }
+        
+    @Override
+    public ComponentBuilderImpl autoConfig(Class<?> clazz, boolean autoConfig) 
{
+        m_component.setAutoConfig(clazz, autoConfig);
+        return this;
+    }
+
+    @Override
+    public ComponentBuilderImpl autoConfig(Class<?> clazz, String 
instanceName) {
+        m_component.setAutoConfig(clazz, instanceName);
+        return this;
+    }
+
+    @Override
+    public ComponentBuilderImpl provides(Class<?> iface) {
+        m_serviceNames = new String[] {iface.getName()};
+        return this;
+    }
+
+    @Override
+    public ComponentBuilderImpl provides(Class<?>  iface, String name, Object 
value, Object ... rest) {
+        provides(iface);
+        properties(name, value, rest);
+        return this;
+    }
+    
+    @Override
+    public ComponentBuilderImpl provides(Class<?>  iface, FluentProperties ... 
properties) {
+        provides(iface);
+        properties(properties);
+        return this;
+    }
+    
+    @Override
+    public ComponentBuilderImpl provides(Class<?>  iface, Dictionary<?,?> 
properties) {
+        provides(iface);
+        properties(properties);
+        return this;
+    }
+
+    @Override
+    public ComponentBuilderImpl  provides(Class<?>[] ifaces) {
+        m_serviceNames = Stream.of(ifaces).map(c -> 
c.getName()).toArray(String[]::new);
+        return this;
+    }
+    
+    @Override
+    public ComponentBuilderImpl provides(Class<?>[] ifaces, String name, 
Object value, Object ... rest) {
+        provides(ifaces);
+        properties(name, value, rest);
+        return this;
+    }
+    
+    @Override
+    public ComponentBuilderImpl provides(Class<?>[] ifaces, FluentProperties 
... properties) {
+        provides(ifaces);
+        properties(properties);
+        return this;
+    }
+    
+    @Override
+    public ComponentBuilderImpl provides(Class<?>[] ifaces, Dictionary<?,?> 
properties) {
+        provides(ifaces);
+        properties(properties);
+        return this;
+    }
+
+    @Override
+    public ComponentBuilderImpl provides(String iface) {
+        m_serviceNames = new String[] {iface};
+        return this;
+    }
+
+    @Override
+    public ComponentBuilderImpl provides(String iface, String name, Object 
value, Object ... rest) {
+        provides(iface);
+        properties(name, value, rest);
+        return this;
+    }
+    
+    @Override
+    public ComponentBuilderImpl provides(String iface, FluentProperties ... 
properties) {
+        provides(iface);
+        properties(properties);
+        return this;
+    }
+    
+    @Override
+    public ComponentBuilderImpl provides(String  iface, Dictionary<?,?> 
properties) {
+        provides(iface);
+        properties(properties);
+        return this;
+    }
+
+    @Override
+    public ComponentBuilderImpl  provides(String[] ifaces) {
+        m_serviceNames = ifaces;
+        return this;
+    }
+    
+    @Override
+    public ComponentBuilderImpl provides(String[] ifaces, String name, Object 
value, Object ... rest) {
+        provides(ifaces);
+        properties(name, value, rest);
+        return this;
+    }
+    
+    @Override
+    public ComponentBuilderImpl provides(String[] ifaces, FluentProperties ... 
properties) {
+        provides(ifaces);
+        properties(properties);
+        return this;
+    }
+    
+    @Override
+    public ComponentBuilderImpl provides(String[] ifaces, Dictionary<?,?> 
properties) {
+        provides(ifaces);
+        properties(properties);
+        return this;
+    }    
+    
+    @SuppressWarnings("unchecked")
+    @Override
+    public ComponentBuilderImpl properties(Dictionary<?, ?> properties) {
+        m_properties = (Dictionary<Object, Object>) properties;
+        return this;
+    }
+
+    @Override
+    public ComponentBuilderImpl properties(String name, Object value, Object 
... rest) {
+       Objects.nonNull(name);
+       Objects.nonNull(value);
+        Properties props = new Properties();
+        props.put(name,  value);
+        if ((rest.length & 1) != 0) {
+               throw new IllegalArgumentException("Invalid number of specified 
properties (number of arguments must be even).");
+        }
+        for (int i = 0; i < rest.length - 1; i += 2) {
+            String k = rest[i].toString().trim();
+            Object v = rest[i+1];
+            props.put(k, v);
+        }
+        m_properties = props;
+        return this;
+    }
+    
+    @Override
+    public ComponentBuilderImpl properties(FluentProperties ... properties) {
+       Dictionary<Object, Object> props = new Hashtable<>();
+       Stream.of(properties).forEach(property -> {
+               String name = Helpers.getLambdaParameterName(property, 0);
+               if (name.equals("arg0")) {
+                       throw new IllegalArgumentException("arg0 property name 
not supported"); 
+               }
+               Object value = property.apply(name);
+               props.put(name, value);
+       });
+        m_properties = props;
+        return this;
+    }
+
+    @Override
+    public ComponentBuilderImpl debug(String label) {
+        m_component.setDebug(label);
+        return this;
+    }
+    
+    @Override
+    public ComponentBuilderImpl autoAdd(boolean autoAdd) {
+        m_autoAdd = autoAdd;
+        return this;
+    }
+    
+    public ComponentBuilderImpl autoAdd() {
+        m_autoAdd = true;
+       return this;
+    }
+
+    public boolean isAutoAdd() {
+        return m_autoAdd;
+    }
+
+    @Override
+    public ComponentBuilderImpl impl(Object instance) {
+        m_impl = instance;
+        return this;
+    }
+        
+    @Override
+    public ComponentBuilderImpl factory(Object factory, String createMethod) {
+        m_factory = factory;
+        m_factoryCreateMethod = createMethod;
+        ensureHasNoFactoryRef();
+        m_hasFactory = true;
+        return this;
+    }
+
+    @Override
+    public ComponentBuilderImpl factory(Supplier<?> create) {
+        Objects.nonNull(create);
+        ensureHasNoFactory();
+        m_hasFactoryRef = true;
+        m_factory = new Object() {
+            @SuppressWarnings("unused")
+            public Object create() {
+                return create.get();
+            }
+        };
+        return this;
+    }
+    
+    @Override
+    public <U, V> ComponentBuilderImpl factory(Supplier<U> supplier, 
Function<U, V> create) {
+        Objects.nonNull(supplier);
+        Objects.nonNull(create);
+        ensureHasNoFactory();
+        m_hasFactoryRef = true;
+
+        m_factory = new Object() {
+            @SuppressWarnings("unused")
+            public Object create() {
+                U factoryImpl = supplier.get();
+                return create.apply(factoryImpl);
+            }
+        }; 
+        return this;
+    }
+
+    @Override
+    public ComponentBuilderImpl factory(Supplier<?> create, Supplier<Object[]> 
getComposite) {
+        Objects.nonNull(create);
+        Objects.nonNull(getComposite);
+        ensureHasNoFactory();
+        m_hasFactoryRef = true;
+
+        m_factory = new Object() {
+            @SuppressWarnings("unused")
+            public Object create() { // Create Factory instance
+                return create.get();
+            }
+            
+            @SuppressWarnings("unused")
+            public Object[] getComposite() { // Create Factory instance
+                return getComposite.get();
+            }
+        };
+        m_factoryHasComposite = true;
+        return this;
+    }
+    
+    @Override
+    public <U> ComponentBuilderImpl factory(Supplier<U> factorySupplier, 
Function<U, ?> factoryCreate, Function<U, Object[]> factoryGetComposite) {
+        Objects.nonNull(factorySupplier);
+        Objects.nonNull(factoryCreate);
+        Objects.nonNull(factoryGetComposite);
+        ensureHasNoFactory();
+        m_hasFactoryRef = true;
+
+        m_factory = new Object() {
+            U m_factoryInstance;
+            
+            @SuppressWarnings("unused")
+            public Object create() { 
+                m_factoryInstance = factorySupplier.get();
+                return factoryCreate.apply(m_factoryInstance);
+            }
+            
+            @SuppressWarnings("unused")
+            public Object[] getComposite() { 
+                return factoryGetComposite.apply(m_factoryInstance);
+            }
+        }; 
+        m_factoryHasComposite = true;
+        return this;
+    }
+        
+    public ComponentBuilderImpl composition(String getCompositionMethod) {
+        return composition(null, getCompositionMethod);
+    }
+    
+    public ComponentBuilderImpl composition(Object instance, String 
getCompositionMethod) {
+        m_compositionInstance = instance;
+        m_compositionMethod = getCompositionMethod;
+        return this;
+    }
+    
+    public ComponentBuilderImpl composition(Supplier<Object[]> 
getCompositionMethod) {
+        m_compositionInstance = new Object() {
+            @SuppressWarnings("unused")
+            public Object[] getComposition() {
+                return getCompositionMethod.get();
+            }
+        };
+        m_compositionMethod = "getComposition";
+        return this;
+    }
+
+    @Override
+    public ComponentBuilderImpl withSrv(Class<?> service, String filter) {
+        return withSrv(service, srv->srv.filter(filter));
+    }   
+
+    @Override
+    public ComponentBuilderImpl withSrv(Class<?> ... services) {
+        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 withSrv(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 
withCnf(Consumer<ConfigurationDependencyBuilder> consumer) {
+        ConfigurationDependencyBuilder dep = new 
ConfigurationDependencyBuilderImpl(m_component);
+        consumer.accept(dep);
+        m_dependencyBuilders.add(dep);
+        return this;
+    }
+    
+    @Override
+    public ComponentBuilderImpl withBundle(Consumer<BundleDependencyBuilder> 
consumer) {
+       BundleDependencyBuilder dep = new 
BundleDependencyBuilderImpl(m_component);
+        consumer.accept(dep);
+        m_dependencyBuilders.add(dep);
+        return this;
+    }
+           
+    @Override
+    public <V> ComponentBuilderImpl withFuture(CompletableFuture<V> future, 
Consumer<FutureDependencyBuilder<V>> consumer) {
+        FutureDependencyBuilder<V> dep = new 
CompletableFutureDependencyImpl<>(m_component, future);
+        consumer.accept(dep);
+        m_dependencyBuilders.add(dep);
+        return this;
+    }
+    
+    public ComponentBuilderImpl init(String callback) {
+        ensureHasNoLifecycleMethodRefs();
+        m_init = callback;
+        return this;
+    }
+    
+    public ComponentBuilderImpl start(String callback) {
+        ensureHasNoLifecycleMethodRefs();
+        m_start = callback;
+        return this;
+    }
+
+    public ComponentBuilderImpl stop(String callback) {
+        ensureHasNoLifecycleMethodRefs();
+        m_stop = callback;
+        return this;
+    }
+    
+    public ComponentBuilderImpl destroy(String callback) {
+        ensureHasNoLifecycleMethodRefs();
+        m_destroy = callback;
+        return this;
+    }
+    
+    public ComponentBuilderImpl init(Object callbackInstance, String callback) 
{
+        m_callbackInstance = callbackInstance;
+        return init(callback);
+    }    
+
+    public ComponentBuilderImpl start(Object callbackInstance, String 
callback) {
+        m_callbackInstance = callbackInstance;
+        return start(callback);
+    }    
+
+    public ComponentBuilderImpl stop(Object callbackInstance, String callback) 
{
+        m_callbackInstance = callbackInstance;
+        return stop(callback);
+    }    
+
+    public ComponentBuilderImpl destroy(Object callbackInstance, String 
callback) {
+        m_callbackInstance = callbackInstance;
+        return destroy(callback);
+    }    
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <U> ComponentBuilderImpl init(CbConsumer<U> callback) {
+        if (callback != null) {
+            setComponentCallbackRef(INIT, Helpers.getLambdaArgType(callback, 
0), (inst, component) -> callback.accept((U) inst));
+        }
+        return this;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <U> ComponentBuilderImpl start(CbConsumer<U> callback) {
+        if (callback != null) {
+            setComponentCallbackRef(START, Helpers.getLambdaArgType(callback, 
0), (inst, component) -> callback.accept((U) inst));
+        }
+        return this;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <U> ComponentBuilderImpl stop(CbConsumer<U> callback) {
+        if (callback != null) {
+            setComponentCallbackRef(STOP, Helpers.getLambdaArgType(callback, 
0), (inst, component) -> callback.accept((U) inst));
+        }
+        return this;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <U> ComponentBuilderImpl destroy(CbConsumer<U> callback) {
+        if (callback != null) {
+            setComponentCallbackRef(DESTROY, 
Helpers.getLambdaArgType(callback, 0), (inst, component) -> callback.accept((U) 
inst));
+        }
+        return this;
+    }
+
+   @SuppressWarnings("unchecked")
+   @Override
+    public <U> ComponentBuilderImpl init(CbTypeComponent<U> callback) {
+        if (callback != null) {
+            setComponentCallbackRef(INIT, Helpers.getLambdaArgType(callback, 
0), (inst, component) -> callback.accept((U) inst, component));
+        }
+        return this;
+    }
+            
+   @SuppressWarnings("unchecked")
+   @Override
+    public <U> ComponentBuilderImpl start(CbTypeComponent<U> callback) {
+        if (callback != null) {
+            setComponentCallbackRef(START, Helpers.getLambdaArgType(callback, 
0), (inst, component) -> callback.accept((U) inst, component));
+        }
+        return this;
+    }
+            
+   @SuppressWarnings("unchecked")
+   @Override
+    public <U> ComponentBuilderImpl stop(CbTypeComponent<U> callback) {
+        if (callback != null) {
+            setComponentCallbackRef(STOP, Helpers.getLambdaArgType(callback, 
0), (inst, component) -> callback.accept((U) inst, component));
+        }
+        return this;
+    }
+            
+   @SuppressWarnings("unchecked")
+   @Override
+    public <U> ComponentBuilderImpl destroy(CbTypeComponent<U> callback) {
+        if (callback != null) {
+            setComponentCallbackRef(DESTROY, 
Helpers.getLambdaArgType(callback, 0), (inst, component) -> callback.accept((U) 
inst, component));
+        }
+        return this;
+    }
+            
+    @Override
+    public ComponentBuilderImpl initInstance(Runnable callback) {
+        if (callback != null) {
+            setInstanceCallbackRef(INIT, (inst, component) -> callback.run());
+        }
+        return this;
+    }
+    
+    @Override
+    public ComponentBuilderImpl startInstance(Runnable callback) {
+        if (callback != null) {
+            setInstanceCallbackRef(START, (inst, component) -> callback.run());
+        }
+        return this;
+    }
+
+    @Override
+    public ComponentBuilderImpl stopInstance(Runnable callback) {
+        if (callback != null) {
+            setInstanceCallbackRef(STOP, (inst, component) -> callback.run());
+        }
+        return this;
+    }
+
+    @Override
+    public ComponentBuilderImpl destroyInstance(Runnable callback) {
+        if (callback != null) {
+            setInstanceCallbackRef(DESTROY, (inst, component) -> 
callback.run());
+        }
+        return this;
+    }
+        
+    @Override
+    public ComponentBuilderImpl initInstance(CbComponent callback) {
+        if (callback != null) {
+            setInstanceCallbackRef(INIT, (inst, component) -> 
callback.accept(component));
+        }
+        return this;
+    }
+  
+    @Override
+    public ComponentBuilderImpl startInstance(CbComponent callback) {
+        if (callback != null) {
+            setInstanceCallbackRef(START, (inst, component) -> 
callback.accept(component));
+        }
+        return this;
+    }
+
+    @Override
+    public ComponentBuilderImpl stopInstance(CbComponent callback) {
+        if (callback != null) {
+            setInstanceCallbackRef(STOP, (inst, component) -> 
callback.accept(component));
+        }
+        return this;
+    }
+
+    @Override
+    public ComponentBuilderImpl destroyInstance(CbComponent callback) {
+        if (callback != null) {
+            setInstanceCallbackRef(DESTROY, (inst, component) -> 
callback.accept(component));
+        }
+        return this;
+    }
+    
+    public Component build() {
+        if (m_serviceNames != null) {
+            m_component.setInterface(m_serviceNames, m_properties);
+        } 
+        
+        if (m_properties != null) {
+            m_component.setServiceProperties(m_properties);
+        }
+                
+        if (! m_componentUpdated) { // Don't override impl or set callbacks if 
component is being updated
+           if (m_impl != null) {               
+               m_component.setImplementation(m_impl);
+               m_component.setComposition(m_compositionInstance, 
m_compositionMethod);
+           } else {
+               Objects.nonNull(m_factory);
+               if (m_hasFactoryRef) {
+                   m_component.setFactory(m_factory, "create");
+                   if (m_factoryHasComposite) {
+                       m_component.setComposition(m_factory, "getComposite");
+                   }
+               } else {
+                   m_component.setFactory(m_factory, m_factoryCreateMethod);
+               }
+           }
+            
+           if (m_refs.size() > 0) {
+                  setLifecycleMethodRefs();
+           } else if (hasLifecleMethods()) {
+               m_component.setCallbacks(m_callbackInstance, m_init, m_start, 
m_stop, m_destroy);
+           }
+        }
+        
+        if (m_dependencyBuilders.size() > 0) {
+            // add atomically in case we are building some component 
dependencies from a component init method.
+            // We first transform the list of builders into a stream of built 
Dependencies, then we collect the result 
+            // to an array of Dependency[].
+            m_component.add(m_dependencyBuilders.stream().map(builder -> 
builder.build()).toArray(Dependency[]::new));
+        }
+        return m_component;
+    }
+
+    private boolean hasLifecleMethods() {
+        return m_init != null || m_start != null || m_stop != null || 
m_destroy != null;
+    }
+    
+    private boolean hasLifecleMethodRefs() {
+        return m_refs.size() > 0;
+    }
+    
+    private void ensureHasNoLifecycleMethods() {
+        if (hasLifecleMethods()) {
+            throw new IllegalStateException("Can't mix method references and 
name names for lifecycle callbacks");
+        }
+    }
+    
+    private void ensureHasNoLifecycleMethodRefs() {
+        if (hasLifecleMethodRefs()) {
+            throw new IllegalStateException("Can't mix method references and 
name names for lifecycle callbacks");
+        }
+    }
+
+    protected <U> ComponentBuilderImpl 
setInstanceCallbackRef(ComponentCallback cbType, MethodRef<U> ref) {
+        ensureHasNoLifecycleMethods();
+        List<MethodRef<Object>> list = m_refs.computeIfAbsent(cbType, l -> new 
ArrayList<>());
+        list.add((instance, component) -> {
+            ref.accept(null, component);
+        });
+        return this;
+    }
+
+    @SuppressWarnings("unchecked")
+    private <U> ComponentBuilderImpl setComponentCallbackRef(ComponentCallback 
cbType, Class<U> type, MethodRef<U> callback) {
+        ensureHasNoLifecycleMethods();
+        if (type.equals(Object.class)) {
+            throw new IllegalStateException("callback does not seam to be one 
from the possible component implementation classes");
+        }
+        List<MethodRef<Object>> list = m_refs.computeIfAbsent(cbType, l -> new 
ArrayList<>());
+        list.add((instance, component) -> {
+            Object componentImpl = Stream.of(component.getInstances())
+                .filter(impl -> Helpers.getClass(impl).equals(type))
+                .findFirst()
+                .orElseThrow(() -> new IllegalStateException("The method 
reference " + callback + " does not match any available component impl 
classes."));   
+            callback.accept((U) componentImpl, component);
+        });
+        return this;
+    }
+        
+    @SuppressWarnings("unused")
+    private void setLifecycleMethodRefs() {
+        Object cb = new Object() {
+            void init(Component comp) {
+               invokeLfcleCallbacks(ComponentCallback.INIT, comp);
+            }
+
+            void start(Component comp) {
+               invokeLfcleCallbacks(ComponentCallback.START, comp);
+            }
+
+            void stop(Component comp) {
+               invokeLfcleCallbacks(ComponentCallback.STOP, comp);
+            }
+
+            void destroy(Component comp) {
+               invokeLfcleCallbacks(ComponentCallback.DESTROY, comp);
+            }
+        };
+        m_component.setCallbacks(cb, "init", "start", "stop", "destroy");
+    }
+    
+    private void invokeLfcleCallbacks(ComponentCallback cbType, Component 
component) {
+        m_refs.computeIfPresent(cbType, (k, mrefs) -> {
+            mrefs.forEach(mref -> mref.accept(null, component));
+            return mrefs;
+         });
+    }
+
+    private void ensureHasNoFactoryRef() {
+        if (m_hasFactoryRef) {
+            throw new IllegalStateException("Can't mix factory method name and 
factory method reference");
+        }
+    }
+    
+    private void ensureHasNoFactory() {
+        if (m_hasFactory) {
+            throw new IllegalStateException("Can't mix factory method name and 
factory method reference");
+        }
+    }
+}

Added: 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ConfigurationDependencyBuilderImpl.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ConfigurationDependencyBuilderImpl.java?rev=1727869&view=auto
==============================================================================
--- 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ConfigurationDependencyBuilderImpl.java
 (added)
+++ 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/ConfigurationDependencyBuilderImpl.java
 Sun Jan 31 23:27:05 2016
@@ -0,0 +1,162 @@
+package org.apache.felix.dm.lambda.impl;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Stream;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.ConfigurationDependency;
+import org.apache.felix.dm.lambda.ConfigurationDependencyBuilder;
+import org.apache.felix.dm.lambda.callbacks.CbComponentDictionary;
+import org.apache.felix.dm.lambda.callbacks.CbDictionary;
+import org.apache.felix.dm.lambda.callbacks.CbTypeComponentDictionary;
+import org.apache.felix.dm.lambda.callbacks.CbTypeDictionary;
+
+public class ConfigurationDependencyBuilderImpl implements 
ConfigurationDependencyBuilder {
+    private String m_pid;
+    private boolean m_propagate;
+    private final Component m_component;
+    private String m_updateMethodName;
+    private Object m_updateCallbackInstance;
+    private boolean m_hasMethodRefs;
+    private boolean m_hasReflectionCallback;
+    private final List<MethodRef<Object>> m_refs = new ArrayList<>();
+    private boolean m_hasComponentCallbackRefs;
+    private boolean m_needsInstance = false;
+    
+    @FunctionalInterface
+    interface MethodRef<I> {
+        public void accept(I instance, Component c, Dictionary<String, Object> 
props);
+    }
+    
+    public ConfigurationDependencyBuilderImpl(Component component) {
+        m_component = component;
+    }
+
+    @Override
+    public ConfigurationDependencyBuilder pid(String pid) {
+        m_pid = pid;
+        return this;
+    }
+
+    @Override
+    public ConfigurationDependencyBuilder pid(Class<?> pidClass) {
+        m_pid = pidClass.getName();
+        return this;
+    }
+
+    @Override
+    public ConfigurationDependencyBuilder propagate() {
+        m_propagate = true;
+        return this;
+    }
+
+    @Override
+    public ConfigurationDependencyBuilder propagate(boolean propagate) {
+        m_propagate = propagate;
+        return this;
+    }
+
+    public ConfigurationDependencyBuilder cb(String update) {
+        checkHasNoMethodRefs();
+        m_hasReflectionCallback = true;
+        m_updateMethodName = update;
+        return this;
+    }
+    
+    public ConfigurationDependencyBuilder cbi(Object callbackInstance, String 
update) {
+        m_updateCallbackInstance = callbackInstance;
+        cb(update);
+        return this;
+    }
+
+    public ConfigurationDependencyBuilder needsInstance(boolean needsInstance) 
{
+        m_needsInstance = needsInstance;
+        return this;
+    }
+
+    @Override
+    public <T> ConfigurationDependencyBuilder cb(CbTypeDictionary<T>  
callback) {
+        Class<T> type = Helpers.getLambdaArgType(callback, 0);
+        return setComponentCallbackRef(type, (instance, component, props) -> { 
callback.accept((T) instance, props); });
+    }
+
+    @Override
+    public <T> ConfigurationDependencyBuilder cb(CbTypeComponentDictionary<T>  
callback) {
+        Class<T> type = Helpers.getLambdaArgType(callback, 0);
+        return setComponentCallbackRef(type, (instance, component, props) -> { 
callback.accept((T) instance, component, props); });
+    }
+
+    @Override
+    public ConfigurationDependencyBuilder cbi(CbDictionary callback) {
+        return setInstanceCallbackRef((instance, component, props) -> { 
callback.accept(props); });
+    }
+    
+    @Override
+    public ConfigurationDependencyBuilder cbi(CbComponentDictionary callback) {
+        return setInstanceCallbackRef((instance, component, props) -> { 
callback.accept(component, props); });
+    }
+
+    @Override
+    public ConfigurationDependency build() {
+        ConfigurationDependency dep = 
m_component.getDependencyManager().createConfigurationDependency();
+        Objects.nonNull(m_pid);
+        dep.setPid(m_pid);
+        dep.setPropagate(m_propagate);
+        if (m_updateMethodName != null) {
+            if (m_updateCallbackInstance != null) {
+                dep.setCallback(m_updateCallbackInstance, m_updateMethodName, 
m_needsInstance);
+            } else {
+                dep.setCallback(m_updateMethodName);
+            }
+        } else if (m_refs.size() > 0) {
+            // setup an internal callback object. When config is updated, we 
have to call each registered 
+            // method references. 
+            // Notice that we need the component to be instantiated in case 
there is a mref on one of the component instances (unbound method ref), or is 
used
+            // called "needsInstance(true)".
+            dep.setCallback(new Object() {
+                @SuppressWarnings("unused")
+                void updated(Component comp, Dictionary<String, Object> props) 
{
+                    m_refs.forEach(mref -> mref.accept(null, comp, props));
+                }
+            }, "updated", m_hasComponentCallbackRefs||m_needsInstance);
+        }
+        return dep;
+    }
+    
+    private <T> ConfigurationDependencyBuilder 
setInstanceCallbackRef(MethodRef<T> ref) {
+        checkHasNoReflectionCallbacks();
+        m_hasMethodRefs = true;
+        m_refs.add((instance, component, props) -> ref.accept(null, component, 
props));
+        return this;
+    }
+    
+    @SuppressWarnings("unchecked")
+    private <T> ConfigurationDependencyBuilder 
setComponentCallbackRef(Class<T> type, MethodRef<T> ref) {
+        checkHasNoReflectionCallbacks();
+        m_hasMethodRefs = true;
+        m_hasComponentCallbackRefs = true;
+        m_refs.add((instance, component, props) -> {
+            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((T) componentImpl, component, props);
+        });
+        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");
+        }
+    }
+}

Added: 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/FactoryPidAdapterBuilderImpl.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/FactoryPidAdapterBuilderImpl.java?rev=1727869&view=auto
==============================================================================
--- 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/FactoryPidAdapterBuilderImpl.java
 (added)
+++ 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/FactoryPidAdapterBuilderImpl.java
 Sun Jan 31 23:27:05 2016
@@ -0,0 +1,166 @@
+package org.apache.felix.dm.lambda.impl;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+
+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.FactoryPidAdapterBuilder;
+import org.apache.felix.dm.lambda.callbacks.CbComponentDictionary;
+import org.apache.felix.dm.lambda.callbacks.CbDictionary;
+import org.apache.felix.dm.lambda.callbacks.CbTypeComponentDictionary;
+import org.apache.felix.dm.lambda.callbacks.CbTypeDictionary;
+
+public class FactoryPidAdapterBuilderImpl implements 
AdapterBase<FactoryPidAdapterBuilder>, FactoryPidAdapterBuilder {
+    private String m_factoryPid;
+    private boolean m_propagate;
+    private final DependencyManager m_dm;
+    private boolean m_autoAdd = true;
+    private String m_updateMethodName;
+    private Object m_updateCallbackInstance;
+    private boolean m_hasMethodRefs;
+    private boolean m_hasReflectionCallback;
+    private Consumer<ComponentBuilder<?>> m_compBuilder = (componentBuilder -> 
{});
+    private final List<MethodRef<Object>> m_refs = new ArrayList<>();
+
+    @FunctionalInterface
+    interface MethodRef<I> {
+        public void accept(I instance, Component c, Dictionary<String, Object> 
props);
+    }
+
+    public FactoryPidAdapterBuilderImpl(DependencyManager dm) {
+        m_dm = dm;
+    }
+    
+    public void andThenBuild(Consumer<ComponentBuilder<?>> builder) {
+        m_compBuilder = m_compBuilder.andThen(builder);
+    }
+
+    @Override
+    public FactoryPidAdapterBuilderImpl autoAdd(boolean autoAdd) {
+        m_autoAdd = autoAdd;
+        return this;
+    }
+        
+    public boolean isAutoAdd() {
+        return m_autoAdd;
+    }
+
+    @Override
+    public FactoryPidAdapterBuilder factoryPid(String pid) {
+        m_factoryPid = pid;
+        return this;
+    }
+
+    @Override
+    public FactoryPidAdapterBuilder factoryPid(Class<?> pidClass) {
+        m_factoryPid = pidClass.getName();
+        return this;
+    }
+
+    @Override
+    public FactoryPidAdapterBuilder propagate() {
+        m_propagate = true;
+        return this;
+    }
+
+    @Override
+    public FactoryPidAdapterBuilder propagate(boolean propagate) {
+        m_propagate = propagate;
+        return this;
+    }
+
+    public FactoryPidAdapterBuilder cb(String update) {
+        checkHasNoMethodRefs();
+        m_hasReflectionCallback = true;
+        m_updateMethodName = update;
+        return this;
+    }
+    
+    public FactoryPidAdapterBuilder cb(Object callbackInstance, String update) 
{
+        cb(update);
+        m_updateCallbackInstance = callbackInstance;
+        return this;
+    }
+    
+    @Override
+    public <U> FactoryPidAdapterBuilder cb(CbTypeDictionary<U> callback) {
+        Class<U> type = Helpers.getLambdaArgType(callback, 0);
+        return setComponentCallbackRef(type, (instance, component, props) -> { 
callback.accept((U) instance, props); });
+    }
+    
+    @Override
+    public <U> FactoryPidAdapterBuilder cb(CbTypeComponentDictionary<U> 
callback) {
+        Class<U> type = Helpers.getLambdaArgType(callback, 0);
+        return setComponentCallbackRef(type, (instance, component, props) -> { 
callback.accept((U) instance, component, props); });
+    }
+
+    @Override
+    public FactoryPidAdapterBuilder cbi(CbDictionary callback) {
+        return setInstanceCallbackRef((instance, component, props) -> { 
callback.accept(props); });
+    }
+
+    @Override
+    public FactoryPidAdapterBuilder cbi(CbComponentDictionary callback) {
+        return setInstanceCallbackRef((instance, component, props) -> { 
callback.accept(component, props); });
+    }
+
+    @Override
+    public Component build() {        
+        Objects.nonNull(m_factoryPid);
+        Component c = null;
+        
+        if (m_hasMethodRefs) {
+            Object wrapCallback = new Object() {
+                @SuppressWarnings("unused")
+                public void updated(Component comp, Dictionary<String, Object> 
conf) {
+                    m_refs.forEach(mref -> mref.accept(null, 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);
+        }
+        ComponentBuilderImpl cb = new ComponentBuilderImpl(c, false);
+        m_compBuilder.accept (cb);
+        return cb.build();
+    }
+    
+    private <U> FactoryPidAdapterBuilder setInstanceCallbackRef(MethodRef<U> 
ref) {
+        checkHasNoReflectionCallbacks();
+        m_hasMethodRefs = true;
+        m_refs.add((instance, component, props) -> ref.accept(null, component, 
props));
+        return this;
+    }
+    
+    @SuppressWarnings("unchecked")
+    private <U> FactoryPidAdapterBuilder setComponentCallbackRef(Class<U> 
type, MethodRef<U> ref) {
+        checkHasNoReflectionCallbacks();
+        m_hasMethodRefs = true;
+        m_refs.add((instance, component, props) -> {
+            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((U) componentImpl, component, props);
+        });
+        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");
+        }
+    }
+}

Added: 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/Helpers.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/Helpers.java?rev=1727869&view=auto
==============================================================================
--- 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/Helpers.java
 (added)
+++ 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/Helpers.java
 Sun Jan 31 23:27:05 2016
@@ -0,0 +1,147 @@
+package org.apache.felix.dm.lambda.impl;
+
+import java.lang.invoke.SerializedLambda;
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+import java.lang.reflect.Proxy;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+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.lambda.callbacks.SerializableLambda;
+
+/**
+ * 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 Class<?> getClass(Object obj) {
+               Class<?> clazz = obj.getClass();
+               if (Proxy.isProxyClass(clazz)) {
+                       return Proxy.getProxyClass(clazz.getClassLoader(), 
clazz);
+               }
+               return clazz;
+       }
+       
+       /**
+        * 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 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>  
+        */
+       @SuppressWarnings("unchecked")
+    public static <T> Class<T> getLambdaArgType(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;
+       }
+       
+       /**
+        * Extracts the first parameter of a lambda.
+        */
+       public static String getLambdaParameterName(SerializableLambda lambda, 
int index) {
+               SerializedLambda serialized = getSerializedLambda(lambda);
+               Method m = getLambdaMethod(serialized, 
lambda.getClass().getClassLoader());
+               Parameter p = m.getParameters()[index];
+               
+        if (Objects.equals("arg0", p.getName())) {
+            throw new IllegalStateException("Can'f find lambda method name 
(Please check you are using javac -parameters option).");
+        }
+        return p.getName();
+       }
+       
+       /**
+        * Returns the SerializedObject of a given lambda.
+        */
+    private static SerializedLambda getSerializedLambda(SerializableLambda 
lambda) {
+           if (lambda == null) {
+               throw new IllegalArgumentException();
+           }
+
+           for (Class<?> clazz = lambda.getClass(); clazz != null; clazz = 
clazz.getSuperclass()) {
+               try {
+                   Method replaceMethod = 
clazz.getDeclaredMethod("writeReplace");
+                   replaceMethod.setAccessible(true);
+                   Object serializedForm = replaceMethod.invoke(lambda);
+
+                   if (serializedForm instanceof SerializedLambda) {
+                       return (SerializedLambda) serializedForm;
+                   }
+               }
+               catch (NoSuchMethodException e) {
+                   // fall through the loop and try the next class
+               }
+               catch (Throwable t) {
+                   throw new RuntimeException("Error while extracting 
serialized lambda", t);
+               }
+           }
+
+           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/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/SRefAsDictionary.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/SRefAsDictionary.java?rev=1727869&view=auto
==============================================================================
--- 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/SRefAsDictionary.java
 (added)
+++ 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/SRefAsDictionary.java
 Sun Jan 31 23:27:05 2016
@@ -0,0 +1,94 @@
+package org.apache.felix.dm.lambda.impl;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.NoSuchElementException;
+
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Maps a ServiceReference to a Dictionary.
+ */
+public class SRefAsDictionary extends Dictionary<String, Object> {
+    private final ServiceReference<?> m_ref;
+    private volatile int m_size = -1;
+
+    public SRefAsDictionary(ServiceReference<?> ref) {
+        m_ref = ref;
+    }
+    
+    @Override
+    public Object get(Object key) {
+        return m_ref.getProperty(key.toString());
+    }
+    
+    @Override
+    public int size() {
+        return m_size != -1 ? m_size : (m_size = 
m_ref.getPropertyKeys().length);
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return size() == 0;
+    }
+
+    @Override
+    public Enumeration<String> keys() {
+        return 
Collections.enumeration(Arrays.asList(m_ref.getPropertyKeys())); 
+    }
+
+    @Override
+    public Enumeration<Object> elements() {
+        final String[] keys = m_ref.getPropertyKeys();
+        
+        return new Enumeration<Object>() {
+            int m_index = 0;
+            
+            @Override
+            public boolean hasMoreElements() {
+                return m_index < keys.length;
+            }
+
+            @Override
+            public Object nextElement() {
+                if (m_index >= keys.length) {
+                    throw new NoSuchElementException();
+                }
+                return m_ref.getProperty(keys[m_index ++]);
+            }
+        };
+    }
+
+    @Override
+    public Object remove(Object key) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Object put(String key, Object value) {
+        throw new UnsupportedOperationException();
+    }
+    
+    public String toString() {
+        int max = size() - 1;
+        if (max == -1)
+            return "{}";
+
+        StringBuilder sb = new StringBuilder();
+        String[] keys = m_ref.getPropertyKeys();
+        sb.append('{');
+        for (int i = 0; ; i++) {
+            String key = keys[i];
+            Object value = m_ref.getProperty(key);
+            sb.append(key);
+            sb.append('=');
+            sb.append(value == this ? "(this Dictionary)" : value.toString());
+
+            if (i == max)
+                return sb.append('}').toString();
+            sb.append(", ");
+        }
+    }
+}

Added: 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/SRefAsMap.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/SRefAsMap.java?rev=1727869&view=auto
==============================================================================
--- 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/SRefAsMap.java
 (added)
+++ 
felix/trunk/dependencymanager/org.apache.felix.dependencymanager.lambda/src/org/apache/felix/dm/lambda/impl/SRefAsMap.java
 Sun Jan 31 23:27:05 2016
@@ -0,0 +1,84 @@
+package org.apache.felix.dm.lambda.impl;
+
+import java.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Maps a ServiceReference to a Map.
+ */
+public class SRefAsMap extends AbstractMap<String, Object> {
+    private final ServiceReference<?> m_ref;
+
+    public SRefAsMap(ServiceReference<?> ref) {
+        m_ref = ref;
+    }
+    
+    public Object get(Object key) {
+        return m_ref.getProperty(key.toString());
+    }
+
+    @Override
+    public Set<Entry<String, Object>> entrySet() {
+        return new AbstractSet<Entry<String, Object>>() {
+            @Override
+            public Iterator<Entry<String, Object>> iterator() {
+                final Enumeration<String> e = 
Collections.enumeration(Arrays.asList(m_ref.getPropertyKeys()));
+                
+                return new Iterator<Entry<String, Object>>() {
+                    private String key;
+
+                    public boolean hasNext() {
+                        return e.hasMoreElements();
+                    }
+
+                    public Entry<String, Object> next() {
+                        key = e.nextElement();
+                        return new KeyEntry(key);
+                    }
+
+                    public void remove() {
+                        throw new UnsupportedOperationException();
+                    }
+                };
+            }
+
+            @Override
+            public int size() {
+                return m_ref.getPropertyKeys().length;
+            }
+        };
+    }
+
+    @Override
+    public Object put(String key, Object value) {
+        throw new UnsupportedOperationException();
+    }
+
+    class KeyEntry implements Map.Entry<String, Object> {
+        private final String key;
+
+        KeyEntry(String key) {
+            this.key = key;
+        }
+
+        public String getKey() {
+            return key;
+        }
+
+        public Object getValue() {
+            return m_ref.getProperty(key);
+        }
+
+        public Object setValue(Object value) {
+            return SRefAsMap.this.put(key, value);
+        }
+    }
+}


Reply via email to