All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.picketlink.common.properties.MethodPropertyImpl Maven / Gradle / Ivy

There is a newer version: 3.0.0.Beta2
Show newest version
/*
 * JBoss, Home of Professional Open Source
 *
 * Copyright 2013 Red Hat, Inc. and/or its affiliates.
 *
 * 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.picketlink.common.properties;

import java.beans.Introspector;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Type;

import org.picketlink.common.reflection.Reflections;

import static org.picketlink.common.reflection.Reflections.invokeMethod;

/**
 * A bean property based on the value represented by a getter/setter method pair
 *
 */
class MethodPropertyImpl implements MethodProperty 
{
    private static final String GETTER_METHOD_PREFIX = "get";
    private static final String SETTER_METHOD_PREFIX = "set";
    private static final String BOOLEAN_GETTER_METHOD_PREFIX = "is";

    private static final int GETTER_METHOD_PREFIX_LENGTH = GETTER_METHOD_PREFIX.length();
    private static final int SETTER_METHOD_PREFIX_LENGTH = SETTER_METHOD_PREFIX.length();
    private static final int BOOLEAN_GETTER_METHOD_PREFIX_LENGTH = BOOLEAN_GETTER_METHOD_PREFIX.length();

    private final Method getterMethod;
    private final String propertyName;
    private final Method setterMethod;

    public MethodPropertyImpl(Method method) 
    {
        final String accessorMethodPrefix;
        final String propertyNameInAccessorMethod;
        
        if (method.getName().startsWith(GETTER_METHOD_PREFIX)) 
        {
            if (method.getReturnType() == Void.TYPE) 
            {
                throw new IllegalArgumentException(
                        "Invalid accessor method, must have return value if starts with 'get'. Method: " + method);
            } 
            else if (method.getParameterTypes().length > 0) 
            {
                throw new IllegalArgumentException(
                        "Invalid accessor method, must have zero arguments if starts with 'get'. Method: " + method);
            }
            propertyNameInAccessorMethod = method.getName().substring(GETTER_METHOD_PREFIX_LENGTH);
            accessorMethodPrefix = GETTER_METHOD_PREFIX;
        } 
        else if (method.getName().startsWith(SETTER_METHOD_PREFIX)) 
        {
            if (method.getReturnType() != Void.TYPE) 
            {
                throw new IllegalArgumentException(
                        "Invalid accessor method, must not have return value if starts with 'set'. Method: " + method);
            } 
            else if (method.getParameterTypes().length != 1) 
            {
                throw new IllegalArgumentException(
                        "Invalid accessor method, must have one argument if starts with 'set'. Method: " + method);
            }
            propertyNameInAccessorMethod = method.getName().substring(SETTER_METHOD_PREFIX_LENGTH);
            accessorMethodPrefix = SETTER_METHOD_PREFIX;
        } 
        else if (method.getName().startsWith(BOOLEAN_GETTER_METHOD_PREFIX)) 
        {
            if (method.getReturnType() != Boolean.TYPE || !method.getReturnType().isPrimitive()) 
            {
                throw new IllegalArgumentException(
                        "Invalid accessor method, must return boolean primitive if starts with 'is'. Method: " + 
                         method);
            }
            propertyNameInAccessorMethod = method.getName().substring(BOOLEAN_GETTER_METHOD_PREFIX_LENGTH);
            accessorMethodPrefix = BOOLEAN_GETTER_METHOD_PREFIX;
        } 
        else 
        {
            throw new IllegalArgumentException(
                    "Invalid accessor method, must start with 'get', 'set' or 'is'.  " + "Method: " + method);
        }
        
        if (propertyNameInAccessorMethod.length() == 0 || 
                !Character.isUpperCase(propertyNameInAccessorMethod.charAt(0))) 
        {
            throw new IllegalArgumentException("Invalid accessor method, prefix '" + accessorMethodPrefix +
                    "' must be followed a non-empty property name, capitalized. Method: " + method);
        }
        
        this.propertyName = Introspector.decapitalize(propertyNameInAccessorMethod);
        this.getterMethod = getGetterMethod(method.getDeclaringClass(), propertyName);
        this.setterMethod = getSetterMethod(method.getDeclaringClass(), propertyName);
    }

