Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Copyright 2010 the original author or authors.
   *
   * Licensed 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.callbackparams.sandbox;
 
 import java.util.Map;
This class has nested resources that can be used to produce callback-values for Property.Callback through annotations. (The interface Property.Callback itself cannot be implemented directly as of yet.)

Example usage ...
 @RunWith(org.callbackparams.junit4.CallbackParamsRunner)
 public class MyTest {

   @Test
   public void runTest(Property.Callback<MyBean> beanCallback) {
     // ...
   }

   @Property.BeanClass(MyBean.class)
   @Property.Name("myIntProperty")
   enum MyEnum {
       @Property.Value("21") FOO,
       @Property.Value("67") BAR;
   }
 }
 
The annotations around and within MyEnum is meant as a shortcut that is equivalent with this ...
   enum MyEnum implements Property.Callback<MyBean> {
     FOO(21), BAR(67);

     int value;

     MyEnum(int value) {
       this.value = value;
     }

     void setValues(MyBean bean) {
         bean.setMyIntProperty(value);
     }

     void assertValues(MyBean bean) {
       Assert.assertEquals("Value for property \"myIntProperty\" on " + bean,
           value, bean.getMyIntProperty());
     }
   }
 
Thus, a considerable amount of (bold) boilerplate code can be excluded by using the annotations, as shown in the first case.

This class is meant as a proof-of-concept of a backup-factory API that can be used by a callback-interface in case a callback-value neither implements the interface nor provides any implementation through org.callbackparams.CallbackFactory.getCallback().
This class being a proof-of-concept here means that it applies to a concept that is generally understood among developers (i.e. beans and their properties) but unlike Collector the reusability of this class is probably more limited.

