Fix FELIX-3749 (https://issues.apache.org/jira/browse/FELIX-3749)

Apply patch from Guillaume Sauthier, forgot some files...

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1407407 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/ClassMetadataCollector.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/ClassMetadataCollector.java
new file mode 100644
index 0000000..6b7904c
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/ClassMetadataCollector.java
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation;
+
+import org.apache.felix.ipojo.manipulator.Reporter;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.registry.BindingRegistry;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.commons.EmptyVisitor;
+import org.objectweb.asm.tree.ClassNode;
+import org.objectweb.asm.tree.FieldNode;
+import org.objectweb.asm.tree.MethodNode;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ClassMetadataCollector extends EmptyVisitor {
+
+    /**
+     * Binding's registry.
+     */
+    private BindingRegistry registry;
+
+    /**
+     * Output information.
+     */
+    private Reporter reporter;
+
+    /**
+     * Workbench where produced Elements will be merged and hierarchically organized.
+     */
+    private ComponentWorkbench workbench;
+
+    /**
+     * Class currently being analyzed.
+     */
+    private ClassNode node;
+
+    private Element componentMetadata;
+
+    private Element instanceMetadata;
+
+    public ClassMetadataCollector(BindingRegistry registry, Reporter reporter) {
+        this.registry = registry;
+        this.reporter = reporter;
+        node = new ClassNode();
+    }
+
+    /**
+     * Build metadata. May be {@literal null} if no "component type" was found.
+     * @return Build metadata. May be {@literal null} if no "component type" was found.
+     */
+    public Element getComponentMetadata() {
+        return componentMetadata;
+    }
+
+    /**
+     * Build metadata. May be {@literal null} if no "component type" was found.
+     * @return Build metadata. May be {@literal null} if no "component type" was found.
+     */
+    public Element getInstanceMetadata() {
+        return instanceMetadata;
+    }
+
+    @Override
+    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
+        node.visit(version, access, name, signature, superName, interfaces);
+        workbench = new ComponentWorkbench(registry, node);
+    }
+
+    /**
+     * Visit class annotations.
+     * This method detects @component and @provides annotations.
+     * @param desc : annotation descriptor.
+     * @param visible : is the annotation visible at runtime.
+     * @return the annotation visitor.
+     * @see org.objectweb.asm.ClassAdapter#visitAnnotation(java.lang.String, boolean)
+     */
+    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+
+        // Return the visitor to be executed (may be null)
+        return registry.selection(workbench)
+                .type(node)
+                .annotatedWith(desc)
+                .get();
+
+    }
+
+    /**
+     * Visit a field.
+     * Call the field collector visitor.
+     * @param access : field access.
+     * @param name : field name
+     * @param desc : field descriptor
+     * @param signature : field signature
+     * @param value : field value (static field only)
+     * @return the field visitor.
+     * @see org.objectweb.asm.ClassAdapter#visitField(int, java.lang.String, java.lang.String, java.lang.String, java.lang.Object)
+     */
+    public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
+        return new FieldMetadataCollector(workbench, new FieldNode(access, name, desc, signature, value));
+    }
+
+    /**
+     * Visit a method.
+     * Call the method collector visitor.
+     * @param access : method access
+     * @param name : method name
+     * @param desc : method descriptor
+     * @param signature : method signature
+     * @param exceptions : method exceptions
+     * @return the Method Visitor.
+     * @see org.objectweb.asm.ClassAdapter#visitMethod(int, java.lang.String, java.lang.String, java.lang.String, java.lang.String[])
+     */
+    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
+        return new MethodMetadataCollector(workbench, new MethodNode(access, name, desc, signature, exceptions), reporter);
+    }
+
+    /**
+     * End of the visit : compute final elements.
+     * @see org.objectweb.asm.commons.EmptyVisitor#visitEnd()
+     */
+    @Override
+    public void visitEnd() {
+        if (workbench.getRoot() == null) {
+            // No 'top-level' element has been contributed
+
+            if (!workbench.getElements().isEmpty()) {
+                // There are other annotation's contribution on this type (additional handler declaration/configuration)
+                // That means that there is a missing 'component type' annotation
+
+                reporter.warn("Class %s has not been marked as a component type (no @Component, @Handler, ...). It will be ignored in manipulation.",
+                        workbench.getType().getClassName());
+                return;
+            } // else: no root and no elements
+            return;
+        }
+
+        componentMetadata = workbench.build();
+        instanceMetadata = workbench.getInstance();
+    }
+
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/ComponentWorkbench.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/ComponentWorkbench.java
new file mode 100644
index 0000000..2fdd6c5
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/ComponentWorkbench.java
@@ -0,0 +1,152 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.registry.BindingRegistry;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.ClassNode;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ComponentWorkbench {
+
+    /**
+     * Root element (usually <component /> or <handler/>).
+     * Maybe null until set.
+     */
+    private Element root;
+
+    /**
+     * Instance element (may be {@literal null}).
+     */
+    private Element instance;
+
+    /**
+     * Map of [element ids, element].
+     * This map is used to easily get an already created element.
+     */
+    private Map<String, Element> m_ids = new TreeMap<String, Element>();
+
+    /**
+     * Map of [element, referto].
+     * This map is used to recreate the element hierarchy.
+     * Stored element are added under referred element.
+     */
+    private Map<Element, String> m_elements = new LinkedHashMap<Element, String>();
+
+    private Type type;
+
+    private BindingRegistry bindingRegistry;
+
+    private ClassNode classNode;
+
+    public ComponentWorkbench(BindingRegistry bindingRegistry, ClassNode node) {
+        this.bindingRegistry = bindingRegistry;
+        this.classNode = node;
+        this.type = Type.getObjectType(node.name);
+    }
+
+    public Type getType() {
+        return type;
+    }
+
+    public BindingRegistry getBindingRegistry() {
+        return bindingRegistry;
+    }
+
+    public ClassNode getClassNode() {
+        return classNode;
+    }
+
+    /**
+     * The identified root Element. May be null if at the visit time, the root as not been identified.
+     * @return the root Element. or {@literal null} if not defined at the execution time.
+     */
+    public Element getRoot() {
+        return root;
+    }
+
+    public void setRoot(Element root) {
+        // TODO check if root already assigned
+        this.root = root;
+    }
+
+    public Element getInstance() {
+        return instance;
+    }
+
+    public void setInstance(Element instance) {
+        this.instance = instance;
+    }
+
+    public Map<String, Element> getIds() {
+        return m_ids;
+    }
+
+    public Map<Element, String> getElements() {
+        return m_elements;
+    }
+
+    public Element build() {
+
+        if (root == null) {
+            // No 'top level' component Element has been registered
+            return null;
+        }
+
+        // Iterates on all contributed Elements
+        for (Element current : m_elements.keySet()) {
+
+            // If the traversed Element has a reference to another Element,
+            // it has to be moved inside that referenced Element
+            // This is useful for contributing data to other handlers
+
+            String refId = m_elements.get(current);
+            if (refId == null) {
+                // No reference provided, just add it a a direct child
+                root.addElement(current);
+            } else {
+
+                // Get the referenced Element (if any)
+                Element ref = m_ids.get(refId);
+                if (ref == null) {
+                    // Add to the root Element
+                    root.addElement(current);
+                } else {
+                    // Add as child of the referenced Element
+                    ref.addElement(current);
+                }
+            }
+        }
+
+        // Clear
+        m_ids.clear();
+        m_elements.clear();
+
+        return root;
+
+    }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/FieldMetadataCollector.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/FieldMetadataCollector.java
new file mode 100644
index 0000000..2efe009
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/FieldMetadataCollector.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.registry.BindingRegistry;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.commons.EmptyVisitor;
+import org.objectweb.asm.tree.FieldNode;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class FieldMetadataCollector extends EmptyVisitor implements FieldVisitor {
+
+    /**
+     * Binding's registry.
+     */
+    private BindingRegistry registry;
+
+    /**
+     * The workbench currently in use.
+     */
+    private ComponentWorkbench workbench;
+
+    /**
+     * Visited field.
+     */
+    private FieldNode node;
+
+    public FieldMetadataCollector(ComponentWorkbench workbench, FieldNode node) {
+        this.workbench = workbench;
+        this.node = node;
+        this.registry = workbench.getBindingRegistry();
+    }
+
+    /**
+     * Visit annotations on the current field.
+     * @param desc : annotation name
+     * @param visible : is the annotation a runtime annotation.
+     * @return the annotation visitor visiting the annotation
+     * @see org.objectweb.asm.FieldVisitor#visitAnnotation(java.lang.String, boolean)
+     */
+    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+
+        // Return the visitor to be executed (may be null)
+        return registry.selection(workbench)
+                .field(node)
+                .annotatedWith(desc)
+                .get();
+
+    }
+
+
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/MethodMetadataCollector.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/MethodMetadataCollector.java
new file mode 100644
index 0000000..874ecd4
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/MethodMetadataCollector.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation;
+
+import org.apache.felix.ipojo.manipulator.Reporter;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.registry.BindingRegistry;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.commons.EmptyVisitor;
+import org.objectweb.asm.tree.MethodNode;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class MethodMetadataCollector extends EmptyVisitor implements MethodVisitor {
+
+    /**
+     * Binding's registry.
+     */
+    private BindingRegistry registry;
+
+    /**
+     * Output informations.
+     */
+    private Reporter reporter;
+
+    /**
+     * The workbench currently in use.
+     */
+    private ComponentWorkbench workbench;
+
+    /**
+     * Visited field.
+     */
+    private MethodNode node;
+
+    public MethodMetadataCollector(ComponentWorkbench workbench, MethodNode node, Reporter reporter) {
+        this.workbench = workbench;
+        this.reporter = reporter;
+        this.node = node;
+        this.registry = workbench.getBindingRegistry();
+    }
+
+    /**
+     * Visit method annotations.
+     *
+     * @param desc : annotation name.
+     * @param visible : is the annotation visible at runtime.
+     * @return the visitor paring the visited annotation.
+     * @see org.objectweb.asm.commons.EmptyVisitor#visitAnnotation(java.lang.String, boolean)
+     */
+    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+
+        // Return the visitor to be executed (may be null)
+        return registry.selection(workbench)
+                .method(node)
+                .annotatedWith(desc)
+                .get();
+
+    }
+
+    /**
+     * Visit a parameter annotation.
+     *
+     * @see org.objectweb.asm.commons.EmptyVisitor#visitParameterAnnotation(int, java.lang.String, boolean)
+     */
+    public AnnotationVisitor visitParameterAnnotation(int index,
+                                                      String desc,
+                                                      boolean visible) {
+        // Only process annotations on constructor
+        if (node.name.equals("<init>")) {
+
+            // Return the visitor to be executed (may be null)
+            return registry.selection(workbench)
+                    .parameter(node, index)
+                    .annotatedWith(desc)
+                    .get();
+
+        }
+        return super.visitParameterAnnotation(index, desc, visible);
+    }
+
+
+
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/module/DefaultBindingModule.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/module/DefaultBindingModule.java
new file mode 100644
index 0000000..d9ec4a8
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/module/DefaultBindingModule.java
@@ -0,0 +1,318 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.module;
+
+import org.apache.felix.ipojo.annotations.Bind;
+import org.apache.felix.ipojo.annotations.Component;
+import org.apache.felix.ipojo.annotations.Controller;
+import org.apache.felix.ipojo.annotations.Handler;
+import org.apache.felix.ipojo.annotations.HandlerDeclaration;
+import org.apache.felix.ipojo.annotations.Instantiate;
+import org.apache.felix.ipojo.annotations.Invalidate;
+import org.apache.felix.ipojo.annotations.Modified;
+import org.apache.felix.ipojo.annotations.PostRegistration;
+import org.apache.felix.ipojo.annotations.PostUnregistration;
+import org.apache.felix.ipojo.annotations.Property;
+import org.apache.felix.ipojo.annotations.Provides;
+import org.apache.felix.ipojo.annotations.Requires;
+import org.apache.felix.ipojo.annotations.ServiceController;
+import org.apache.felix.ipojo.annotations.ServiceProperty;
+import org.apache.felix.ipojo.annotations.Unbind;
+import org.apache.felix.ipojo.annotations.Updated;
+import org.apache.felix.ipojo.annotations.Validate;
+import org.apache.felix.ipojo.manipulator.Reporter;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.ComponentWorkbench;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.ComponentVisitor;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.ControllerVisitor;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.FieldPropertyVisitor;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.HandlerDeclarationVisitor;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.HandlerVisitor;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.InstantiateVisitor;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.LifecycleVisitor;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.MethodPropertyVisitor;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.ParameterPropertyVisitor;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.PostRegistrationVisitor;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.ProvidesVisitor;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.RequiresVisitor;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.ServiceControllerVisitor;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.UpdatedVisitor;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.bind.Action;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.bind.MethodBindVisitor;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.bind.ParameterBindVisitor;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.util.Elements;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.util.Names;
+import org.apache.felix.ipojo.manipulator.spi.AbsBindingModule;
+import org.apache.felix.ipojo.manipulator.spi.AnnotationVisitorFactory;
+import org.apache.felix.ipojo.manipulator.spi.BindingContext;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.tree.FieldNode;
+import org.objectweb.asm.tree.MethodNode;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import java.lang.annotation.ElementType;
+
+import static org.apache.felix.ipojo.manipulator.spi.helper.Predicates.on;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class DefaultBindingModule extends AbsBindingModule {
+
+    /**
+     * Configure all the iPOJO's default annotation's bindings.
+     */
+    public void configure() {
+
+        // Class level annotations
+        // --------------------------------
+        bind(Component.class)
+                .to(new AnnotationVisitorFactory() {
+                    public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
+                        return new ComponentVisitor(context.getWorkbench(), context.getReporter());
+                    }
+                });
+
+        bind(Handler.class)
+                .to(new AnnotationVisitorFactory() {
+                    public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
+                        return new HandlerVisitor(context.getWorkbench(), context.getReporter());
+                    }
+                });
+
+        bind(Provides.class)
+                .to(new AnnotationVisitorFactory() {
+                    public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
+                        return new ProvidesVisitor(context.getWorkbench());
+                    }
+                });
+
+
+        bind(HandlerDeclaration.class)
+                .to(new AnnotationVisitorFactory() {
+                    public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
+                        Reporter reporter = context.getReporter();
+                        return new HandlerDeclarationVisitor(context.getWorkbench(), getFreshDocumentBuilder(reporter), reporter);
+                    }
+                });
+
+        bind(Instantiate.class)
+                .to(new AnnotationVisitorFactory() {
+                    public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
+                        return new InstantiateVisitor(context.getWorkbench());
+                    }
+                });
+
+        // Field level annotations
+        // --------------------------------
+        bind(Requires.class)
+                .when(on(ElementType.FIELD))
+                .to(new AnnotationVisitorFactory() {
+                    public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
+                        return new RequiresVisitor(context.getWorkbench(), ((FieldNode) context.getNode()).name);
+                    }
+                })
+                .when(on(ElementType.PARAMETER))
+                .to(new AnnotationVisitorFactory() {
+                    public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
+                        return new ParameterBindVisitor(context.getWorkbench(), Action.BIND, context.getParameterIndex());
+                    }
+                });
+
+        bind(Controller.class)
+                .to(new AnnotationVisitorFactory() {
+                    public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
+                        return new ControllerVisitor(context.getWorkbench(), ((FieldNode) context.getNode()).name);
+                    }
+                });
+
+        bind(ServiceProperty.class)
+                .to(new AnnotationVisitorFactory() {
+                    public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
+                        String name = ((FieldNode) context.getNode()).name;
+                        ComponentWorkbench workbench = context.getWorkbench();
+
+                        if (!workbench.getIds().containsKey("provides")) {
+                            // The provides annotation is already computed.
+                            context.getReporter().warn("The component does not provide services, skip ServiceProperty for {}", name);
+                            return null;
+                        } else {
+                            // Get the provides element
+                            Element provides = workbench.getIds().get("provides");
+                            return new FieldPropertyVisitor(name, provides);
+                        }
+
+                    }
+                });
+
+        bind(ServiceController.class)
+                .to(new AnnotationVisitorFactory() {
+                    public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
+                        String name = ((FieldNode) context.getNode()).name;
+                        ComponentWorkbench workbench = context.getWorkbench();
+
+                        if (!workbench.getIds().containsKey("provides")) { // The provides annotation is already computed.
+                            context.getReporter().warn("The component does not provide services, skip @ServiceController for {}", name);
+                            return null;
+                        } else {
+                            // Get the provides element
+                            Element provides = workbench.getIds().get("provides");
+                            return new ServiceControllerVisitor(name, provides);
+                        }
+
+                    }
+                });
+
+        bind(Property.class)
+                .when(on(ElementType.FIELD))
+                .to(new AnnotationVisitorFactory() {
+                    public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
+
+                        ComponentWorkbench workbench = context.getWorkbench();
+                        Element properties = Elements.getPropertiesElement(workbench);
+                        String name = ((FieldNode) context.getNode()).name;
+                        return new FieldPropertyVisitor(name, properties);
+                    }
+
+                })
+                .when(on(ElementType.METHOD))
+                .to(new AnnotationVisitorFactory() {
+                    public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
+
+                        ComponentWorkbench workbench = context.getWorkbench();
+                        // @Property on method parameter
+                        Element properties = Elements.getPropertiesElement(workbench);
+                        String name = ((MethodNode) context.getNode()).name;
+                        return new MethodPropertyVisitor(properties, name);
+                    }
+                })
+                .when(on(ElementType.PARAMETER))
+                .to(new AnnotationVisitorFactory() {
+                    public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
+
+                        ComponentWorkbench workbench = context.getWorkbench();
+                        // @Property on method parameter
+                        Element properties = Elements.getPropertiesElement(workbench);
+                        MethodNode method = (MethodNode) context.getNode();
+                        return new ParameterPropertyVisitor(properties, method, context.getParameterIndex());
+                    }
+                });
+
+        bind(Validate.class)
+                .to(new AnnotationVisitorFactory() {
+                    public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
+                        MethodNode node = (MethodNode) context.getNode();
+                        return new LifecycleVisitor(context.getWorkbench(),
+                                Names.computeEffectiveMethodName(node.name),
+                                LifecycleVisitor.Transition.VALIDATE);
+                    }
+                });
+
+        bind(Invalidate.class)
+                .to(new AnnotationVisitorFactory() {
+                    public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
+                        MethodNode node = (MethodNode) context.getNode();
+                        return new LifecycleVisitor(context.getWorkbench(),
+                                Names.computeEffectiveMethodName(node.name),
+                                LifecycleVisitor.Transition.INVALIDATE);
+                    }
+                });
+
+        bind(Updated.class)
+                .to(new AnnotationVisitorFactory() {
+                    public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
+                        MethodNode node = (MethodNode) context.getNode();
+                        return new UpdatedVisitor(context.getWorkbench(),
+                                Names.computeEffectiveMethodName(node.name));
+                    }
+                });
+
+        bind(Bind.class)
+                .to(new AnnotationVisitorFactory() {
+                    public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
+                        MethodNode node = (MethodNode) context.getNode();
+                        return new MethodBindVisitor(context.getWorkbench(), Action.BIND, node.name);
+                    }
+                });
+
+        bind(Unbind.class)
+                .to(new AnnotationVisitorFactory() {
+                    public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
+                        MethodNode node = (MethodNode) context.getNode();
+                        return new MethodBindVisitor(context.getWorkbench(), Action.UNBIND, node.name);
+                    }
+                });
+
+        bind(Modified.class)
+                .to(new AnnotationVisitorFactory() {
+                    public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
+                        MethodNode node = (MethodNode) context.getNode();
+                        return new MethodBindVisitor(context.getWorkbench(), Action.MODIFIED, node.name);
+                    }
+                });
+
+        bind(PostRegistration.class)
+                .to(new AnnotationVisitorFactory() {
+                    public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
+                        MethodNode node = (MethodNode) context.getNode();
+                        return new PostRegistrationVisitor(context.getWorkbench(), node.name);
+                    }
+                });
+
+        bind(PostUnregistration.class)
+                .to(new AnnotationVisitorFactory() {
+                    public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
+                        MethodNode node = (MethodNode) context.getNode();
+                        return new PostRegistrationVisitor(context.getWorkbench(), node.name);
+                    }
+                });
+    }
+
+    private DocumentBuilder m_builder;
+
+
+    /**
+     * Creates a 'fresh' document builder.
+     * @return a new document builder is not already created, else reset
+     * the created one, and return it.
+     */
+    protected DocumentBuilder getFreshDocumentBuilder(Reporter reporter) {
+        if (m_builder == null) {
+
+            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+            factory.setNamespaceAware(true);
+            try {
+                m_builder = factory.newDocumentBuilder();
+            } catch (ParserConfigurationException e) {
+                // TODO GSA is this acceptable to throw a RuntimeException here ?
+                reporter.warn("Cannot get a fresh DocumentBuilder", e);
+            }
+
+            return m_builder;
+        }
+
+        // The builder has to be reseted
+        m_builder.reset();
+
+        return m_builder;
+    }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/Binding.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/Binding.java
new file mode 100644
index 0000000..e60e751
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/Binding.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.registry;
+
+import org.apache.felix.ipojo.manipulator.spi.AnnotationVisitorFactory;
+import org.apache.felix.ipojo.manipulator.spi.Predicate;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * Triple storing the source annotation, the associated factory and the predicate for conditional support.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class Binding {
+    private Class<? extends Annotation> annotationType;
+    private AnnotationVisitorFactory factory;
+    private Predicate predicate;
+
+    public Class<? extends Annotation> getAnnotationType() {
+        return annotationType;
+    }
+
+    public void setAnnotationType(Class<? extends Annotation> annotationType) {
+        this.annotationType = annotationType;
+    }
+
+    public AnnotationVisitorFactory getFactory() {
+        return factory;
+    }
+
+    public void setFactory(AnnotationVisitorFactory factory) {
+        this.factory = factory;
+    }
+
+    public Predicate getPredicate() {
+        return predicate;
+    }
+
+    public void setPredicate(Predicate predicate) {
+        this.predicate = predicate;
+    }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/BindingRegistry.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/BindingRegistry.java
new file mode 100644
index 0000000..cefbf20
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/BindingRegistry.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.registry;
+
+import org.apache.felix.ipojo.manipulator.Reporter;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.ComponentWorkbench;
+import org.apache.felix.ipojo.manipulator.spi.Predicate;
+import org.objectweb.asm.Type;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Stores all the {@link Binding}s coming from the {@link org.apache.felix.ipojo.manipulator.spi.Module}.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class BindingRegistry {
+    private Map<String, List<Binding>> tree;
+    private Reporter reporter;
+
+    /**
+     * When no other Binding is selected, the default Bindings list is used.
+     */
+    private List<Binding> defaultBindings;
+
+    public BindingRegistry(Reporter reporter) {
+        this.reporter = reporter;
+        tree = new HashMap<String, List<Binding>>();
+        defaultBindings = new ArrayList<Binding>();
+    }
+
+    /**
+     * Stores the given Bindings
+     */
+    public void addBindings(Iterable<Binding> bindings) {
+        for (Binding binding : bindings) {
+            Type type = Type.getType(binding.getAnnotationType());
+
+            List<Binding> potential = tree.get(type.getDescriptor());
+            if (potential == null) {
+                // Annotation is not already found in supported list
+                potential = new ArrayList<Binding>();
+                tree.put(type.getDescriptor(), potential);
+            }
+
+            potential.add(binding);
+        }
+    }
+
+    /**
+     * Initiate a {@link Selection} for the given workbench.
+     */
+    public Selection selection(ComponentWorkbench workbench) {
+        return new Selection(this, workbench, reporter);
+    }
+
+    public List<Binding> getBindings(String descriptor) {
+        return tree.get(descriptor);
+    }
+
+    public List<Binding> getDefaultBindings() {
+        return defaultBindings;
+    }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/Selection.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/Selection.java
new file mode 100644
index 0000000..1d26d80
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/Selection.java
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.registry;
+
+import org.apache.felix.ipojo.manipulator.Reporter;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.ComponentWorkbench;
+import org.apache.felix.ipojo.manipulator.spi.BindingContext;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.ClassNode;
+import org.objectweb.asm.tree.FieldNode;
+import org.objectweb.asm.tree.MemberNode;
+import org.objectweb.asm.tree.MethodNode;
+
+import java.lang.annotation.ElementType;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * A {@link Selection} is used to select a subset of all supported {@link AnnotationVisitor}.
+ * It's a query DSL.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class Selection implements Iterable<AnnotationVisitor> {
+
+    private BindingRegistry registry;
+    private ComponentWorkbench workbench;
+    private Reporter reporter;
+    private MemberNode node;
+    private int index = -1;
+    private String annotation;
+    private ElementType elementType = null;
+
+    public Selection(BindingRegistry registry, ComponentWorkbench workbench, Reporter reporter) {
+        this.registry = registry;
+        this.workbench = workbench;
+        this.reporter = reporter;
+    }
+
+    public Selection field(FieldNode node) {
+        this.node = node;
+        this.elementType = ElementType.FIELD;
+        return this;
+    }
+
+    public Selection method(MethodNode node) {
+        this.node = node;
+        this.elementType = ElementType.METHOD;
+        return this;
+    }
+
+    public Selection type(ClassNode node) {
+        this.node = node;
+        this.elementType = ElementType.TYPE;
+        return this;
+    }
+
+    public Selection parameter(MethodNode node, int index) {
+        this.index = index;
+        this.node = node;
+        this.elementType = ElementType.PARAMETER;
+        return this;
+    }
+
+    public Selection annotatedWith(String desc) {
+        this.annotation = desc;
+        return this;
+    }
+
+    public AnnotationVisitor get() {
+        Iterator<AnnotationVisitor> i = iterator();
+        if (iterator().hasNext()) {
+            return i.next();
+        }
+        return null;
+    }
+
+    public Iterator<AnnotationVisitor> iterator() {
+
+        List<AnnotationVisitor> visitors = new ArrayList<AnnotationVisitor>();
+
+        BindingContext context = new BindingContext(workbench, reporter, Type.getType(annotation), node, elementType, index);
+        List<Binding> predicates = registry.getBindings(annotation);
+
+        if (predicates != null && !predicates.isEmpty()) {
+            collectMatchingVisitors(predicates, context, visitors);
+        }
+
+        if (visitors.isEmpty() && !registry.getDefaultBindings().isEmpty()) {
+            collectMatchingVisitors(registry.getDefaultBindings(), context, visitors);
+        }
+
+
+        return visitors.iterator();
+    }
+
+    private void collectMatchingVisitors(List<Binding> bindings, BindingContext context, List<AnnotationVisitor> visitors) {
+        for (Binding binding : bindings) {
+            if (binding.getPredicate().matches(context)) {
+                AnnotationVisitor visitor = binding.getFactory().newAnnotationVisitor(context);
+                visitors.add(visitor);
+            }
+        }
+    }
+
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/ComponentVisitor.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/ComponentVisitor.java
new file mode 100644
index 0000000..5f0f58b
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/ComponentVisitor.java
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor;
+
+import org.apache.felix.ipojo.manipulator.Reporter;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.ComponentWorkbench;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.commons.EmptyVisitor;
+
+/**
+ * Parse the @Component annotation.
+ * @see org.apache.felix.ipojo.annotations.Component
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ComponentVisitor extends EmptyVisitor implements AnnotationVisitor {
+
+    private Reporter reporter;
+
+    /**
+     * Element 'properties'.
+     */
+    private Element m_props = new Element("properties", "");
+
+    private Element component = new Element("component", "");
+
+    private ComponentWorkbench workbench;
+
+    public ComponentVisitor(ComponentWorkbench workbench, Reporter reporter) {
+        this.workbench = workbench;
+        this.reporter = reporter;
+    }
+
+    /**
+     * Visit @Component annotation attribute.
+     * @param name attribute name
+     * @param value attribute value
+     * @see org.objectweb.asm.commons.EmptyVisitor#visit(java.lang.String, java.lang.Object)
+     */
+    public void visit(String name, Object value) {
+        if (name.equals("public_factory")  || name.equals("publicFactory")) {
+            // public_factory is deprecated, but must sill be supported
+            String factory = value.toString();
+            if (factory != null && factory.equalsIgnoreCase("false")) {
+                component.addAttribute(new Attribute("public", "false"));
+            } else {
+                component.addAttribute(new Attribute("public", "true"));
+            }
+            return;
+        }
+
+        if (name.equals("name")) {
+            component.addAttribute(new Attribute("name", value.toString()));
+            return;
+        }
+        if (name.equals("immediate")) {
+            component.addAttribute(new Attribute("immediate", value.toString()));
+            return;
+        }
+        if (name.equals("architecture")) {
+            component.addAttribute(new Attribute("architecture", value.toString()));
+            return;
+        }
+        if (name.equals("propagation") && (value != null)) {
+            if (arePropertiesEmpty()) {
+                initComponentProperties();
+            }
+            m_props.addAttribute(new Attribute("propagation", value.toString()));
+            return;
+        }
+        if (name.equals("managedservice") && (value != null)) {
+            if (arePropertiesEmpty()) {
+                initComponentProperties();
+            }
+            m_props.addAttribute(new Attribute("pid", value.toString()));
+            return;
+        }
+        if ((name.equals("factory_method")  || name.equals("factoryMethod")) && (value != null)) {
+            // factory_method is deprecated, but must still be supported.
+            component.addAttribute(new Attribute("factory-method", value.toString()));
+            return;
+        }
+        if (name.equals("version") && (value != null)) {
+            component.addAttribute(new Attribute("version", value.toString()));
+        }
+    }
+
+    private boolean arePropertiesEmpty() {
+        return m_props.getElements().length == 0;
+    }
+
+    private void initComponentProperties() {
+        workbench.getElements().put(m_props, null);
+        workbench.getIds().put("properties", m_props);
+    }
+
+    /**
+     * End of the visit.
+     * Append to the "component" element computed attribute.
+     * @see org.objectweb.asm.commons.EmptyVisitor#visitEnd()
+     */
+    public void visitEnd() {
+
+        String classname = workbench.getType().getClassName();
+
+        if (component.getAttribute("name") == null) {
+            component.addAttribute(new Attribute("name", classname));
+        }
+
+        component.addAttribute(new Attribute("classname", classname));
+
+        if (workbench.getRoot() == null) {
+            workbench.setRoot(component);
+        } else {
+            // Error case: 2 component type's annotations (@Component and @Handler for example) on the same class
+            reporter.error("Multiple 'component type' annotations on the class '{}'.", classname);
+            reporter.warn("@Component will be ignored.");
+        }
+    }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/ControllerVisitor.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/ControllerVisitor.java
new file mode 100644
index 0000000..e7d33af
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/ControllerVisitor.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.ComponentWorkbench;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.commons.EmptyVisitor;
+
+/**
+ * Parses the @Controller annotation.
+ * @see org.apache.felix.ipojo.annotations.Controller
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ControllerVisitor extends EmptyVisitor implements AnnotationVisitor {
+
+    private ComponentWorkbench workbench;
+
+    private String field;
+
+    public ControllerVisitor(ComponentWorkbench workbench, String field) {
+        this.workbench = workbench;
+        this.field = field;
+    }
+
+    /**
+     * Visit @Handler annotation attributes.
+     * @see org.objectweb.asm.commons.EmptyVisitor#visit(String, Object)
+     */
+    public void visitEnd() {
+        Element controller = new Element("controller", "");
+        controller.addAttribute(new Attribute("field", field));
+        workbench.getElements().put(controller, null);
+    }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/FieldPropertyVisitor.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/FieldPropertyVisitor.java
new file mode 100644
index 0000000..1c2bfdc
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/FieldPropertyVisitor.java
@@ -0,0 +1,151 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor;
+
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.commons.EmptyVisitor;
+
+/**
+ * Parses a Property or ServiceProperty annotation.
+ * @see org.apache.felix.ipojo.annotations.ServiceProperty
+ * @see org.apache.felix.ipojo.annotations.Property
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class FieldPropertyVisitor extends EmptyVisitor implements AnnotationVisitor {
+
+    /**
+     * Parent element element.
+     */
+    private Element m_parent;
+
+    /**
+     * Field name.
+     */
+    private String m_field;
+
+    /**
+     * Property name.
+     */
+    private String m_name;
+
+    /**
+     * Property value.
+     */
+    private String m_value;
+
+    /**
+     * Property mandatory aspect.
+     */
+    private String m_mandatory;
+
+    /**
+     * Property type.
+     */
+    private String m_type;
+
+
+    /**
+     * Constructor without field
+     * @param parent : element element..
+     */
+    public FieldPropertyVisitor(Element parent) {
+        this(null, parent);
+    }
+
+    /**
+     * Constructor.
+     * @param parent : element element.
+     * @param field : field name.
+     */
+    public FieldPropertyVisitor(String field, Element parent) {
+        m_parent = parent;
+        m_field = field;
+    }
+
+    /**
+     * Visit one "simple" annotation.
+     * @param name : annotation name
+     * @param value : annotation value
+     * @see org.objectweb.asm.AnnotationVisitor#visit(String, Object)
+     */
+    public void visit(String name, Object value) {
+        if (name.equals("name")) {
+            m_name = value.toString();
+            return;
+        }
+        if (name.equals("value")) {
+            m_value = value.toString();
+            return;
+        }
+        if (name.equals("mandatory")) {
+            m_mandatory = value.toString();
+            return;
+        }
+        if (name.equals("type")) {
+        	m_type = value.toString();
+        }
+    }
+
+    /**
+     * End of the annotation.
+     * Create a "property" element
+     * @see org.objectweb.asm.AnnotationVisitor#visitEnd()
+     */
+    public void visitEnd() {
+        if (m_field != null  && m_name == null) {
+            m_name = m_field;
+        }
+
+
+        Element[] props = m_parent.getElements("property");
+        Element prop = null;
+        for (int i = 0; prop == null && props != null && i < props.length; i++) {
+            String name = props[i].getAttribute("name");
+            if (name != null && name.equals(m_name)) {
+                prop = props[i];
+            }
+        }
+
+        if (prop == null) {
+            prop = new Element("property", "");
+            m_parent.addElement(prop);
+            if (m_name != null) {
+                prop.addAttribute(new Attribute("name", m_name));
+            }
+        }
+
+        if (m_field != null) {
+        	prop.addAttribute(new Attribute("field", m_field));
+        }
+        if (m_type != null) {
+        	prop.addAttribute(new Attribute("type", m_type));
+        }
+
+        if (m_value != null) {
+            prop.addAttribute(new Attribute("value", m_value));
+        }
+        if (m_mandatory != null) {
+            prop.addAttribute(new Attribute("mandatory", m_mandatory));
+        }
+
+    }
+}
\ No newline at end of file
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/HandlerDeclarationVisitor.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/HandlerDeclarationVisitor.java
new file mode 100644
index 0000000..2570afc
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/HandlerDeclarationVisitor.java
@@ -0,0 +1,157 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor;
+
+import org.apache.felix.ipojo.manipulator.Reporter;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.ComponentWorkbench;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.commons.EmptyVisitor;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.NodeList;
+
+import javax.xml.parsers.DocumentBuilder;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Parse the @HandlerDeclaration annotation.
+ * @see org.apache.felix.ipojo.annotations.HandlerDeclaration
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class HandlerDeclarationVisitor extends EmptyVisitor implements AnnotationVisitor {
+
+    /**
+     * XML accepted by the handler.
+     */
+    private String m_value;
+
+    private DocumentBuilder builder;
+
+    private ComponentWorkbench workbench;
+    private Reporter reporter;
+
+    public HandlerDeclarationVisitor(ComponentWorkbench workbench, DocumentBuilder builder, Reporter reporter) {
+        this.workbench = workbench;
+        this.builder = builder;
+        this.reporter = reporter;
+    }
+
+    /**
+     * Parses the value attribute.
+     * @param name 'value'
+     * @param value the value
+     * @see org.objectweb.asm.commons.EmptyVisitor#visit(java.lang.String, java.lang.Object)
+     */
+    public void visit(String name, Object value) {
+        // there is only a 'value' attribute
+        this.m_value = (String) value;
+    }
+
+    /**
+     * End of the visit.
+     * Builds the XML document.
+     * @see org.objectweb.asm.commons.EmptyVisitor#visitEnd()
+     */
+    public void visitEnd() {
+        // The value is an XML document
+        InputStream is = new ByteArrayInputStream(m_value.getBytes());
+        Document document = null;
+        try {
+            document = builder.parse(is);
+            Element e = convertDOMElements(document.getDocumentElement());
+            workbench.getElements().put(e, null);
+        } catch (Exception e) {
+            reporter.warn("Cannot convert {} to iPOJO Elements.", m_value, e);
+        } finally {
+            try {
+                is.close();
+            } catch (IOException e) {
+                reporter.trace("Cannot close correctly the value input stream ({}).", m_value, e);
+            }
+        }
+    }
+
+    /**
+     * Converts recursively the given XML Element into an iPOJO Element.
+     * @param xmlElement DOM Element to be converted
+     */
+    private static Element convertDOMElements(final org.w3c.dom.Element xmlElement) {
+
+        // Create an equivalent iPOJO element
+        Element converted = transformElement(xmlElement);
+
+        convertDOMElements(converted, xmlElement);
+
+        return converted;
+    }
+
+    /**
+     * Converts recursively the given XML Element into an iPOJO Element.
+     * @param root iPOJO root Element
+     * @param xmlElement DOM Element to be converted
+     */
+    private static void convertDOMElements(final Element root,
+                                           final org.w3c.dom.Element xmlElement) {
+
+        // Convert attributes if any
+        if (xmlElement.hasAttributes()) {
+            NamedNodeMap attributes = xmlElement.getAttributes();
+            for (int i = 0; i < attributes.getLength(); i++) {
+                Attr attr = (Attr) attributes.item(i);
+                root.addAttribute(transformAttribute(attr));
+            }
+        }
+
+        // Convert child elements if any
+        if (xmlElement.hasChildNodes()) {
+            NodeList children = xmlElement.getChildNodes();
+            for (int i = 0; i < children.getLength(); i++) {
+
+                // Create an equivalent iPOJO element
+                org.w3c.dom.Element child = (org.w3c.dom.Element) children.item(i);
+                Element converted = transformElement(child);
+
+                // Add converted element as a root's child
+                root.addElement(converted);
+
+                // Recursive call
+                convertDOMElements(converted, child);
+            }
+        }
+
+    }
+
+    private static Attribute transformAttribute(Attr attr) {
+        return new Attribute(attr.getName(),
+                attr.getNamespaceURI(),
+                attr.getValue());
+    }
+
+    private static Element transformElement(org.w3c.dom.Element xmlElement) {
+        return new Element(xmlElement.getLocalName(), xmlElement.getNamespaceURI());
+    }
+
+}
+
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/HandlerVisitor.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/HandlerVisitor.java
new file mode 100644
index 0000000..0bc16fd
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/HandlerVisitor.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor;
+
+import org.apache.felix.ipojo.manipulator.Reporter;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.ComponentWorkbench;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.commons.EmptyVisitor;
+
+/**
+ * Parses the @Handler annotation.
+ * @see org.apache.felix.ipojo.annotations.Handler
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class HandlerVisitor extends EmptyVisitor implements AnnotationVisitor {
+
+    private Element handler = new Element("handler", "");
+
+    private ComponentWorkbench workbench;
+
+    private Reporter reporter;
+
+    public HandlerVisitor(ComponentWorkbench workbench, Reporter reporter) {
+        this.workbench = workbench;
+        this.reporter = reporter;
+    }
+
+    /**
+     * Visit @Handler annotation attributes.
+     * @param name : annotation attribute name
+     * @param value : annotation attribute value
+     * @see org.objectweb.asm.commons.EmptyVisitor#visit(java.lang.String, java.lang.Object)
+     */
+    public void visit(String name, Object value) {
+        if (name.equals("name")) {
+            handler.addAttribute(new Attribute("name", value.toString()));
+            return;
+        }
+        if (name.equals("namespace")) {
+            handler.addAttribute(new Attribute("namespace", value.toString()));
+            return;
+        }
+        if (name.equals("level")) {
+            handler.addAttribute(new Attribute("level", value.toString()));
+            return;
+        }
+        if (name.equals("architecture")) {
+            handler.addAttribute(new Attribute("architecture", value.toString()));
+        }
+    }
+
+
+    /**
+     * End of the visit.
+     * Append to the "component" element computed attribute.
+     * @see org.objectweb.asm.commons.EmptyVisitor#visitEnd()
+     */
+    public void visitEnd() {
+
+        String classname = workbench.getType().getClassName();
+        handler.addAttribute(new Attribute("classname", classname));
+
+        if (workbench.getRoot() == null) {
+            workbench.setRoot(handler);
+        } else {
+            // Error case: 2 component type's annotations (@Component and @Handler for example) on the same class
+            reporter.error("Multiple 'component type' annotations on the class '{}'.", classname);
+            reporter.warn("@Handler will be ignored.");
+        }
+    }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/InstantiateVisitor.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/InstantiateVisitor.java
new file mode 100644
index 0000000..51beb15
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/InstantiateVisitor.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.ComponentWorkbench;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.commons.EmptyVisitor;
+
+/**
+ * Parse the @Instantitate annotation.
+ * @see org.apache.felix.ipojo.annotations.Instantiate
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class InstantiateVisitor extends EmptyVisitor implements AnnotationVisitor {
+
+    private Element instance = new Element("instance", "");
+
+    private ComponentWorkbench workbench;
+
+    public InstantiateVisitor(ComponentWorkbench workbench) {
+        this.workbench = workbench;
+    }
+
+    /**
+     * Visit an annotation attribute.
+     * @param name the attribute name
+     * @param value the attribute value
+     * @see org.objectweb.asm.commons.EmptyVisitor#visit(java.lang.String, java.lang.Object)
+     */
+    public void visit(String name, Object value) {
+        if (name.equals("name")) {
+            instance.addAttribute(new Attribute("name", (String) value));
+        }
+    }
+
+    /**
+     * End of the visit. Creates the instance element.
+     * @see org.objectweb.asm.commons.EmptyVisitor#visitEnd()
+     */
+    public void visitEnd() {
+        // TODO Is this really the classname that we need here ? Or the component's name ?
+        instance.addAttribute(new Attribute("component", workbench.getType().getClassName()));
+
+        workbench.setInstance(instance);
+
+    }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/LifecycleVisitor.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/LifecycleVisitor.java
new file mode 100644
index 0000000..61ea087
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/LifecycleVisitor.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.ComponentWorkbench;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.commons.EmptyVisitor;
+
+/**
+ * Parse @Validate and @Invalidate annotations.
+ * @see org.apache.felix.ipojo.annotations.Validate
+ * @see org.apache.felix.ipojo.annotations.Invalidate
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class LifecycleVisitor extends EmptyVisitor implements AnnotationVisitor {
+
+    public static enum Transition {
+        VALIDATE, INVALIDATE
+    }
+
+    private ComponentWorkbench workbench;
+    private String name;
+    private Transition transition;
+
+    public LifecycleVisitor(ComponentWorkbench workbench, String name, Transition transition) {
+        this.workbench = workbench;
+        this.name = name;
+        this.transition = transition;
+    }
+
+    @Override
+    public void visitEnd() {
+        Element cb = new Element("callback", "");
+        cb.addAttribute(new Attribute("transition", transition.name().toLowerCase()));
+        cb.addAttribute(new Attribute("method", name));
+        workbench.getElements().put(cb, null);
+    }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/MethodPropertyVisitor.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/MethodPropertyVisitor.java
new file mode 100644
index 0000000..5804c6c
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/MethodPropertyVisitor.java
@@ -0,0 +1,163 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor;
+
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.commons.EmptyVisitor;
+
+import static org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.util.Names.computeEffectiveMethodName;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class MethodPropertyVisitor extends EmptyVisitor implements AnnotationVisitor {
+
+    /**
+     * Parent element.
+     */
+    private Element m_parent;
+
+    /**
+     * Attached method.
+     */
+    private String m_method;
+
+    /**
+     * Property name.
+     */
+    private String m_name;
+
+    /**
+     * Property id.
+     */
+    private String m_id;
+
+    /**
+     * Property value.
+     */
+    private String m_value;
+
+    /**
+     * Property mandatory aspect.
+     */
+    private String m_mandatory;
+
+    /**
+     * Constructor.
+     *
+     * @param parent : element element.
+     * @param method : attached method.
+     */
+    public MethodPropertyVisitor(Element parent, String method) {
+        m_parent = parent;
+        m_method = method;
+    }
+
+    /**
+     * Visit annotation attributes.
+     *
+     * @param name : annotation name
+     * @param value : annotation value
+     * @see org.objectweb.asm.commons.EmptyVisitor#visit(java.lang.String, java.lang.Object)
+     */
+    public void visit(String name, Object value) {
+        if (name.equals("name")) {
+            m_name = value.toString();
+            return;
+        }
+        if (name.equals("value")) {
+            m_value = value.toString();
+            return;
+        }
+        if (name.equals("mandatory")) {
+            m_mandatory = value.toString();
+            return;
+        }
+        if (name.equals("id")) {
+            m_id = value.toString();
+        }
+    }
+
+    /**
+     * End of the visit.
+     * Append the computed element to the element element.
+     *
+     * @see org.objectweb.asm.commons.EmptyVisitor#visitEnd()
+     */
+    public void visitEnd() {
+        Element prop = visitEndCommon();
+
+        prop.addAttribute(new Attribute("method", m_method));
+
+    }
+
+    protected Element visitEndCommon() {
+        m_method = computeEffectiveMethodName(m_method);
+
+        // If neither name nor id is provided, try to extract the name
+        if (m_name == null && m_id == null && m_method.startsWith("set")) {
+            m_name = m_method.substring("set".length());
+            m_id = m_name;
+            // Else align the two values
+        } else if (m_name != null && m_id == null) {
+            m_id = m_name;
+        } else if (m_id != null && m_name == null) {
+            m_name = m_id;
+        }
+
+        Element prop = getPropertyElement();
+
+        if (m_value != null) {
+            prop.addAttribute(new Attribute("value", m_value));
+        }
+        if (m_mandatory != null) {
+            prop.addAttribute(new Attribute("mandatory", m_mandatory));
+        }
+        return prop;
+    }
+
+    private Element getPropertyElement() {
+
+        // Gather all the <property> Elements
+        Element[] props = m_parent.getElements("property");
+        Element prop = null;
+        for (int i = 0; props != null && prop == null && i < props.length; i++) {
+
+            // Get the first one with the good name
+            String name = props[i].getAttribute("name");
+            if (name != null && name.equals(m_name)) {
+                prop = props[i];
+            }
+        }
+
+        // Create the Element if not present
+        if (prop == null) {
+            prop = new Element("property", "");
+            m_parent.addElement(prop);
+            if (m_name != null) {
+                prop.addAttribute(new Attribute("name", m_name));
+            }
+        }
+
+        return prop;
+    }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/ParameterPropertyVisitor.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/ParameterPropertyVisitor.java
new file mode 100644
index 0000000..fb5ca87
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/ParameterPropertyVisitor.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor;
+
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.MethodNode;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ParameterPropertyVisitor extends MethodPropertyVisitor implements AnnotationVisitor {
+
+    /**
+     * If this is a parameter annotation, the index of the parameter.
+     */
+    private int m_index = -1;
+
+    private MethodNode node;
+
+    /**
+     * Constructor.
+     *
+     * @param parent : element element.
+     * @param method : attached method.
+     * @param index  : the parameter index
+     */
+    public ParameterPropertyVisitor(Element parent, MethodNode method, int index) {
+        super(parent, method.name);
+        this.node = method;
+        m_index = index;
+    }
+
+    /**
+     * End of the visit.
+     * Append the computed element to the element element.
+     *
+     * @see org.objectweb.asm.commons.EmptyVisitor#visitEnd()
+     */
+    public void visitEnd() {
+        Element prop = visitEndCommon();
+        String type = Type.getArgumentTypes(node.desc)[m_index].getClassName();
+        prop.addAttribute(new Attribute("type", type));
+        prop.addAttribute(new Attribute("constructor-parameter", Integer.toString(m_index)));
+
+    }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/PostRegistrationVisitor.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/PostRegistrationVisitor.java
new file mode 100644
index 0000000..873fde8
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/PostRegistrationVisitor.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.ComponentWorkbench;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.commons.EmptyVisitor;
+
+/**
+ * @see org.apache.felix.ipojo.annotations.PostRegistration
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class PostRegistrationVisitor extends EmptyVisitor implements AnnotationVisitor {
+
+    private ComponentWorkbench workbench;
+    private String name;
+
+    public PostRegistrationVisitor(ComponentWorkbench workbench, String name) {
+        this.workbench = workbench;
+        this.name = name;
+    }
+
+    @Override
+    public void visitEnd() {
+        Element provides = null;
+        if (workbench.getIds().containsKey("provides")) {
+            provides = workbench.getIds().get("provides");
+            provides.addAttribute(new Attribute("post-registration", name));
+        }
+        // Else ignore annotation ...
+    }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/PostUnregistrationVisitor.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/PostUnregistrationVisitor.java
new file mode 100644
index 0000000..eae941e
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/PostUnregistrationVisitor.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.ComponentWorkbench;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.commons.EmptyVisitor;
+
+/**
+ * @see org.apache.felix.ipojo.annotations.PostUnregistration
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class PostUnregistrationVisitor extends EmptyVisitor implements AnnotationVisitor {
+
+    private ComponentWorkbench workbench;
+    private String name;
+
+    public PostUnregistrationVisitor(ComponentWorkbench workbench, String name) {
+        this.workbench = workbench;
+        this.name = name;
+    }
+
+    @Override
+    public void visitEnd() {
+        Element provides = null;
+        if (workbench.getIds().containsKey("provides")) {
+            provides = workbench.getIds().get("provides");
+            provides.addAttribute(new Attribute("post-unregistration", name));
+        }
+        // Else ignore annotation ...
+    }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/ProvidesVisitor.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/ProvidesVisitor.java
new file mode 100644
index 0000000..d23aa33
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/ProvidesVisitor.java
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.ComponentWorkbench;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.commons.EmptyVisitor;
+
+/**
+ * Parse the @Provides annotation.
+ * @see org.apache.felix.ipojo.annotations.Provides
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ProvidesVisitor extends EmptyVisitor implements AnnotationVisitor {
+
+    private ComponentWorkbench workbench;
+
+    /**
+     * Provides element.
+     */
+    private Element m_prov = new Element("provides", "");
+
+    public ProvidesVisitor(ComponentWorkbench workbench) {
+        this.workbench = workbench;
+    }
+
+    /**
+     * Visit @provides annotation attributes.
+     * @param name : annotation attribute name
+     * @param value : annotation attribute value
+     * @see org.objectweb.asm.commons.EmptyVisitor#visit(java.lang.String, java.lang.Object)
+     */
+    public void visit(String name, Object value) {
+        if (name.equals("factory")) { // Should be deprecated
+            m_prov.addAttribute(new Attribute("factory", value.toString()));
+        }
+        if (name.equals("strategy")) {
+            m_prov.addAttribute(new Attribute("strategy", value.toString()));
+        }
+    }
+
+    /**
+     * Visit specifications array.
+     * @param name : attribute name
+     * @return a visitor visiting each element of the array.
+     * @see org.objectweb.asm.commons.EmptyVisitor#visitArray(java.lang.String)
+     */
+    public AnnotationVisitor visitArray(String name) {
+        if (name.equals("specifications")) {
+            return new InterfaceArrayVisitor();
+        } else if (name.equals("properties")) {
+            // Create a new simple visitor to visit the nested ServiceProperty annotations
+            // Collected properties are collected in m_prov
+            return new EmptyVisitor() {
+                public AnnotationVisitor visitAnnotation(String ignored, String desc) {
+                    return new FieldPropertyVisitor(m_prov);
+                }
+            };
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * End of the visit.
+     * Append to the element element the computed "provides" element.
+     * @see org.objectweb.asm.commons.EmptyVisitor#visitEnd()
+     */
+    public void visitEnd() {
+        workbench.getIds().put("provides", m_prov);
+        workbench.getElements().put(m_prov, null);
+    }
+
+    private class InterfaceArrayVisitor extends EmptyVisitor {
+        /**
+         * List of parsed interface.
+         */
+        private String m_itfs;
+
+        /**
+         * Visit one element of the array.
+         * @param arg0 : null
+         * @param arg1 : element value.
+         * @see org.objectweb.asm.commons.EmptyVisitor#visit(java.lang.String, java.lang.Object)
+         */
+        public void visit(String arg0, Object arg1) {
+            if (m_itfs == null) {
+                m_itfs = "{" + ((Type) arg1).getClassName();
+            } else {
+                m_itfs += "," + ((Type) arg1).getClassName();
+            }
+        }
+
+        /**
+         * End of the array visit.
+         * Add the attribute to 'provides' element.
+         * @see org.objectweb.asm.commons.EmptyVisitor#visitEnd()
+         */
+        public void visitEnd() {
+            m_prov.addAttribute(new Attribute("specifications", m_itfs + "}"));
+        }
+
+    }
+
+
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/RequiresVisitor.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/RequiresVisitor.java
new file mode 100644
index 0000000..73ae8a0
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/RequiresVisitor.java
@@ -0,0 +1,210 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.ComponentWorkbench;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.commons.EmptyVisitor;
+
+/**
+ * AnnotationVisitor parsing the @Requires annotation.
+ * @see org.apache.felix.ipojo.annotations.Requires
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class RequiresVisitor extends EmptyVisitor implements AnnotationVisitor {
+
+
+    private ComponentWorkbench workbench;
+
+    /**
+     * Dependency field.
+     */
+    private String m_field;
+
+    /**
+     * Dependency filter.
+     */
+    private String m_filter;
+
+    /**
+     * Is the dependency optional ?
+     */
+    private String m_optional;
+
+    /**
+     * Dependency specification.
+     */
+    private String m_specification;
+
+    /**
+     * Dependency id.
+     */
+    private String m_id;
+
+    /**
+     * Binding policy.
+     */
+    private String m_policy;
+
+    /**
+     * Default-Implementation attribute.
+     */
+    private String m_defaultImplementation;
+
+    /**
+     * Enable or Disable Nullable pattern.
+     */
+    private String m_nullable;
+
+    /**
+     * Comparator.
+     */
+    private String m_comparator;
+
+    /**
+     * From attribute.
+     */
+    private String m_from;
+
+    /**
+     * Proxy attribute.
+     */
+    private String m_proxy;
+
+    /**
+     * Constructor.
+     * @param name : field name.
+     */
+    public RequiresVisitor(ComponentWorkbench workbench, String name) {
+        this.workbench = workbench;
+        this.m_field = name;
+    }
+
+    /**
+     * Visit one "simple" annotation.
+     * @param name : annotation name
+     * @param value : annotation value
+     * @see org.objectweb.asm.AnnotationVisitor#visit(java.lang.String, java.lang.Object)
+     */
+    public void visit(String name, Object value) {
+        if (name.equals("filter")) {
+            m_filter = value.toString();
+            return;
+        }
+        if (name.equals("optional")) {
+            m_optional = value.toString();
+            return;
+        }
+        if (name.equals("nullable")) {
+            m_nullable = value.toString();
+            return;
+        }
+        if (name.equals("policy")) {
+            m_policy = value.toString();
+            return;
+        }
+        if (name.equals("defaultimplementation")) {
+            Type type = Type.getType(value.toString());
+            m_defaultImplementation = type.getClassName();
+            return;
+        }
+        if (name.equals("specification")) {
+            m_specification = value.toString();
+            return;
+        }
+        if (name.equals("id")) {
+            m_id = value.toString();
+            return;
+        }
+        if (name.equals("comparator")) {
+            Type type = Type.getType(value.toString());
+            m_comparator = type.getClassName();
+            return;
+        }
+        if (name.equals("from")) {
+            m_from = value.toString();
+            return;
+        }
+        if (name.equals("proxy")) {
+            m_proxy = value.toString();
+        }
+    }
+
+    /**
+     * End of the annotation.
+     * Create a "requires" element
+     * @see org.objectweb.asm.AnnotationVisitor#visitEnd()
+     */
+    public void visitEnd() {
+        Element requires = null;
+        if (m_id == null) {
+            requires = workbench.getIds().get(m_field);
+        } else {
+            requires = workbench.getIds().get(m_id);
+        }
+
+        if (requires == null) {
+            requires = new Element("requires", "");
+        }
+
+        requires.addAttribute(new Attribute("field", m_field));
+        if (m_specification != null) {
+            requires.addAttribute(new Attribute("specification", m_specification));
+        }
+        if (m_filter != null) {
+            requires.addAttribute(new Attribute("filter", m_filter));
+        }
+        if (m_optional != null) {
+            requires.addAttribute(new Attribute("optional", m_optional));
+        }
+        if (m_nullable != null) {
+            requires.addAttribute(new Attribute("nullable", m_nullable));
+        }
+        if (m_defaultImplementation != null) {
+            requires.addAttribute(new Attribute("default-implementation", m_defaultImplementation));
+        }
+        if (m_policy != null) {
+            requires.addAttribute(new Attribute("policy", m_policy));
+        }
+        if (m_id != null) {
+            requires.addAttribute(new Attribute("id", m_id));
+        }
+        if (m_comparator != null) {
+            requires.addAttribute(new Attribute("comparator", m_comparator));
+        }
+        if (m_from != null) {
+            requires.addAttribute(new Attribute("from", m_from));
+        }
+        if (m_proxy != null) {
+            requires.addAttribute(new Attribute("proxy", m_proxy));
+        }
+
+        if (m_id != null) {
+            workbench.getIds().put(m_id, requires);
+        } else {
+            workbench.getIds().put(m_field, requires);
+        }
+
+        workbench.getElements().put(requires, null);
+    }
+}
\ No newline at end of file
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/ServiceControllerVisitor.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/ServiceControllerVisitor.java
new file mode 100644
index 0000000..5aad731
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/ServiceControllerVisitor.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor;
+
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.commons.EmptyVisitor;
+
+/**
+ * Parses a @ServiceController annotation.
+ * @see org.apache.felix.ipojo.annotations.ServiceController
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ServiceControllerVisitor extends EmptyVisitor implements AnnotationVisitor {
+
+    /**
+     * Parent element.
+     */
+    private Element provides;
+
+    /**
+     * Provides element.
+     */
+    private Element controller = new Element("controller", "");
+
+    /**
+     * Constructor.
+     * @param provides : element element.
+     * @param field : field name.
+     */
+    public ServiceControllerVisitor(String field, Element provides) {
+        this.provides = provides;
+        controller.addAttribute(new Attribute("field", field));
+    }
+
+    /**
+     * Visit one "simple" annotation.
+     * @param name : annotation name
+     * @param value : annotation value
+     * @see org.objectweb.asm.AnnotationVisitor#visit(java.lang.String, java.lang.Object)
+     */
+    public void visit(String name, Object value) {
+        if (name.equals("value")) {
+            controller.addAttribute(new Attribute("value", value.toString()));
+            return;
+        }
+        if (name.equals("specification")) {
+            String spec = ((Type) value).getClassName();
+            controller.addAttribute(new Attribute("specification", spec));
+        }
+    }
+
+    /**
+     * End of the annotation.
+     * Create a "controller" element
+     * @see org.objectweb.asm.AnnotationVisitor#visitEnd()
+     */
+    public void visitEnd() {
+        provides.addElement(controller);
+    }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/UpdatedVisitor.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/UpdatedVisitor.java
new file mode 100644
index 0000000..7a3d844
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/UpdatedVisitor.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.ComponentWorkbench;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.util.Elements;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.commons.EmptyVisitor;
+
+/**
+ * @see org.apache.felix.ipojo.annotations.Updated
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class UpdatedVisitor extends EmptyVisitor implements AnnotationVisitor {
+
+    private ComponentWorkbench workbench;
+    private String name;
+
+    public UpdatedVisitor(ComponentWorkbench workbench, String name) {
+        this.workbench = workbench;
+        this.name = name;
+    }
+
+    @Override
+    public void visitEnd() {
+        Element properties = Elements.getPropertiesElement(workbench);
+        properties.addAttribute(new Attribute("updated", name));
+
+    }
+
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/bind/AbstractBindVisitor.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/bind/AbstractBindVisitor.java
new file mode 100644
index 0000000..29461ce
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/bind/AbstractBindVisitor.java
@@ -0,0 +1,210 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.bind;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.ComponentWorkbench;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.commons.EmptyVisitor;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public abstract class AbstractBindVisitor extends EmptyVisitor implements AnnotationVisitor {
+
+    protected ComponentWorkbench workbench;
+    protected Action action;
+
+    public AbstractBindVisitor(ComponentWorkbench workbench, Action action) {
+        this.workbench = workbench;
+        this.action = action;
+    }
+
+    /**
+     * Requirement filter.
+     */
+    protected String m_filter;
+    /**
+     * Is the requirement optional?
+     */
+    protected String m_optional;
+    /**
+     * Is the requirement aggregate?
+     */
+    protected String m_aggregate;
+    /**
+     * Required specification.
+     */
+    protected String m_specification;
+    /**
+     * Requirement id.
+     */
+    protected String m_id;
+    /**
+     * Binding policy.
+     */
+    protected String m_policy;
+    /**
+     * Comparator.
+     */
+    protected String m_comparator;
+    /**
+     * From attribute.
+     */
+    protected String m_from;
+
+    /**
+     * Visit annotation's attributes.
+     *
+     * @param name : annotation name
+     * @param value : annotation value
+     * @see org.objectweb.asm.commons.EmptyVisitor#visit(String, Object)
+     */
+    public void visit(String name, Object value) {
+        if (name.equals("filter")) {
+            m_filter = value.toString();
+            return;
+        }
+        if (name.equals("optional")) {
+            m_optional = value.toString();
+            return;
+        }
+        if (name.equals("aggregate")) {
+            m_aggregate = value.toString();
+            return;
+        }
+        if (name.equals("specification")) {
+            m_specification = value.toString();
+            return;
+        }
+        if (name.equals("policy")) {
+            m_policy = value.toString();
+            return;
+        }
+        if (name.equals("id")) {
+            m_id = value.toString();
+            return;
+        }
+        if (name.equals("comparator")) {
+            Type type = Type.getType(value.toString());
+            m_comparator = type.getClassName();
+            return;
+        }
+        if (name.equals("from")) {
+            m_from = value.toString();
+        }
+
+    }
+
+    public void visitEnd() {
+    }
+
+    protected Element getRequiresElement() {
+
+        // Check if it is a full-determined requirement
+        Element requires = workbench.getIds().get(m_id);
+        if (requires == null) {
+            // Add the complete requires
+            requires = createRequiresElement();
+        } else {
+            if (!completeExistingRequires(requires))
+                return null;
+        }
+
+        return requires;
+    }
+
+    protected boolean completeExistingRequires(Element requires) {
+
+        if (!completeAttribute(requires, "specification", m_specification))
+            return false;
+
+        if (!completeAttribute(requires, "optional", m_optional))
+            return false;
+
+        if (!completeAttribute(requires, "aggregate", m_aggregate))
+            return false;
+
+        if (!completeAttribute(requires, "filter", m_filter))
+            return false;
+
+        if (!completeAttribute(requires, "policy", m_policy))
+            return false;
+
+        if (!completeAttribute(requires, "comparator", m_comparator))
+            return false;
+
+        if (!completeAttribute(requires, "from", m_from))
+            return false;
+
+        return true;
+    }
+
+    private boolean completeAttribute(Element requires, String name, String value) {
+        // If we have a value
+        if (value != null) {
+
+            String old = requires.getAttribute(name);
+            if (old == null) {
+                // If the old value was not set, just set the new value
+                requires.addAttribute(new Attribute(name, value));
+            } else if (!value.equals(old)) {
+                //
+                System.err.println("The '" + name + "' attribute has changed: " + old + " -> " + value);
+                return false;
+            } // Otherwise, the old and new value are equals
+        }
+        return true;
+    }
+
+    protected Element createRequiresElement() {
+        Element requires;
+        requires = new Element("requires", "");
+        if (m_specification != null) {
+            requires.addAttribute(new Attribute("specification", m_specification));
+        }
+        if (m_aggregate != null) {
+            requires.addAttribute(new Attribute("aggregate", m_aggregate));
+        }
+        if (m_filter != null) {
+            requires.addAttribute(new Attribute("filter", m_filter));
+        }
+        if (m_optional != null) {
+            requires.addAttribute(new Attribute("optional", m_optional));
+        }
+        if (m_policy != null) {
+            requires.addAttribute(new Attribute("policy", m_policy));
+        }
+        if (m_id != null) {
+            requires.addAttribute(new Attribute("id", m_id));
+        }
+        if (m_comparator != null) {
+            requires.addAttribute(new Attribute("comparator", m_comparator));
+        }
+        if (m_from != null) {
+            requires.addAttribute(new Attribute("from", m_from));
+        }
+        return requires;
+    }
+
+
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/bind/Action.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/bind/Action.java
new file mode 100644
index 0000000..5ed64a1
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/bind/Action.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.bind;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public enum Action {
+    BIND, MODIFIED, UNBIND
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/bind/MethodBindVisitor.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/bind/MethodBindVisitor.java
new file mode 100644
index 0000000..6be36fc
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/bind/MethodBindVisitor.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.bind;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.ComponentWorkbench;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.util.Names;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+
+import static org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.util.Names.computeEffectiveMethodName;
+
+/**
+ * Parse @Bind & @Unbind annotations on methods.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class MethodBindVisitor extends AbstractBindVisitor {
+
+    /**
+     * Method name.
+     */
+    private String m_name;
+
+    public MethodBindVisitor(ComponentWorkbench workbench, Action action, String method) {
+        super(workbench, action);
+        this.m_name = method;
+    }
+
+    /**
+     * End of the visit.
+     * Create or append the requirement info to a created or already existing "requires" element.
+     *
+     * @see org.objectweb.asm.commons.EmptyVisitor#visitEnd()
+     */
+    public void visitEnd() {
+        if (m_id == null) {
+            String identifier = Names.getMethodIdentifier(m_name);
+            if (identifier != null) {
+                m_id = identifier;
+            } else {
+                System.err.println("Cannot determine the id of the " + action.name() + " method : " + computeEffectiveMethodName(m_name));
+                return;
+            }
+        }
+
+        Element requires = getRequiresElement();
+
+        Element callback = new Element("callback", "");
+        callback.addAttribute(new Attribute("method", computeEffectiveMethodName(m_name)));
+        callback.addAttribute(new Attribute("type", action.name().toLowerCase()));
+        requires.addElement(callback);
+
+        workbench.getIds().put(m_id, requires);
+        workbench.getElements().put(requires, null);
+    }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/bind/ParameterBindVisitor.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/bind/ParameterBindVisitor.java
new file mode 100644
index 0000000..b3063ee
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/bind/ParameterBindVisitor.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.bind;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.ComponentWorkbench;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+
+/**
+ * Parse @Bind & @Unbind annotations on method's parameters.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ParameterBindVisitor extends AbstractBindVisitor {
+
+    /**
+     * For annotation parameter,
+     * the parameter index.
+     */
+    private int m_index;
+
+    public ParameterBindVisitor(ComponentWorkbench workbench, Action action, int index) {
+        super(workbench, action);
+        m_index = index;
+    }
+
+    /**
+     * End of the visit.
+     * Create or append the requirement info to a created or already existing "requires" element.
+     *
+     * @see org.objectweb.asm.commons.EmptyVisitor#visitEnd()
+     */
+    public void visitEnd() {
+        if (m_id == null) {
+            m_id = Integer.toString(m_index);
+        }
+
+        Element requires = getRequiresElement();
+
+        // Specific for parameters
+        requires.addAttribute(new Attribute("constructor-parameter", Integer.toString(m_index)));
+
+        workbench.getIds().put(m_id, requires);
+        workbench.getElements().put(requires, null);
+    }
+
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/generic/FieldGenericVisitor.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/generic/FieldGenericVisitor.java
new file mode 100644
index 0000000..b2edce0
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/generic/FieldGenericVisitor.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.generic;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.ComponentWorkbench;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.tree.FieldNode;
+
+import java.lang.annotation.ElementType;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class FieldGenericVisitor extends RootGenericVisitor {
+    public FieldGenericVisitor(ComponentWorkbench workbench, Element element, FieldNode node) {
+        super(workbench, element, ElementType.FIELD);
+        element.addAttribute(new Attribute("field", node.name));
+    }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/generic/GenericVisitor.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/generic/GenericVisitor.java
new file mode 100644
index 0000000..cd1296a
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/generic/GenericVisitor.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.generic;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.util.Elements;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.commons.EmptyVisitor;
+
+import java.lang.reflect.Array;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class GenericVisitor extends EmptyVisitor implements AnnotationVisitor {
+    protected Element element;
+
+    public GenericVisitor(Element element) {
+        this.element = element;
+    }
+
+    /**
+     * Visit a 'simple' annotation attribute.
+     * This method is used for primitive arrays too.
+     * @param name : attribute name
+     * @param value : attribute value
+     * @see org.objectweb.asm.commons.EmptyVisitor#visit(String, Object)
+     */
+    public void visit(String name, Object value) {
+        if (value.getClass().isArray()) {
+            // Primitive arrays case
+            String v = null;
+            int index = Array.getLength(value);
+            for (int i = 0; i < index; i++) {
+                if (v == null) {
+                    v = "{" + Array.get(value, i);
+                } else {
+                    v += "," + Array.get(value, i);
+                }
+            }
+            v += "}";
+            element.addAttribute(new Attribute(name, v));
+            return;
+        }
+
+        // Attributes are added as normal attributes
+        if (!(value instanceof Type)) {
+            element.addAttribute(new Attribute(name, value.toString()));
+        } else {
+            // Attributes of type class need a special handling
+            element.addAttribute(new Attribute(name, ((Type) value).getClassName()));
+        }
+
+    }
+
+    /**
+     * Visit a sub-annotation.
+     * @param name : attribute name.
+     * @param descriptor : annotation description
+     * @return an annotation visitor which will visit the given annotation
+     * @see org.objectweb.asm.commons.EmptyVisitor#visitAnnotation(String, String)
+     */
+    public AnnotationVisitor visitAnnotation(String name, String descriptor) {
+        // Sub annotations are mapped to sub-elements
+        Element sub = Elements.buildElement(Type.getType(descriptor));
+        element.addElement(sub);
+        return new GenericVisitor(sub);
+    }
+
+    /**
+     * Visit an array attribute.
+     * @param name : attribute name
+     * @return a visitor which will visit each element of the array
+     * @see org.objectweb.asm.commons.EmptyVisitor#visitArray(String)
+     */
+    public AnnotationVisitor visitArray(String name) {
+        return new SubArrayVisitor(element, name);
+    }
+
+    /**
+     * Visits an enumeration attribute.
+     * @param name the attribute name
+     * @param desc the enumeration descriptor
+     * @param value the attribute value
+     * @see org.objectweb.asm.AnnotationVisitor#visitEnum(String, String, String)
+     */
+    public void visitEnum(String name, String desc, String value) {
+        element.addAttribute(new Attribute(name, value));
+    }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/generic/MethodGenericVisitor.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/generic/MethodGenericVisitor.java
new file mode 100644
index 0000000..29c558a
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/generic/MethodGenericVisitor.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.generic;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.ComponentWorkbench;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.tree.MethodNode;
+
+import java.lang.annotation.ElementType;
+
+import static org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.util.Names.computeEffectiveMethodName;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class MethodGenericVisitor extends RootGenericVisitor {
+    public MethodGenericVisitor(ComponentWorkbench workbench, Element element, MethodNode node) {
+        super(workbench, element, ElementType.METHOD);
+        element.addAttribute(new Attribute("method", computeEffectiveMethodName(node.name)));
+    }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/generic/ParameterGenericVisitor.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/generic/ParameterGenericVisitor.java
new file mode 100644
index 0000000..c3e59e7
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/generic/ParameterGenericVisitor.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.generic;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.ComponentWorkbench;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.MethodNode;
+
+import java.lang.annotation.ElementType;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ParameterGenericVisitor extends RootGenericVisitor {
+    private int index;
+    private MethodNode node;
+
+    public ParameterGenericVisitor(ComponentWorkbench workbench, Element element, MethodNode node, int index) {
+        super(workbench, element, ElementType.PARAMETER);
+        this.node = node;
+        this.index = index;
+    }
+
+    @Override
+    public void visitEnd() {
+        super.visitEnd();
+
+        String type = Type.getArgumentTypes(node.desc)[index].getClassName();
+        // TODO Is the 'index' attribute required ?
+        element.addAttribute(new Attribute("index", Integer.toString(index)));
+        element.addAttribute(new Attribute("type", type));
+        element.addAttribute(new Attribute("constructor-parameter", Integer.toString(index)));
+
+    }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/generic/RootGenericVisitor.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/generic/RootGenericVisitor.java
new file mode 100644
index 0000000..2bb65aa
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/generic/RootGenericVisitor.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.generic;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.ComponentWorkbench;
+import org.apache.felix.ipojo.metadata.Element;
+
+import java.lang.annotation.ElementType;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class RootGenericVisitor extends GenericVisitor {
+    private ComponentWorkbench workbench;
+
+    /**
+     * Id attribute (if found)
+     * else use the annotation package name.
+     */
+    private String m_id;
+
+    /**
+     * Parent attribute (if found)
+     * else use the annotation package name.
+     */
+    private String m_parent;
+
+    /**
+     * Describes the structure that supports the traversed annotation.
+     */
+    private ElementType type;
+
+    public RootGenericVisitor(ComponentWorkbench workbench, Element element, ElementType type) {
+        super(element);
+        this.workbench = workbench;
+        this.type = type;
+    }
+
+    /**
+     * Visit a 'simple' annotation attribute.
+     * This method is used for primitive arrays too.
+     * @param name : attribute name
+     * @param value : attribute value
+     * @see org.objectweb.asm.commons.EmptyVisitor#visit(String, Object)
+     */
+    public void visit(String name, Object value) {
+        super.visit(name, value);
+
+        if (name.equals("id")) {
+            m_id = value.toString();
+        } else if (name.equals("parent")) {
+            m_parent = value.toString();
+        }
+    }
+
+    /**
+     * End of the visit.
+     * All attribute were visited, we can update collectors data.
+     * @see org.objectweb.asm.commons.EmptyVisitor#visitEnd()
+     */
+    public void visitEnd() {
+
+        if (m_id != null) {
+            // An ID has been provided as annotation attribute
+            // Register our element under that ID
+            workbench.getIds().put(m_id, element);
+        } else {
+            // No ID provided, generate a new one from the element's namespace (aka handler's namespace)
+            m_id = element.getNameSpace();
+            if (!workbench.getIds().containsKey(m_id) && isClassType()) {
+                // No Elements were already registered under that namespace
+                workbench.getIds().put(m_id, element);
+            } else {
+                // ID already registered by another annotation
+                if (m_parent == null) {
+                    // If no parent specified, place this element under the 'class level' Element (default)
+                    m_parent = element.getNameSpace();
+                } // Otherwise, place this element under the specified Element (contribution)
+            }
+        }
+
+        workbench.getElements().put(element, m_parent);
+
+    }
+
+    private boolean isClassType() {
+        return ElementType.TYPE.equals(type);
+    }
+
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/generic/SubArrayVisitor.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/generic/SubArrayVisitor.java
new file mode 100644
index 0000000..e70727d
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/generic/SubArrayVisitor.java
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.generic;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.util.Elements;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.commons.EmptyVisitor;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class SubArrayVisitor extends EmptyVisitor implements AnnotationVisitor {
+
+    /**
+     * Parent element.
+     */
+    private Element m_elem;
+
+    /**
+     * Attribute name.
+     */
+    private String m_name;
+
+    /**
+     * Attribute value.
+     * (accumulator)
+     */
+    private String m_acc;
+
+    /**
+     * Constructor.
+     * @param elem : element element.
+     * @param name : attribute name.
+     */
+    public SubArrayVisitor(Element elem, String name) {
+        m_elem = elem;
+        m_name = name;
+    }
+
+    /**
+     * Visit a 'simple' element of the visited array.
+     * @param name : null
+     * @param value : element value.
+     * @see org.objectweb.asm.commons.EmptyVisitor#visit(String, Object)
+     */
+    public void visit(String name, Object value) {
+        if (m_acc == null) {
+            if (!(value instanceof Type)) {
+                m_acc = "{" + value.toString();
+            } else {
+                // Attributes of type class need a special handling
+                m_acc = "{" + ((Type) value).getClassName();
+            }
+        } else {
+            if (!(value instanceof Type)) {
+                m_acc = m_acc + "," + value.toString();
+            } else {
+                // Attributes of type class need a special handling
+                m_acc = m_acc + "," + ((Type) value).getClassName();
+            }
+        }
+    }
+
+    /**
+     * Visits an enumeration attribute.
+     * @param name the attribute name
+     * @param desc the enumeration descriptor
+     * @param value the attribute value
+     */
+    public void visitEnum(String name, String desc, String value) {
+        if (m_acc == null) {
+            m_acc = "{" + value;
+        } else {
+            m_acc = m_acc + "," + value;
+        }
+    }
+
+
+    /**
+     * Visit an annotation element of the visited array.
+     * @param name : null
+     * @param desc : annotation to visit
+     * @return the visitor which will visit the annotation
+     * @see org.objectweb.asm.commons.EmptyVisitor#visitAnnotation(String, String)
+     */
+    public AnnotationVisitor visitAnnotation(String name, String desc) {
+        // Sub annotations are map to sub-elements
+        Element elem = Elements.buildElement(Type.getType(desc));
+        m_elem.addElement(elem);
+        return new GenericVisitor(elem);
+    }
+
+    /**
+     * End of the visit.
+     * @see org.objectweb.asm.commons.EmptyVisitor#visitEnd()
+     */
+    public void visitEnd() {
+        if (m_acc != null) {
+            // We have analyzed an attribute
+            m_elem.addAttribute(new Attribute(m_name, m_acc + "}"));
+        }
+    }
+
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/generic/TypeGenericVisitor.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/generic/TypeGenericVisitor.java
new file mode 100644
index 0000000..9da0437
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/generic/TypeGenericVisitor.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.generic;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.ComponentWorkbench;
+import org.apache.felix.ipojo.metadata.Element;
+
+import java.lang.annotation.ElementType;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class TypeGenericVisitor extends RootGenericVisitor {
+    public TypeGenericVisitor(ComponentWorkbench workbench, Element element) {
+        super(workbench, element, ElementType.TYPE);
+    }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/util/Bindings.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/util/Bindings.java
new file mode 100644
index 0000000..877794a
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/util/Bindings.java
@@ -0,0 +1,165 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.util;
+
+import org.apache.felix.ipojo.manipulator.Reporter;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.registry.Binding;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.registry.BindingRegistry;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.generic.FieldGenericVisitor;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.generic.MethodGenericVisitor;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.generic.ParameterGenericVisitor;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.generic.TypeGenericVisitor;
+import org.apache.felix.ipojo.manipulator.spi.AnnotationVisitorFactory;
+import org.apache.felix.ipojo.manipulator.spi.BindingContext;
+import org.apache.felix.ipojo.manipulator.spi.Module;
+import org.apache.felix.ipojo.manipulator.spi.Predicate;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.tree.FieldNode;
+import org.objectweb.asm.tree.MethodNode;
+
+import java.lang.annotation.ElementType;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.ServiceLoader;
+import java.util.regex.Pattern;
+
+import static org.apache.felix.ipojo.manipulator.spi.helper.Predicates.and;
+import static org.apache.felix.ipojo.manipulator.spi.helper.Predicates.on;
+import static org.apache.felix.ipojo.manipulator.spi.helper.Predicates.pattern;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class Bindings {
+
+    private static List<Binding> DEFAULT_BINDINGS;
+    static {
+        DEFAULT_BINDINGS = new ArrayList<Binding>();
+        DEFAULT_BINDINGS.add(newGenericTypeBinding());
+        DEFAULT_BINDINGS.add(newGenericFieldBinding());
+        DEFAULT_BINDINGS.add(newGenericMethodBinding());
+        DEFAULT_BINDINGS.add(newGenericParameterBinding());
+        DEFAULT_BINDINGS = Collections.unmodifiableList(DEFAULT_BINDINGS);
+    }
+
+    private static Binding newGenericTypeBinding() {
+        Binding binding = new Binding();
+        // ElementType is TYPE
+        // Annotation descriptor is matching generic pattern
+        binding.setPredicate(
+                and(
+                        on(ElementType.TYPE),
+                        customAnnotationPattern()
+                ));
+        binding.setFactory(new AnnotationVisitorFactory() {
+            public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
+                Element element = Elements.buildElement(context.getAnnotationType());
+                return new TypeGenericVisitor(context.getWorkbench(), element);
+            }
+        });
+        return binding;
+    }
+
+    private static Predicate customAnnotationPattern() {
+        return pattern("(.*\\.ipojo\\..*)|(.*\\.handler\\..*)").matches();
+    }
+
+    private static Binding newGenericFieldBinding() {
+        Binding binding = new Binding();
+        // ElementType is FIELD
+        // Annotation descriptor is matching generic pattern
+        binding.setPredicate(
+                and(
+                        on(ElementType.FIELD),
+                        customAnnotationPattern()
+                ));
+        binding.setFactory(new AnnotationVisitorFactory() {
+            public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
+                Element element = Elements.buildElement(context.getAnnotationType());
+                return new FieldGenericVisitor(context.getWorkbench(), element, (FieldNode) context.getNode());
+            }
+        });
+        return binding;
+    }
+
+    private static Binding newGenericMethodBinding() {
+        Binding binding = new Binding();
+        // ElementType is METHOD
+        // Annotation descriptor is matching generic pattern
+        binding.setPredicate(
+                and(
+                        on(ElementType.METHOD),
+                        customAnnotationPattern()
+                ));
+        binding.setFactory(new AnnotationVisitorFactory() {
+            public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
+                Element element = Elements.buildElement(context.getAnnotationType());
+                return new MethodGenericVisitor(context.getWorkbench(), element, (MethodNode) context.getNode());
+            }
+        });
+        return binding;
+    }
+
+    private static Binding newGenericParameterBinding() {
+        Binding binding = new Binding();
+        // ElementType is METHOD
+        // Annotation descriptor is matching generic pattern
+        binding.setPredicate(
+                and(
+                        on(ElementType.PARAMETER),
+                        customAnnotationPattern()
+                ));
+        binding.setFactory(new AnnotationVisitorFactory() {
+            public AnnotationVisitor newAnnotationVisitor(BindingContext context) {
+                Element element = Elements.buildElement(context.getAnnotationType());
+                return new ParameterGenericVisitor(context.getWorkbench(), element, (MethodNode) context.getNode(), context.getParameterIndex());
+            }
+        });
+        return binding;
+    }
+
+
+    public static BindingRegistry newBindingRegistry(Reporter reporter) {
+
+        BindingRegistry registry = new BindingRegistry(reporter);
+        ServiceLoader<Module> loader = ServiceLoader.load(Module.class, classloader());
+
+        // Build each Module and add its contributed Bindings in the registry
+        for (Module module : loader) {
+            module.configure();
+            registry.addBindings(module);
+        }
+
+        // Do not forget the default Bindings
+        registry.getDefaultBindings().addAll(DEFAULT_BINDINGS);
+
+        return registry;
+    }
+
+    public static List<Binding> getDefaultBindings() {
+        return DEFAULT_BINDINGS;
+    }
+
+    private static ClassLoader classloader() {
+        return Bindings.class.getClassLoader();
+    }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/util/Elements.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/util/Elements.java
new file mode 100644
index 0000000..28439b6
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/util/Elements.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.util;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.ComponentWorkbench;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.Type;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class Elements {
+
+    /**
+     * Build the {@link Element} object from the given descriptor.
+     * It splits the annotation's classname in 2 parts (up to the last '.')
+     * first part (package's name) becomes the Element's namespace, and second
+     * part (class simple name) becomes the Element's name.
+     * @param type annotation descriptor
+     * @return the new element
+     */
+    public static Element buildElement(Type type) {
+        String name = type.getClassName();
+        int index = name.lastIndexOf('.');
+        String local = name.substring(index + 1);
+        String namespace = name.substring(0, index);
+        return new Element(local, namespace);
+    }
+
+    /**
+     * Return the Element named {@literal properties}, creates one if missing.
+     * @param workbench source for search
+     * @return the {@literal properties} Element (never null).
+     */
+    public static Element getPropertiesElement(ComponentWorkbench workbench) {
+        Element properties = workbench.getIds().get("properties");
+        if (properties == null) {
+            properties = new Element("properties", "");
+            workbench.getIds().put("properties", properties);
+            workbench.getElements().put(properties, null);
+        }
+        return properties;
+    }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/util/Names.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/util/Names.java
new file mode 100644
index 0000000..390ee43
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/util/Names.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.util;
+
+import org.apache.felix.ipojo.manipulation.MethodCreator;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class Names {
+
+    /**
+     * Computes the real method name. This method is useful when the annotation is collected on an manipulated method
+     * (prefixed by <code>__M_</code>). This method just removes the prefix if found.
+     * @param name the collected method name
+     * @return the effective method name, can be the collected method name if the method name does not start with
+     * the prefix.
+     */
+    public static String computeEffectiveMethodName(String name) {
+        if (name != null && name.startsWith(MethodCreator.PREFIX)) {
+            return name.substring(MethodCreator.PREFIX.length());
+        } else {
+            return name;
+        }
+    }
+
+    /**
+     * Extract an identifier from the given method name.
+     * It removes some pre-defined prefixes ({@literal bind}, {@literal unbind},
+     * {@literal set}, {@literal unset}, {@literal modified}).
+     * @param method method's name
+     * @return the method's identifier
+     */
+    public static String getMethodIdentifier(final String method) {
+
+        String effectiveName = computeEffectiveMethodName(method);
+
+        if (effectiveName.startsWith("bind")) {
+            return effectiveName.substring("bind".length());
+        }
+
+        if (effectiveName.startsWith("set")) {
+            return effectiveName.substring("set".length());
+        }
+
+        if (effectiveName.startsWith("unbind")) {
+            return effectiveName.substring("unbind".length());
+        }
+
+        if (effectiveName.startsWith("unset")) {
+            return effectiveName.substring("unset".length());
+        }
+
+        if (effectiveName.startsWith("modified")) {
+            return effectiveName.substring("modified".length());
+        }
+
+        return null;
+
+    }
+
+    /**
+     * Check if the given annotation descriptor is an iPOJO custom annotation.
+     * A valid iPOJO custom annotation must contains 'ipojo' or 'handler' in its qualified name.
+     * @param desc annotation descriptor
+     * @return {@literal true} if the given descriptor is an iPOJO custom annotation
+     */
+    public static boolean isCustomAnnotation(final String desc) {
+        String lowerCase = desc.toLowerCase();
+        return lowerCase.contains("ipojo") || lowerCase.contains("handler");
+    }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/AbsBindingModule.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/AbsBindingModule.java
new file mode 100644
index 0000000..d4317be
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/AbsBindingModule.java
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.spi;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.registry.Binding;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+
+import static org.apache.felix.ipojo.manipulator.spi.helper.Predicates.alwaysTrue;
+import static org.apache.felix.ipojo.manipulator.spi.helper.Predicates.on;
+import static org.apache.felix.ipojo.manipulator.spi.helper.Predicates.onlySupportedElements;
+import static org.apache.felix.ipojo.manipulator.spi.helper.Predicates.or;
+
+/**
+ * All provided {@link Module}s have to inherit from this class.
+ * It provides a simple to use DSL to express annotation bindings.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public abstract class AbsBindingModule implements Module {
+
+    /**
+     * Build dindings.
+     */
+    private List<Binding> bindings = new ArrayList<Binding>();
+
+    public Iterator<Binding> iterator() {
+        return bindings.iterator();
+    }
+
+    /**
+     * Initiate an annotation binding.
+     * Examples:
+     * <pre>
+     *     AnnotationVisitorFactory factory = new CompositeVisitorFactory();
+     *     bind(Composite.class).to(factory);
+     *     bind(Composite.class).when(.. some condition ..)
+     *                          .to(factory);
+     * </pre>
+     * @param annotationType the annotation that will be bound to the {@link AnnotationVisitorFactory}
+     */
+    protected AnnotationBindingBuilder bind(Class<? extends Annotation> annotationType) {
+        return new AnnotationBindingBuilder(bindings, annotationType);
+    }
+
+    /**
+     * DSL helper class.
+     */
+    public class AnnotationBindingBuilder {
+        private Class<? extends Annotation> annotationType;
+        private AnnotationVisitorFactory factory;
+        private List<Binding> registry;
+
+        public AnnotationBindingBuilder(List<Binding> registry,
+                                        Class<? extends Annotation> annotationType) {
+            this.registry = registry;
+            this.annotationType = annotationType;
+        }
+
+        /**
+         * Declares a {@link Predicate} that will add a condition to the annotation binding.
+         * @see org.apache.felix.ipojo.manipulator.spi.helper.Predicates
+         * @param predicate the predicate to use
+         */
+        public ConditionalBindingBuilder when(Predicate predicate) {
+            return new ConditionalBindingBuilder(this, predicate);
+        }
+
+        /**
+         * Complete the annotation binding with the {@link AnnotationVisitorFactory} to be executed
+         * when the annotation is found.
+         * @param factory to be executed when the annotation is found.
+         */
+        public void to(AnnotationVisitorFactory factory) {
+            this.factory = factory;
+            registry.add(build());
+        }
+
+        /**
+         * Creates the Binding.
+         */
+        private Binding build() {
+            Binding binding = new Binding();
+            binding.setAnnotationType(annotationType);
+            binding.setPredicate(onlySupportedElements(annotationType));
+            binding.setFactory(factory);
+            return binding;
+        }
+
+    }
+
+    public class ConditionalBindingBuilder {
+        private AnnotationBindingBuilder parent;
+        private Predicate predicate;
+        private AnnotationVisitorFactory factory;
+
+        public ConditionalBindingBuilder(AnnotationBindingBuilder parent, Predicate predicate) {
+            this.parent = parent;
+            this.predicate = predicate;
+        }
+
+        /**
+         * Complete the annotation binding with the {@link AnnotationVisitorFactory} to be executed
+         * when the annotation is found.
+         * @param factory to be executed when the annotation is found.
+         */
+        public AnnotationBindingBuilder to(AnnotationVisitorFactory factory) {
+            this.factory = factory;
+            bindings.add(build());
+
+            return parent;
+        }
+
+        /**
+         * Creates the Binding.
+         */
+        private Binding build() {
+            Binding binding = parent.build();
+            binding.setPredicate(predicate);
+            binding.setFactory(factory);
+            return binding;
+        }
+    }
+
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/AnnotationVisitorFactory.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/AnnotationVisitorFactory.java
new file mode 100644
index 0000000..b29d3cc
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/AnnotationVisitorFactory.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.spi;
+
+import org.objectweb.asm.AnnotationVisitor;
+
+/**
+ * Produces a new {@link AnnotationVisitor} instance for the given {@link BindingContext}.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface AnnotationVisitorFactory {
+
+    /**
+     * May return {@literal null} if no visitor can be created.
+     */
+    AnnotationVisitor newAnnotationVisitor(BindingContext context);
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/BindingContext.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/BindingContext.java
new file mode 100644
index 0000000..14129bf
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/BindingContext.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.spi;
+
+import org.apache.felix.ipojo.manipulator.Reporter;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.ComponentWorkbench;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.MemberNode;
+
+import java.lang.annotation.ElementType;
+
+/**
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class BindingContext {
+
+    /**
+     *
+     */
+    private ComponentWorkbench workbench;
+    private MemberNode node;
+    private ElementType elementType;
+    private int parameterIndex;
+    private Reporter reporter;
+    private Type annotationType;
+
+    public BindingContext(final ComponentWorkbench workbench,
+                          final Reporter reporter,
+                          final Type annotationType,
+                          final MemberNode node,
+                          final ElementType elementType,
+                          final int parameterIndex) {
+        this.workbench = workbench;
+        this.reporter = reporter;
+        this.annotationType = annotationType;
+        this.node = node;
+        this.elementType = elementType;
+        this.parameterIndex = parameterIndex;
+    }
+
+    public ComponentWorkbench getWorkbench() {
+        return workbench;
+    }
+
+    public MemberNode getNode() {
+        return node;
+    }
+
+    public ElementType getElementType() {
+        return elementType;
+    }
+
+    public int getParameterIndex() {
+        return parameterIndex;
+    }
+
+    public Reporter getReporter() {
+        return reporter;
+    }
+
+    public Type getAnnotationType() {
+        return annotationType;
+    }
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/Module.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/Module.java
new file mode 100644
index 0000000..e5f4b5c
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/Module.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.spi;
+
+import org.apache.felix.ipojo.manipulator.metadata.annotation.registry.Binding;
+
+/**
+ * A Module is the contributions from third party to the iPOJO manipulation process.
+ * It is dedicated to Annotation binding support (executing a given ASM AnnotationVisitor
+ * when a particular annotation is found).
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface Module extends Iterable<Binding> {
+
+    /**
+     * Configure the bindings provided by this module.
+     */
+    void configure();
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/Predicate.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/Predicate.java
new file mode 100644
index 0000000..cee734b
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/Predicate.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.spi;
+
+/**
+ * A Predicate is executed with a given {@link BindingContext} and returns {@literal true} if the
+ * {@link #matches(BindingContext)} operation is a success. It returns {@literal false} otherwise.
+ * Predicates can be used to determine if the traversed element (can be found on {@link BindingContext})
+ * matches some properties.
+ *
+ * @see org.apache.felix.ipojo.manipulator.spi.helper.Predicates
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface Predicate {
+
+    /**
+     * Returns {@literal true} if the context is matching the predicate.
+     * @param context Binding information source
+     * @return {@literal true} if the context is matching the predicate, {@literal false} otherwise.
+     */
+    boolean matches(BindingContext context);
+}
diff --git a/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/helper/Predicates.java b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/helper/Predicates.java
new file mode 100644
index 0000000..ddc4022
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/helper/Predicates.java
@@ -0,0 +1,224 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.spi.helper;
+
+import org.apache.felix.ipojo.manipulator.spi.BindingContext;
+import org.apache.felix.ipojo.manipulator.spi.Predicate;
+import org.objectweb.asm.tree.ClassNode;
+import org.objectweb.asm.tree.FieldNode;
+import org.objectweb.asm.tree.MethodNode;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.regex.Pattern;
+
+/**
+ * Ready-to-use {@link Predicate} implementations.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class Predicates {
+    public static Node node() {
+        return new Node();
+    }
+
+    public static Reference reference(String refId) {
+        return new Reference(refId);
+    }
+
+    public static Matcher pattern(String regex) {
+        return new Matcher(regex);
+    }
+
+    /**
+     * Restrict to the given {@link ElementType}.
+     * @param type expected {@link ElementType}
+     */
+    public static Predicate on(final ElementType type) {
+        return new Predicate() {
+            public boolean matches(BindingContext context) {
+                return context.getElementType().equals(type);
+            }
+        };
+    }
+
+    /**
+     * Always return {@literal true}.
+     */
+    public static Predicate alwaysTrue() {
+        return new Predicate() {
+            public boolean matches(BindingContext context) {
+                return true;
+            }
+        };
+    }
+
+    /**
+     * Successful if all given predicates are satisfied.
+     * @param predicates predicates to be satisfied
+     */
+    public static Predicate and(final Predicate... predicates) {
+
+        // Optimization
+        if (predicates.length == 1) {
+            return predicates[0];
+        }
+
+        return new Predicate() {
+            public boolean matches(BindingContext context) {
+
+                for (Predicate predicate : predicates) {
+                    // Quit with first failure
+                    if (!predicate.matches(context)) {
+                        return false;
+                    }
+                }
+                return true;
+            }
+        };
+    }
+
+    /**
+     * Successful if at least one of the given predicates is satisfied.
+     * @param predicates predicates to be satisfied (at least one)
+     */
+    public static Predicate or(final Collection<Predicate> predicates) {
+
+        // Optimization
+        if (predicates.size() == 1) {
+            return predicates.iterator().next();
+        }
+
+        return new Predicate() {
+            public boolean matches(BindingContext context) {
+
+                for (Predicate predicate : predicates) {
+                    // Quit with first success
+                    if (predicate.matches(context)) {
+                        return true;
+                    }
+                }
+                // No predicate were matching
+                return false;
+            }
+        };
+    }
+
+    /**
+     * Successful if at least one of the given predicates is satisfied.
+     * @param predicates predicates to be satisfied (at least one)
+     */
+    public static Predicate or(final Predicate... predicates) {
+        return or(Arrays.asList(predicates));
+    }
+
+    /**
+     * Restrict to the supported {@link ElementType}(s) of the annotation (use the @Target, if provided).
+     * @param annotationType annotation to explore
+     */
+    public static Predicate onlySupportedElements(final Class<? extends Annotation> annotationType) {
+        Target target = annotationType.getAnnotation(Target.class);
+        if (target == null) {
+            return alwaysTrue();
+        }
+
+        Collection<Predicate> supportedTypes = new HashSet<Predicate>();
+        for (ElementType type : target.value()) {
+            supportedTypes.add(on(type));
+        }
+
+        return or(supportedTypes);
+    }
+
+    public static class Reference {
+
+        private String refId;
+
+        public Reference(String refId) {
+            this.refId = refId;
+        }
+
+        /**
+         * Restrict execution if the {@link org.apache.felix.ipojo.manipulator.metadata.annotation.ComponentWorkbench}
+         * contains the given reference's name.
+         */
+        public Predicate exists() {
+            return new Predicate() {
+                public boolean matches(BindingContext context) {
+                    return context.getWorkbench().getIds().containsKey(refId);
+                }
+            };
+        }
+    }
+
+    public static class Matcher {
+
+        private Pattern pattern;
+
+        public Matcher(String regex) {
+            pattern = Pattern.compile(regex);
+        }
+
+        /**
+         * Restrict execution if the annotation's classname matches the given pattern.
+         */
+        public Predicate matches() {
+            return new Predicate() {
+                public boolean matches(BindingContext context) {
+                    return pattern.matcher(context.getAnnotationType().getClassName()).matches();
+                }
+            };
+        }
+    }
+
+    public static class Node {
+        /**
+         * Restrict execution if the supported {@literal Node} has the given name.
+         */
+        public Predicate named(final String expected) {
+            return new Predicate() {
+                public boolean matches(BindingContext context) {
+                    if (context.getNode() instanceof FieldNode) {
+                        FieldNode field = (FieldNode) context.getNode();
+                        return field.name.equals(expected);
+                    }
+
+                    if (context.getNode() instanceof MethodNode) {
+                        MethodNode method = (MethodNode) context.getNode();
+                        return method.name.equals(expected);
+                    }
+
+                    if (context.getNode() instanceof ClassNode) {
+                        ClassNode clazz = (ClassNode) context.getNode();
+                        return clazz.name.equals(expected);
+                    }
+
+                    // Parameters have no name in bytecode
+
+                    return false;
+                }
+            };
+        }
+    }
+
+}
diff --git a/ipojo/manipulator/manipulator/src/main/resources/META-INF/services/org.apache.felix.ipojo.manipulator.spi.Module b/ipojo/manipulator/manipulator/src/main/resources/META-INF/services/org.apache.felix.ipojo.manipulator.spi.Module
new file mode 100644
index 0000000..d3b15f9
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/main/resources/META-INF/services/org.apache.felix.ipojo.manipulator.spi.Module
@@ -0,0 +1 @@
+org.apache.felix.ipojo.manipulator.metadata.annotation.module.DefaultBindingModule
\ No newline at end of file
diff --git a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/ComponentWorkbenchTestCase.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/ComponentWorkbenchTestCase.java
new file mode 100644
index 0000000..b8afe16
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/ComponentWorkbenchTestCase.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation;
+
+import junit.framework.TestCase;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.tree.ClassNode;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: guillaume
+ * Date: 10/12/12
+ * Time: 11:17 AM
+ * To change this template use File | Settings | File Templates.
+ */
+public class ComponentWorkbenchTestCase extends TestCase {
+    public void testBuildWithNoTopLevelElements() throws Exception {
+
+        ComponentWorkbench workbench = new ComponentWorkbench(null, node());
+        Element built = workbench.build();
+        assertNull(built);
+
+    }
+
+    public void testSimpleBuild() throws Exception {
+
+        Element root = new Element("root", null);
+
+        ComponentWorkbench workbench = new ComponentWorkbench(null, node());
+        workbench.setRoot(root);
+        Element built = workbench.build();
+
+        assertEquals("root", built.getName());
+        assertNull(built.getNameSpace());
+        assertEquals(0, built.getAttributes().length);
+        assertEquals(0, built.getElements().length);
+
+    }
+
+    public void testElementsAreHierarchicallyPlaced() throws Exception {
+
+        Element root = new Element("root", null);
+        Element child = new Element("child", null);
+
+        ComponentWorkbench workbench = new ComponentWorkbench(null, node());
+        workbench.setRoot(root);
+        workbench.getElements().put(child, null);
+
+        Element built = workbench.build();
+
+        assertEquals("root", built.getName());
+        assertNull(built.getNameSpace());
+        assertEquals(0, built.getAttributes().length);
+        assertEquals(1, built.getElements().length);
+
+        Element builtChild = built.getElements("child")[0];
+
+        assertEquals("child", builtChild.getName());
+        assertNull(builtChild.getNameSpace());
+        assertEquals(0, builtChild.getAttributes().length);
+        assertEquals(0, builtChild.getElements().length);
+
+
+    }
+
+
+    private static ClassNode node() {
+        ClassNode node = new ClassNode();
+        node.name = "my/Component";
+        return node;
+    }
+
+}
diff --git a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/BindingRegistryTestCase.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/BindingRegistryTestCase.java
new file mode 100644
index 0000000..7c1bbf4
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/BindingRegistryTestCase.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.registry;
+
+import junit.framework.TestCase;
+import org.apache.felix.ipojo.annotations.Provides;
+import org.apache.felix.ipojo.manipulator.Reporter;
+import org.apache.felix.ipojo.manipulator.spi.AnnotationVisitorFactory;
+import org.apache.felix.ipojo.manipulator.spi.Predicate;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.objectweb.asm.Type;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: guillaume
+ * Date: 10/11/12
+ * Time: 10:31 AM
+ * To change this template use File | Settings | File Templates.
+ */
+public class BindingRegistryTestCase extends TestCase {
+
+    private BindingRegistry registry;
+
+    @Mock
+    private Reporter reporter;
+    @Mock
+    private AnnotationVisitorFactory factory;
+    @Mock
+    private Predicate predicate;
+
+    @Override
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        registry = new BindingRegistry(reporter);
+    }
+
+    public void testBindingAddition() throws Exception {
+        registry.addBindings(Collections.singletonList(binding()));
+
+        List<Binding> predicates = registry.getBindings(Type.getType(Provides.class).getDescriptor());
+
+        assertEquals(1, predicates.size());
+        Binding found = predicates.get(0);
+        assertNotNull(found);
+        assertEquals(predicate, found.getPredicate());
+        assertEquals(factory, found.getFactory());
+    }
+
+    public void testGetBindingsWhenEmpty() throws Exception {
+        assertNull(registry.getBindings(Type.getType(Provides.class).getDescriptor()));
+        assertNotNull(registry.selection(null));
+    }
+
+    private Binding binding() {
+        Binding binding = new Binding();
+        binding.setAnnotationType(Provides.class);
+        binding.setFactory(factory);
+        binding.setPredicate(predicate);
+        return binding;
+    }
+}
diff --git a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/SelectionTestCase.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/SelectionTestCase.java
new file mode 100644
index 0000000..5055ed0
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/SelectionTestCase.java
@@ -0,0 +1,252 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.registry;
+
+import junit.framework.TestCase;
+import org.apache.felix.ipojo.manipulator.Reporter;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.generic.FieldGenericVisitor;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.generic.MethodGenericVisitor;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.generic.ParameterGenericVisitor;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.generic.TypeGenericVisitor;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.visitor.util.Bindings;
+import org.apache.felix.ipojo.manipulator.spi.AbsBindingModule;
+import org.apache.felix.ipojo.manipulator.spi.AnnotationVisitorFactory;
+import org.apache.felix.ipojo.manipulator.spi.BindingContext;
+import org.hamcrest.Matcher;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.ClassNode;
+import org.objectweb.asm.tree.FieldNode;
+import org.objectweb.asm.tree.MethodNode;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.when;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: guillaume
+ * Date: 10/11/12
+ * Time: 10:49 AM
+ * To change this template use File | Settings | File Templates.
+ */
+public class SelectionTestCase extends TestCase {
+    private BindingRegistry registry;
+
+    @Mock
+    private Reporter reporter;
+    @Mock
+    private AnnotationVisitorFactory factory;
+    @Mock
+    private AnnotationVisitor visitor;
+
+    @Override
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        registry = new BindingRegistry(reporter);
+        when(factory.newAnnotationVisitor(any(BindingContext.class)))
+                .thenReturn(visitor);
+    }
+
+    public void testSelectionOnClassNodeOnly() throws Exception {
+
+        AbsBindingModule module = new MonoBindingModule(OnTypeOnly.class);
+        module.configure();
+        registry.addBindings(module);
+
+        // Verifications
+        assertClassSelection(OnTypeOnly.class, equalTo(visitor));
+        assertFieldSelection(OnTypeOnly.class, nullValue());
+        assertMethodSelection(OnTypeOnly.class, nullValue());
+        assertParameterSelection(OnTypeOnly.class, nullValue());
+    }
+
+    public void testSelectionOnFieldNodeOnly() throws Exception {
+
+        AbsBindingModule module = new MonoBindingModule(OnFieldOnly.class);
+        module.configure();
+        registry.addBindings(module);
+
+        // Verifications
+        assertClassSelection(OnFieldOnly.class, nullValue());
+        assertFieldSelection(OnFieldOnly.class, equalTo(visitor));
+        assertMethodSelection(OnFieldOnly.class, nullValue());
+        assertParameterSelection(OnFieldOnly.class, nullValue());
+
+    }
+
+    public void testSelectionOnMethodNodeOnly() throws Exception {
+
+        AbsBindingModule module = new MonoBindingModule(OnMethodOnly.class);
+        module.configure();
+        registry.addBindings(module);
+
+        // Verifications
+        assertClassSelection(OnMethodOnly.class, nullValue());
+        assertFieldSelection(OnMethodOnly.class, nullValue());
+        assertMethodSelection(OnMethodOnly.class, equalTo(visitor));
+        assertParameterSelection(OnMethodOnly.class, nullValue());
+
+    }
+
+    public void testSelectionOnMethodParameterOnly() throws Exception {
+
+        AbsBindingModule module = new MonoBindingModule(OnParameterOnly.class);
+        module.configure();
+        registry.addBindings(module);
+
+        // Verifications
+        assertClassSelection(OnParameterOnly.class, nullValue());
+        assertFieldSelection(OnParameterOnly.class, nullValue());
+        assertMethodSelection(OnParameterOnly.class, nullValue());
+        assertParameterSelection(OnParameterOnly.class, equalTo(visitor));
+
+    }
+
+    public void testSelectionOBothMethodAndParameter() throws Exception {
+
+        AbsBindingModule module = new MonoBindingModule(OnBothMethodAndParameter.class);
+        module.configure();
+        registry.addBindings(module);
+
+        // Verifications
+        assertClassSelection(OnBothMethodAndParameter.class, nullValue());
+        assertFieldSelection(OnBothMethodAndParameter.class, nullValue());
+        assertMethodSelection(OnBothMethodAndParameter.class, equalTo(visitor));
+        assertParameterSelection(OnBothMethodAndParameter.class, equalTo(visitor));
+
+    }
+
+    public void testSelectionForGenericVisitors() throws Exception {
+
+        assertClassSelection(OnTypeOnly.class, nullValue());
+        assertFieldSelection(OnFieldOnly.class, nullValue());
+        assertMethodSelection(OnMethodOnly.class, nullValue());
+        assertParameterSelection(OnParameterOnly.class, nullValue());
+
+        registry.getDefaultBindings().addAll(Bindings.getDefaultBindings());
+
+        // Verifications
+        assertClassSelection(OnTypeOnly.class, instanceOf(TypeGenericVisitor.class));
+        assertFieldSelection(OnFieldOnly.class, instanceOf(FieldGenericVisitor.class));
+        assertMethodSelection(OnMethodOnly.class, instanceOf(MethodGenericVisitor.class));
+        assertParameterSelection(OnParameterOnly.class, instanceOf(ParameterGenericVisitor.class));
+
+    }
+
+    private void assertClassSelection(Class<? extends Annotation> type, Matcher matcher) {
+        Selection selection = new Selection(registry, null, reporter);
+        selection.type(classNode());
+        selection.annotatedWith(descriptor(type));
+
+        assertTrue(matcher.matches(selection.get()));
+    }
+
+    private void assertFieldSelection(Class<? extends Annotation> type, Matcher matcher) {
+        Selection selection = new Selection(registry, null, reporter);
+        selection.field(fieldNode());
+        selection.annotatedWith(descriptor(type));
+
+        assertTrue(matcher.matches(selection.get()));
+    }
+
+    private void assertMethodSelection(Class<? extends Annotation> type, Matcher matcher) {
+        Selection selection = new Selection(registry, null, reporter);
+        selection.method(methodNode());
+        selection.annotatedWith(descriptor(type));
+
+        assertTrue(matcher.matches(selection.get()));
+    }
+
+    private void assertParameterSelection(Class<? extends Annotation> type, Matcher matcher) {
+        Selection selection = new Selection(registry, null, reporter);
+        selection.parameter(methodNode(), 0);
+        selection.annotatedWith(descriptor(type));
+
+        assertTrue(matcher.matches(selection.get()));
+    }
+
+    private MethodNode methodNode() {
+        return new MethodNode(0, "method", "(java/lang/String)V", null, null);
+    }
+
+    private ClassNode classNode() {
+        ClassNode node = new ClassNode();
+        node.visit(0, 0, "my/Component", null, "java/lang/Object", null);
+        return node;
+    }
+
+    public void testSelectionWithEmptyRegistry() throws Exception {
+        Selection selection = new Selection(registry, null, reporter);
+
+        selection.field(fieldNode())
+                .annotatedWith(descriptor(OnTypeOnly.class));
+
+        assertNull(selection.get());
+    }
+
+    private String descriptor(Class<? extends Annotation> type) {
+        return Type.getType(type).getDescriptor();
+    }
+
+    private FieldNode fieldNode() {
+        return new FieldNode(0,
+                             "field",
+                             Type.getType(Object.class).getDescriptor(),
+                             null,
+                             null);
+    }
+
+    @Target(ElementType.TYPE)
+    private @interface OnTypeOnly {}
+
+    @Target(ElementType.FIELD)
+    private @interface OnFieldOnly {}
+
+    @Target(ElementType.METHOD)
+    private @interface OnMethodOnly {}
+
+    @Target(ElementType.PARAMETER)
+    private @interface OnParameterOnly {}
+
+    @Target({ElementType.PARAMETER, ElementType.METHOD})
+    private @interface OnBothMethodAndParameter {}
+
+
+    private class MonoBindingModule extends AbsBindingModule {
+        private Class<? extends Annotation> type;
+
+        public MonoBindingModule(Class<? extends Annotation> aClass) {
+            this.type = aClass;
+        }
+
+        public void configure() {
+            bind(type).to(factory);
+        }
+    }
+}
diff --git a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/ComponentVisitorTestCase.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/ComponentVisitorTestCase.java
new file mode 100644
index 0000000..c3f5914
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/ComponentVisitorTestCase.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.manipulator.metadata.annotation.visitor;
+
+import junit.framework.TestCase;
+import org.apache.felix.ipojo.manipulator.Reporter;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.ComponentWorkbench;
+import org.apache.felix.ipojo.metadata.Element;
+import org.objectweb.asm.tree.ClassNode;
+
+import static org.mockito.Mockito.mock;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: guillaume
+ * Date: 10/10/12
+ * Time: 5:46 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class ComponentVisitorTestCase extends TestCase {
+
+    public void testDefaultNameIsClassname() throws Exception {
+        Reporter reporter = mock(Reporter.class);
+        ComponentWorkbench workbench = new ComponentWorkbench(null, clazz());
+        ComponentVisitor visitor = new ComponentVisitor(workbench, reporter);
+        visitor.visitEnd();
+
+        Element root = workbench.getRoot();
+        assertNotNull(root);
+        assertEquals("my.Component", root.getAttribute("name"));
+    }
+
+    public void testNameAttribute() throws Exception {
+        Reporter reporter = mock(Reporter.class);
+        ComponentWorkbench workbench = new ComponentWorkbench(null, clazz());
+        ComponentVisitor visitor = new ComponentVisitor(workbench, reporter);
+        visitor.visit("name", "changed");
+        visitor.visitEnd();
+
+        Element root = workbench.getRoot();
+        assertNotNull(root);
+        assertEquals("changed", root.getAttribute("name"));
+    }
+
+    public void testPublicFactoryDeprecationSupport() throws Exception {
+        Reporter reporter = mock(Reporter.class);
+        ComponentWorkbench workbench = new ComponentWorkbench(null, clazz());
+        ComponentVisitor visitor = new ComponentVisitor(workbench, reporter);
+        visitor.visit("public_factory", "false");
+        visitor.visitEnd();
+
+        Element root = workbench.getRoot();
+        assertNotNull(root);
+        assertEquals("false", root.getAttribute("public"));
+    }
+
+    public void testFactoryMethodDeprecationSupport() throws Exception {
+        Reporter reporter = mock(Reporter.class);
+        ComponentWorkbench workbench = new ComponentWorkbench(null, clazz());
+        ComponentVisitor visitor = new ComponentVisitor(workbench, reporter);
+        visitor.visit("factory_method", "create");
+        visitor.visitEnd();
+
+        Element root = workbench.getRoot();
+        assertNotNull(root);
+        assertEquals("create", root.getAttribute("factory-method"));
+    }
+
+    private ClassNode clazz() {
+        ClassNode node = new ClassNode();
+        node.name = "my/Component";
+        return node;
+    }
+}
diff --git a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/spi/AbsBindingModuleTestCase.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/spi/AbsBindingModuleTestCase.java
new file mode 100644
index 0000000..c1bb23e
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/spi/AbsBindingModuleTestCase.java
@@ -0,0 +1,139 @@
+package org.apache.felix.ipojo.manipulator.spi;
+
+import junit.framework.TestCase;
+import org.apache.felix.ipojo.annotations.Provides;
+import org.apache.felix.ipojo.annotations.Requires;
+import org.apache.felix.ipojo.manipulator.metadata.annotation.registry.Binding;
+
+import java.lang.annotation.ElementType;
+import java.util.Iterator;
+
+import static org.apache.felix.ipojo.manipulator.spi.helper.Predicates.on;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.only;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: guillaume
+ * Date: 10/10/12
+ * Time: 10:37 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class AbsBindingModuleTestCase extends TestCase {
+
+    public void testSimpleBinding() throws Exception {
+        final AnnotationVisitorFactory factory = mock(AnnotationVisitorFactory.class);
+        AbsBindingModule module = new AbsBindingModule() {
+            public void configure() {
+                bind(Provides.class).to(factory);
+            }
+        };
+        module.configure();
+
+        Iterator<Binding> i = module.iterator();
+        Binding one = i.next();
+        assertNotNull(one);
+        assertEquals(Provides.class, one.getAnnotationType());
+        assertEquals(factory, one.getFactory());
+
+        // Only 1 Binding
+        assertFalse(i.hasNext());
+    }
+
+    public void testTwoBindings() throws Exception {
+        final AnnotationVisitorFactory factory = mock(AnnotationVisitorFactory.class);
+        AbsBindingModule module = new AbsBindingModule() {
+            public void configure() {
+                bind(Provides.class).to(factory);
+                bind(Requires.class).to(factory);
+            }
+        };
+        module.configure();
+
+        Iterator<Binding> i = module.iterator();
+        Binding one = i.next();
+        assertNotNull(one);
+        assertEquals(Provides.class, one.getAnnotationType());
+        assertEquals(factory, one.getFactory());
+
+        // Second Binding
+        Binding two = i.next();
+        assertNotNull(two);
+        assertEquals(Requires.class, two.getAnnotationType());
+        assertEquals(factory, two.getFactory());
+    }
+
+    public void testTwoBindingsForSameAnnotation() throws Exception {
+        final AnnotationVisitorFactory factory = mock(AnnotationVisitorFactory.class);
+        final AnnotationVisitorFactory factory2 = mock(AnnotationVisitorFactory.class);
+        AbsBindingModule module = new AbsBindingModule() {
+            public void configure() {
+                bind(Provides.class).to(factory);
+                bind(Provides.class).to(factory2);
+            }
+        };
+        module.configure();
+
+        Iterator<Binding> i = module.iterator();
+        Binding one = i.next();
+        assertNotNull(one);
+        assertEquals(Provides.class, one.getAnnotationType());
+        assertEquals(factory, one.getFactory());
+
+        // Second Binding
+        Binding two = i.next();
+        assertNotNull(two);
+        assertEquals(Provides.class, two.getAnnotationType());
+        assertEquals(factory2, two.getFactory());
+    }
+
+    public void testConditionalBinding() throws Exception {
+        final AnnotationVisitorFactory factory = mock(AnnotationVisitorFactory.class);
+        AbsBindingModule module = new AbsBindingModule() {
+            public void configure() {
+                bind(Provides.class)
+                        .when(on(ElementType.FIELD))
+                        .to(factory);
+            }
+        };
+        module.configure();
+
+        Iterator<Binding> i = module.iterator();
+        Binding one = i.next();
+        assertNotNull(one);
+        assertEquals(Provides.class, one.getAnnotationType());
+        assertEquals(factory, one.getFactory());
+
+        // Only 1 Binding
+        assertFalse(i.hasNext());
+    }
+
+    public void testConditionalBindings() throws Exception {
+        final AnnotationVisitorFactory factory = mock(AnnotationVisitorFactory.class);
+        final AnnotationVisitorFactory factory2 = mock(AnnotationVisitorFactory.class);
+        AbsBindingModule module = new AbsBindingModule() {
+            public void configure() {
+                bind(Provides.class)
+                        .when(on(ElementType.FIELD))
+                        .to(factory)
+                .when(on(ElementType.PARAMETER))
+                .to(factory2);
+            }
+        };
+        module.configure();
+
+        Iterator<Binding> i = module.iterator();
+        Binding one = i.next();
+        assertNotNull(one);
+        assertEquals(Provides.class, one.getAnnotationType());
+        assertEquals(factory, one.getFactory());
+
+        // Second Binding
+        Binding two = i.next();
+        assertNotNull(two);
+        assertEquals(Provides.class, two.getAnnotationType());
+        assertEquals(factory2, two.getFactory());
+    }
+
+
+}