    public String getName() 
    {
        return propertyName;
    }

    @SuppressWarnings("unchecked")
    public Class getJavaClass() 
    {
        return (Class) getterMethod.getReturnType();
    }

    public Type getBaseType() 
    {
        return getterMethod.getGenericReturnType();
    }

    public Method getAnnotatedElement() 
    {
        return getterMethod;
    }

    public Member getMember() 
    {
        return getterMethod;
    }

    public V getValue(Object instance) 
    {
        if (getterMethod == null) 
        {
            throw new UnsupportedOperationException("Property " + 
                this.setterMethod.getDeclaringClass() + "." + propertyName + 
                " cannot be read, as there is no getter method.");
        }
        return Reflections.cast(invokeMethod(getterMethod, instance));
    }

    public void setValue(Object instance, V value) 
    {
        if (setterMethod == null) 
        {
            throw new UnsupportedOperationException("Property " + 
                this.getterMethod.getDeclaringClass() + "." + propertyName + 
                " is read only, as there is no setter method.");
        }
        invokeMethod(setterMethod, instance, value);
    }

    private static Method getSetterMethod(Class clazz, String name) 
    {
        Method[] methods = clazz.getMethods();
        for (Method method : methods) 
        {
            String methodName = method.getName();
            if (methodName.startsWith(SETTER_METHOD_PREFIX) && method.getParameterTypes().length == 1) 
            {
                if (Introspector.decapitalize(methodName.substring(SETTER_METHOD_PREFIX_LENGTH)).equals(name)) 
                {
                    return method;
                }
            }
        }
        return null;
    }

    private static Method getGetterMethod(Class clazz, String name) 
    {
        for (Method method : clazz.getDeclaredMethods()) 
        {
            String methodName = method.getName();
            if (method.getParameterTypes().length == 0) 
            {
                if (methodName.startsWith(GETTER_METHOD_PREFIX)) 
                {
                    if (Introspector.decapitalize(methodName.substring(GETTER_METHOD_PREFIX_LENGTH)).equals(name)) 
                    {
                        return method;
                    }
                } 
                else if (methodName.startsWith(BOOLEAN_GETTER_METHOD_PREFIX)) 
                {
                    if (Introspector.decapitalize(
                            methodName.substring(BOOLEAN_GETTER_METHOD_PREFIX_LENGTH)).equals(name)) 
                    {
                        return method;
                    }
                }
            }
        }
        throw new IllegalArgumentException("no such getter method: " + clazz.getName() + '.' + name);
    }

    public Class getDeclaringClass() 
    {
        return getterMethod.getDeclaringClass();
    }

    public boolean isReadOnly() 
    {
        return setterMethod == null;
    }

    public void setAccessible() 
    {
        if (setterMethod != null) 
        {
            Reflections.setAccessible(setterMethod);
        }
        if (getterMethod != null) 
        {
            Reflections.setAccessible(getterMethod);
        }
    }

    @Override
    public String toString() 
    {
        StringBuilder builder = new StringBuilder();
        if (isReadOnly()) 
        {
            builder.append("read-only ").append(setterMethod.toString()).append("; ");
        }
        builder.append(getterMethod.toString());
        return builder.toString();
    }

    @Override
    public int hashCode() 
    {
        int hash = 1;
        hash = hash * 31 + (setterMethod == null ? 0 : setterMethod.hashCode());
        hash = hash * 31 + getterMethod.hashCode();
        return hash;
    }

    @Override
    public boolean equals(Object obj) 
    {
        if (obj instanceof MethodPropertyImpl) 
        {
            MethodPropertyImpl that = (MethodPropertyImpl) obj;
            if (this.setterMethod == null) 
            {
                return that.setterMethod == null && this.getterMethod.equals(that.getterMethod);
            } 
            else 
            {
                return this.setterMethod.equals(that.setterMethod) && this.getterMethod.equals(that.getterMethod);
            }
        } 
        else 
        {
            return false;
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy