Package org.apache.beehive.controls.api.properties

Source Code of org.apache.beehive.controls.api.properties.PropertySetProxy

package org.apache.beehive.controls.api.properties;
/*
* Copyright 2004 The Apache Software Foundation.
*
* 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.
*
* $Header:$
*/

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import org.apache.beehive.controls.api.properties.PropertyKey;
import org.apache.beehive.controls.api.properties.PropertyMap;
import org.apache.beehive.controls.api.properties.PropertySet;

/**
* The PropertySetProxy class is a dynamic proxy InvocationHandler class that exposes the
* values held within a PropertyMap as an Object implementing an annotation type interface.
* <p>
* This enables properties resolved using the PropertyMap's hiearchical resolution mechanism to
* be exposed to the client of the proxy in the same way that JSR-175 annotations are
* exposed using raw Java reflection APIs.   A proxy of this type should behave identically
* to the one returned from a call to <code>AnnotatedElement.getAnnotation()</code>, but backed
* by a richer, more dynamic resolution mechanism.
*
* @see java.lang.reflect.Proxy
* @see java.lang.reflect.InvocationHandler
* @see java.lang.reflect.AnnotatedElement#getAnnotation
* @see org.apache.beehive.controls.api.properties.PropertySet
* @see org.apache.beehive.controls.api.properties.PropertyMap
*/
public class PropertySetProxy <T extends Annotation> implements InvocationHandler
{
    /**
     * Creates a new proxy instance implementing the PropertySet interface and backed
     * by the data from the property map.
     *
     * @param propertySet an annotation type that has the PropertySet meta-annotation
     * @param propertyMap the PropertyMap containing property values backing the proxy
     * @return proxy that implements the PropertySet interface
     */
    public static <T extends Annotation> T getProxy(Class<T> propertySet, PropertyMap propertyMap)
    {
        assert propertySet != null && propertyMap != null;

        if (!propertySet.isAnnotation())
            throw new IllegalArgumentException(propertySet + " is not an annotation type");

        return (T) Proxy.newProxyInstance(propertySet.getClassLoader(),
                                          new Class [] {propertySet },
                                          new PropertySetProxy(propertySet, propertyMap));
    }

    /**
     * Private constructor, called only from the getProxy factory method
     */
    private PropertySetProxy(Class<T> propertySet, PropertyMap propertyMap)
    {
        _propertySet = propertySet;
        _propertyMap = propertyMap;
    }

    //
    // InvocationHandler.invoke
    //
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
    {
        // Handle cases where Object/Annotation methods are called on this
        // proxy. We were getting null back from Annotation.annotationType.
        Object value = null;
        if (method.getDeclaringClass() == Object.class)
        {
            try {
                if (method.getName().equals("getClass"))
                {
                    value = _propertySet;
                }
                else
                {
                    value = method.invoke(_propertyMap, args);
                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
        else if (method.getDeclaringClass() == Annotation.class &&
                 method.getName().equals("annotationType"))
        {
            value = _propertySet;
        }
        else
        {

            // Query the nested value in the property map
            PropertyKey key = new PropertyKey(_propertySet, method.getName());
            value = _propertyMap.getProperty(key);

            // If the returned value is itself a PropertyMap (i.e. a nested annotation type),
            // then wrap it in a PropertySetProxy instance before returning.
            if (value instanceof PropertyMap)
            {
                PropertyMap propertyMap = (PropertyMap)value;
                value = getProxy(propertyMap.getMapClass(), propertyMap);
            }
        }

        return value;
    }

    /**
     * Returns the PropertySet annotation type associated with the proxy
     */
    public Class<T> getPropertySet() { return _propertySet; }

    /**
     * Returns the underlying PropertyMap containing the property values exposed by the
     * proxy.
     */
    public PropertyMap getPropertyMap() { return _propertyMap; }

    private Class<T> _propertySet;
    private PropertyMap _propertyMap;
}
TOP

Related Classes of org.apache.beehive.controls.api.properties.PropertySetProxy

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.