Author(s):
Henrik Kaipe
See also:
Collector
public class Property<T> {
    public @interface BeanClass {
        java.lang.Class value();
    }
    public @interface Name {
        String value();
    }
    public @interface Value {
        String value();
    }
    public interface Callback<T> {
        void setValues(T bean);
        void assertValues(T bean);

        
As of today the end-users are not supposed to have their callback- values implement this interface and this method effectivly prevents them from doing so by using API that cannot be accessed by end-user code. Unfortunatelly the method can be invoked, however, but that will always generate an exception.

Deprecated:
we will hopefully find a better solution for this pretty ugly workaround
Parameters:
d parameter of a class with private access, which cannot be reached by end-user code
Throws:
java.lang.UnsupportedOperationException always
                PropertyCallbackFactory.Dummy d)
        throws UnsupportedOperationException;

        
It is because of this inner class that Property.Callback parameters will have their callbacks constructed in a very different way.
        class PropertyCallbackFactory implements CallbackFactory {
            final Class<?> beanClass;
            final Class[] parameterInterfaces;
            final Map<String,PropertyDescriptorpropertyDescriptors =
                    new HashMap<StringPropertyDescriptor>();
            private Type eraseAllButTypeVariable(Type type) {
                if (type instanceof WildcardType) {
                    /* Check for a lower bound */
                    Type[] lowerBounds = ((WildcardType)type).getLowerBounds();
                    if (0 == lowerBounds.length) {
                        return null;
                    } else {
                        type = lowerBounds[0];
                    }
                }
                if (type instanceof ParameterizedType) {
                    return ((ParameterizedType)type).getRawType();
                } else {
                    /* Class of type-variable ... */
                    return type;
                }
            }

            
Recursive thing that is supposed to make us find the
            private Type determineGenericTypeDeclaration(Type type) {
                if (Callback.class == type) {
                    throw new IllegalArgumentException(
                            "The Property.Callback parameter declaration must "
                            + "specify the bean-class as the generic type-"
                            + "parameter of the method paramter-declarations."
                            + " E.g. 'testMethod(Property.Callback<BeanClass> "
                            + "propertyCallback)");
                }
                Class<?> rawType = (Class<?>) (type instanceof Class
                        ? type : ((ParameterizedTypetype).getRawType());
                if (Callback.class == rawType) {
                    return eraseAllButTypeVariable( ((ParameterizedType)type)
                            .getActualTypeArguments()[0]);
                } else if (Callback.class.isAssignableFrom(rawType)) {
                    for (Type interf : rawType.getGenericInterfaces()) {
                        final Type beanType =
                                determineGenericTypeDeclaration(interf);
                        if (null == beanType) {
                            continue;
                        } else if (beanType instanceof Class) {
                            return beanType;
                        } else if (rawType == ((TypeVariable<?>)beanType)
                                .getGenericDeclaration()) {
                            final TypeVariable<?>[] typeParameters =
                                    rawType.getTypeParameters();
                            for (int i = 0 ; i < typeParameters.length ; ++i) {
                                if (beanType == typeParameters[i]) {
                                    return eraseAllButTypeVariable(
                                            ((ParameterizedType)type)
                                            .getActualTypeArguments()[i]);
                                }
                            }
                            throw new Error(beanType + " does not seem to be " +
                                    "declared by " + rawType);
                        } else {
                            return beanType;
                        }
                    }
                    return null;
                } else {
                    return null;
                }
            }
            public PropertyCallbackFactory(Method mint paramIndex) {
                Type beanType =  determineGenericTypeDeclaration(
                        m.getGenericParameterTypes()[paramIndex]);
                if (null == beanType) {
                    throw new Error("Could not determine specified bean-class"
                            + " for parameter-declaration "
                            + m.getGenericParameterTypes()[paramIndex]);
                } else {
                    ..println("Bean type: " + beanType);
                     = (Class<?>) beanType;
                     =
                            new Class[] {m.getParameterTypes()[paramIndex]};
                    try {
                        for (PropertyDescriptor pd :
                                Introspector.getBeanInfo()
                                .getPropertyDescriptors()) {
                            if (null == pd.getPropertyEditorClass()) {
                                Object tmpEditor = PropertyEditorManager
                                        .findEditor(pd.getPropertyType());
                                pd.setPropertyEditorClass(null != tmpEditor
                                        ? tmpEditor.getClass()
                                        : PropertyEditorSupport.class);
                            }
                            .put(pd.getName(), pd);
                        }
                    } catch (IntrospectionException ex) {
                        throw new Error(ex);
                    }
                }
            }
            public Object asCallback(Object callbackRecordElement) {
                if (false == callbackRecordElement instanceof Enum) {
                    return null;
                }
                EnumConstantDescriptor ecd = new EnumConstantDescriptor(
                        (Enum<?>) callbackRecordElement);
                Value value = ecd.getAnnotation(Value.class);
                if (null == value) {
                    return null;
                }
                BeanClass beanClass = ecd.getAnnotation(BeanClass.class);
                if (null == beanClass || this. != beanClass.value()) {
                    return null;
                }
                PropertyDescriptor pd = .get(
                        ecd.getAnnotation(Name.classtrue).value());
                final BasicImpl impl = new BasicImpl(pdvalue.value());
                if (Callback.class == [0]) {
                    return impl;
                } else {
                    return Proxy.newProxyInstance(
                            [0].getClassLoader(),
                            ,
                            new InvocationHandler() {
                        public Object invoke(
                                Object proxyMethod methodObject[] args)
                        throws Throwable {
                            try {
                                return method.invoke(implargs);
                            } catch (InvocationTargetException x) {
                                throw x.getTargetException();
                            }
                        }
                    });
                }
            }
            private static class Dummy {}
        }
    }
    private static class BasicImpl extends Impl {
        final PropertyDescriptor descriptor;
        final Object[] setterArgument;
        public BasicImpl(PropertyDescriptor descriptorString value) {
            this. = descriptor;
            PropertyEditor editor = PropertyEditorManager
                    .findEditor(descriptor.getPropertyType());
            editor.setAsText(value);
            this. = new Object[] {editor.getValue()};
        }
        Object invoke(Method mObject beanObject[] args) {
            try {
                try {
                    m.setAccessible(true);
                } catch (SecurityException ignore) {
                    /* Never mind */
                }
                return m.invoke(beanargs);
            } catch (Exception x) {
                Throwable toThrow;
                if (x instanceof InvocationTargetException) {
                    toThrow = ((InvocationTargetException)x)
                            .getTargetException();
                } else {
                    toThrow = x;
                }
                if (toThrow instanceof RuntimeException) {
                    throw (RuntimeException)toThrow;
                } else {
                    throw new Error(toThrow);
                }
            }
        }
        public void setValues(Object bean) {
            invoke(.getWriteMethod(), bean);
        }
        public void assertValues(Object bean) {
            Object actual = invoke(.getReadMethod(), beannull);
            assert [0].equals(actual) : "Value for property \""
                    + .getName() + "\" on " + bean + ": expected <"
                    + [0] + "> but was <" + actual + ">";
        }
    }
    public abstract static class Impl implements Callback<Object> {

        

Deprecated:
we will hopefully find a better solution for this pretty ugly workaround
        public final void dummyMethodThatMakesThisInterfaceImpossibleToImplement(
                PropertyCallbackFactory.Dummy d) {
            throw new UnsupportedOperationException(
                    "This method is not supposed to be used");
        }
    }
    private Property() {}
New to GrepCode? Check out our FAQ X