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

org.callbackparams.internal.NoargMethodProxyMap Maven / Gradle / Ivy

Go to download

CallbackParams is a JUnit-extension for writing parameterized tests. It unlocks new innovative patterns that offer elegant solutions to many obstacles that are traditionally associated with parameterized testing.

There is a newer version: 1.0-beta-6
Show newest version
/*
 * 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.internal;

import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Convenience class for generating method-names for new no-arg methods that
 * are created by {@link CallbackMethodProxyingRebyter}.
 *
 * @author Henrik Kaipe
 */
class NoargMethodProxyMap {

    private final Set/*String*/ originalMethodNames = new HashSet();
    private final Map/*String,StingBuffer*/ methodNameBuilders = new HashMap();
    private final Map/*String,List*/ noArgMethodNames = new HashMap();
    private final Map/*String,List*/ proxiedMethods = new HashMap();
    private final Set/*String*/ declaringClassNames = new HashSet();

    /**
     * @param template original no-arg method names are collected from this class
     */
    NoargMethodProxyMap(Class template) {
        for (; Object.class != template ; template = template.getSuperclass()) {
            final Method[] declaredMethods = template.getDeclaredMethods();
            for (int i = 0 ; i < declaredMethods.length ; ++i) {
                final Method m = declaredMethods[i];
                if (0 == m.getParameterTypes().length) {
                    originalMethodNames.add(m.getName());
                }
            }
        }
    }

    private String newNoargMethodName(String callbackMethodName) {
        StringBuffer sb = (StringBuffer)
                methodNameBuilders.get(callbackMethodName);
        if (null == sb) {
            String suffixBase = "$callbackProxy";
            sb = new StringBuffer(
                    callbackMethodName.length() + suffixBase.length() + 4)
                    .append(callbackMethodName)
                    .append(suffixBase);
            methodNameBuilders.put(callbackMethodName, sb);
            String candidate = sb.toString();
            sb.append("_1");
            if (false == originalMethodNames.contains(candidate)) {
                return candidate;
            }
        }
        String candidate;
        do {
            candidate = increase(sb);
        } while (originalMethodNames.contains(candidate));
        return candidate;
    }

    private String increase(StringBuffer sb) {
        for (int i = sb.length() - 1 ; true ; --i) {
            char loopChar = sb.charAt(i);
            switch (loopChar) {
                case '9':
                    sb.setCharAt(i, '0');
                    continue;
                case '_':
                    return sb.insert(++i, '1').toString();
                default:
                    sb.setCharAt(i, ++loopChar);
                    return sb.toString();
            }
        }
    }

    /**
     * @param m method to be proxied
     * @return the name of the no-arg proxy-method
     */
    String addMethodToBeProxied(Method m) {
        declaringClassNames.add(m.getDeclaringClass().getName());

        String noargProxyMethodName = findProxyNameOfOverriddenMethod(m);
        if (null == noargProxyMethodName) {
            noargProxyMethodName = newNoargMethodName(m.getName());
            ((List)noArgMethodNames.get(m.getName())).add(noargProxyMethodName);
            proxiedMethods.put(noargProxyMethodName, new ArrayList(4));
        }
        ((List)proxiedMethods.get(noargProxyMethodName)).add(m);
        return noargProxyMethodName;
    }

    private String findProxyNameOfOverriddenMethod(Method m) {
        List/*String*/ existingProxyNames =
                (List) noArgMethodNames.get(m.getName());
        if (null == existingProxyNames) {
            noArgMethodNames.put(m.getName(), new ArrayList());
            return null;

        } else {
            final Type[] parameterTypes = m.getGenericParameterTypes();
            for (Iterator iterNames = existingProxyNames.iterator()
                    ; iterNames.hasNext() ;) {
                final String eachName = (String) iterNames.next();
                for (Iterator iterOo = ((List)proxiedMethods.get(eachName))
                        .iterator() ; iterOo.hasNext() ;) {
                    final Method oo = (Method) iterOo.next();
                    if (oo.getDeclaringClass()
                            .isAssignableFrom(m.getDeclaringClass())
                            || m.getDeclaringClass().isAssignableFrom(
                            oo.getDeclaringClass())) {
                        if (Arrays.equals(parameterTypes,
                                oo.getGenericParameterTypes())){
                            return eachName;
                        }
                    }
                }
            }
            return null;
        }
    }

    Map/*String,Method*/ getProxyMethodsForClass(String className) {
        if (false == declaringClassNames.contains(className)) {
            return Collections.EMPTY_MAP;
        }

        Map/*String,Method*/ methodsForClass = new HashMap();
        for (Iterator iterEntr = proxiedMethods.entrySet().iterator()
                ; iterEntr.hasNext() ;) {
            final Map.Entry/*String,List*/ eachProxyEntry =
                    (Map.Entry) iterEntr.next();
            Iterator iterProxiedMethods =
                    ((List)eachProxyEntry.getValue()).iterator();
            while (iterProxiedMethods.hasNext()) {
                final Method proxiedMethod = (Method) iterProxiedMethods.next();
                if (className.equals(proxiedMethod.getDeclaringClass().getName())) {
                    methodsForClass.put(eachProxyEntry.getKey(), proxiedMethod);
                }
            }
        }
        return methodsForClass;
    }

    String getNameOfProxiedMethod(String proxyMethodName) {
        List/*Method*/ methods = (List) proxiedMethods.get(proxyMethodName);
        return null == methods || methods.isEmpty() ? null
                : ((Method)methods.get(0)).getName();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy