de.unentscheidbar.validation.internal.Methods.java Source code

Java tutorial

Introduction

Here is the source code for de.unentscheidbar.validation.internal.Methods.java

Source

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. Portions Copyrighted 2012 Daniel
 * Huss.
 * 
 * The contents of this file are subject to the terms of either the GNU General Public License
 * Version 2 only ("GPL") or the Common Development and Distribution License("CDDL") (collectively,
 * the "License"). You may not use this file except in compliance with the License. You can obtain a
 * copy of the License at http://www.netbeans.org/cddl-gplv2.html or nbbuild/licenses/CDDL-GPL-2-CP.
 * See the License for the specific language governing permissions and limitations under the
 * License. When distributing the software, include this License Header Notice in each file and
 * include the License file at nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this particular file
 * as subject to the "Classpath" exception as provided by Sun in the GPL Version 2 section of the
 * License file that accompanied this code. If applicable, add the following below the License
 * Header, with the fields enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 * 
 * Contributor(s):
 * 
 * The Original Software is NetBeans. The Initial Developer of the Original Software is Sun
 * Microsystems, Inc. Portions Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
 * 
 * If you wish your version of this file to be governed by only the CDDL or only the GPL Version 2,
 * indicate your decision by adding "[Contributor] elects to include this software in this
 * distribution under the [CDDL or GPL Version 2] license." If you do not indicate a single choice
 * of license, a recipient has the option to distribute your version of this file under either the
 * CDDL, the GPL Version 2 or to extend the choice of license to its licensees as provided above.
 * However, if you add GPL Version 2 code and therefore, elected the GPL Version 2 license, then the
 * option applies only if the new code is made subject to such option by the copyright holder.
 */
package de.unentscheidbar.validation.internal;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.List;

import org.apache.commons.lang3.reflect.MethodUtils;
import org.apache.commons.lang3.tuple.Pair;

import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;

public final class Methods {

    private Methods() {

        /* Do not instantiate */
    }

    public static final class MethodChain {

        private final List<Method> chain;

        private MethodChain(List<Method> chain) {

            this.chain = ImmutableList.copyOf(chain);
            if (chain.isEmpty()) {
                throw new IllegalArgumentException("Empty method chain");
            }
        }

        public Object invokeQuietly(Object initial, Object... params) {

            Object target = initial;
            for (int i = 0, len = chain.size() - 1; target != null && i < len; i++) {
                target = Methods.invokeQuietly(chain.get(i), target);
            }
            return Methods.invokeQuietly(chain.get(chain.size() - 1), target, params);
        }
    }

    public static MethodChain findMethod(Class<?> clazz, String methodName, List<Class<?>> parameterTypes,
            String... propertyHierarchy) {

        Class<?>[] paramTypesAsArray = parameterTypes.toArray(new Class<?>[parameterTypes.size()]);
        Method m = MethodUtils.getMatchingAccessibleMethod(clazz, methodName, paramTypesAsArray);

        Builder<Method> builder = ImmutableList.builder();
        for (int i = 0; clazz != null && m == null && i < propertyHierarchy.length; i++) {
            Method propertyAccessor = MethodUtils.getMatchingAccessibleMethod(clazz, propertyHierarchy[i]);
            if (propertyAccessor != null) {
                builder.add(propertyAccessor);
                clazz = propertyAccessor.getReturnType();
                m = MethodUtils.getMatchingAccessibleMethod(clazz, methodName, paramTypesAsArray);
            }
        }
        if (m == null) {
            /* No such method found */
            return null;
        } else {
            /*
             * The list builder now contains all properties that lead to an accessible method m
             * which has the desired signature
             */
            builder.add(m);
            return new MethodChain(builder.build());
        }
    }

    public static MethodChain findMethod(Class<?> clazz, Pair<String, Class<?>> candidate,
            String... propertyHierarchy) {

        return findMethod(clazz, Collections.singletonList(candidate), propertyHierarchy);
    }

    public static MethodChain findMethod(Class<?> clazz, List<Pair<String, Class<?>>> candidates,
            String... propertyHierarchy) {

        MethodChain result = null;
        for (Pair<String, Class<?>> candidate : candidates) {
            String methodName = candidate.getLeft();
            List<Class<?>> parameterType = Collections.<Class<?>>singletonList(candidate.getRight());

            result = findMethod(clazz, methodName, parameterType, propertyHierarchy);
            if (result != null)
                break;
        }
        return result;
    }

    public static Object invokeQuietly(Method method, Object target, Object... params) {

        try {
            return method.invoke(target, params);
        } catch (IllegalAccessException e) {
            throw new IllegalArgumentException("Method not accessible");
        } catch (InvocationTargetException e) {
            /*
             * Eek! Not our fault.
             */
            throw Throwables.propagate(e);
        }
    }
}