Added: felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/AbsBindingModule.java URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/AbsBindingModule.java?rev=1407407&view=auto ============================================================================== --- felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/AbsBindingModule.java (added) +++ felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/AbsBindingModule.java Fri Nov 9 10:05:42 2012 @@ -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:[email protected]">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; + } + } + +}
Added: felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/AnnotationVisitorFactory.java URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/AnnotationVisitorFactory.java?rev=1407407&view=auto ============================================================================== --- felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/AnnotationVisitorFactory.java (added) +++ felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/AnnotationVisitorFactory.java Fri Nov 9 10:05:42 2012 @@ -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:[email protected]">Felix Project Team</a> + */ +public interface AnnotationVisitorFactory { + + /** + * May return {@literal null} if no visitor can be created. + */ + AnnotationVisitor newAnnotationVisitor(BindingContext context); +} Added: felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/BindingContext.java URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/BindingContext.java?rev=1407407&view=auto ============================================================================== --- felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/BindingContext.java (added) +++ felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/BindingContext.java Fri Nov 9 10:05:42 2012 @@ -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:[email protected]">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; + } +} Added: felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/Module.java URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/Module.java?rev=1407407&view=auto ============================================================================== --- felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/Module.java (added) +++ felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/Module.java Fri Nov 9 10:05:42 2012 @@ -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:[email protected]">Felix Project Team</a> + */ +public interface Module extends Iterable<Binding> { + + /** + * Configure the bindings provided by this module. + */ + void configure(); +} Added: felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/Predicate.java URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/Predicate.java?rev=1407407&view=auto ============================================================================== --- felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/Predicate.java (added) +++ felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/Predicate.java Fri Nov 9 10:05:42 2012 @@ -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:[email protected]">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); +} Added: felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/helper/Predicates.java URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/helper/Predicates.java?rev=1407407&view=auto ============================================================================== --- felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/helper/Predicates.java (added) +++ felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/spi/helper/Predicates.java Fri Nov 9 10:05:42 2012 @@ -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:[email protected]">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; + } + }; + } + } + +} Added: felix/trunk/ipojo/manipulator/manipulator/src/main/resources/META-INF/services/org.apache.felix.ipojo.manipulator.spi.Module URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/manipulator/src/main/resources/META-INF/services/org.apache.felix.ipojo.manipulator.spi.Module?rev=1407407&view=auto ============================================================================== --- felix/trunk/ipojo/manipulator/manipulator/src/main/resources/META-INF/services/org.apache.felix.ipojo.manipulator.spi.Module (added) +++ felix/trunk/ipojo/manipulator/manipulator/src/main/resources/META-INF/services/org.apache.felix.ipojo.manipulator.spi.Module Fri Nov 9 10:05:42 2012 @@ -0,0 +1 @@ +org.apache.felix.ipojo.manipulator.metadata.annotation.module.DefaultBindingModule \ No newline at end of file Added: felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/ComponentWorkbenchTestCase.java URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/ComponentWorkbenchTestCase.java?rev=1407407&view=auto ============================================================================== --- felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/ComponentWorkbenchTestCase.java (added) +++ felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/ComponentWorkbenchTestCase.java Fri Nov 9 10:05:42 2012 @@ -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; + } + +} Added: felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/BindingRegistryTestCase.java URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/BindingRegistryTestCase.java?rev=1407407&view=auto ============================================================================== --- felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/BindingRegistryTestCase.java (added) +++ felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/BindingRegistryTestCase.java Fri Nov 9 10:05:42 2012 @@ -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; + } +} Added: felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/SelectionTestCase.java URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/SelectionTestCase.java?rev=1407407&view=auto ============================================================================== --- felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/SelectionTestCase.java (added) +++ felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/registry/SelectionTestCase.java Fri Nov 9 10:05:42 2012 @@ -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); + } + } +} Added: felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/ComponentVisitorTestCase.java URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/ComponentVisitorTestCase.java?rev=1407407&view=auto ============================================================================== --- felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/ComponentVisitorTestCase.java (added) +++ felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/metadata/annotation/visitor/ComponentVisitorTestCase.java Fri Nov 9 10:05:42 2012 @@ -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; + } +} Added: felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/spi/AbsBindingModuleTestCase.java URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/spi/AbsBindingModuleTestCase.java?rev=1407407&view=auto ============================================================================== --- felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/spi/AbsBindingModuleTestCase.java (added) +++ felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulator/spi/AbsBindingModuleTestCase.java Fri Nov 9 10:05:42 2012 @@ -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()); + } + + +}
