Package com.github.overengineer.container.dynamic

Source Code of com.github.overengineer.container.dynamic.DelegatingService

package com.github.overengineer.container.dynamic;

import com.github.overengineer.container.Provider;
import com.github.overengineer.container.inject.InjectorFactory;
import com.github.overengineer.container.inject.MethodInjector;
import com.github.overengineer.container.key.Key;
import com.github.overengineer.container.metadata.MetadataAdapter;
import com.github.overengineer.container.parameter.ParameterMatchingUtil;

import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
* @author rees.byars
*/
public class DelegatingService<T> implements InvocationHandler, Serializable {

    private final Class<T> serviceInterface;
    private transient Map<Method, ServiceDelegateInvoker> delegateInvokerCache;
    private final InjectorFactory injectorFactory;
    private final MetadataAdapter metadataAdapter;
    private final Provider provider;
    T proxy;

    DelegatingService(Class<T> serviceInterface, Provider provider, InjectorFactory injectorFactory, MetadataAdapter metadataAdapter) {
        this.serviceInterface = serviceInterface;
        this.provider = provider;
        this.injectorFactory = injectorFactory;
        this.metadataAdapter = metadataAdapter;
        initCache();
    }

    @Override
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
        String methodName = method.getName();
        if ("equals".equals(methodName)) {
            return proxy == objects[0];
        } else if ("hashCode".equals(methodName)) {
            return System.identityHashCode(proxy);
        } else if ("toString".equals(methodName)) {
            return proxy.getClass().getName() + '@' + Integer.toHexString(System.identityHashCode(this)) + "$DelegatingService$[" + serviceInterface.getName() + "]";
        }
        if (delegateInvokerCache == null) {
            synchronized (this) {
                if (delegateInvokerCache == null) {
                    initCache();
                }
            }
        }
        return delegateInvokerCache.get(method).invoke(objects);
    }

    private void initCache() {
        delegateInvokerCache = new HashMap<Method, ServiceDelegateInvoker>();
        for (Method serviceMethod : serviceInterface.getDeclaredMethods()) {
            Key delegateKey = metadataAdapter.getDelegateKey(serviceMethod);
            Class<?> delegateClass = delegateKey.getTargetClass();
            Class[] providedArgs = serviceMethod.getParameterTypes();
            Method delegateMethod = null;
            for (Method delegateCandidateMethod : delegateClass.getDeclaredMethods()) {
                //TODO make the provided arg matching injectable to match different parameter builders
                if (delegateCandidateMethod.getName().equals(serviceMethod.getName()) && ParameterMatchingUtil.precedingMatch(providedArgs, delegateCandidateMethod.getParameterTypes())) {
                    delegateMethod = delegateCandidateMethod;
                    break;
                }
            }
            if (delegateMethod == null) {
                //TODO mrpvoe error message
                throw new IllegalArgumentException("No valid delegate methods could be found");
            }
            MethodInjector delegateMethodInjector = injectorFactory.create(delegateClass, delegateMethod, providedArgs);
            @SuppressWarnings("unchecked")
            ServiceDelegateInvoker<T> serviceDelegateInvoker = new ServiceDelegateInvoker<T>(delegateKey, delegateMethodInjector, provider);
            delegateInvokerCache.put(serviceMethod, serviceDelegateInvoker);
        }
    }

}
TOP

Related Classes of com.github.overengineer.container.dynamic.DelegatingService

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.