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

com.gh.bmd.jrt.invocation.Invocations Maven / Gradle / Ivy

There is a newer version: 5.9.0
Show newest version
/*
 * 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 com.gh.bmd.jrt.invocation;

import com.gh.bmd.jrt.channel.ResultChannel;
import com.gh.bmd.jrt.common.ClassToken;
import com.gh.bmd.jrt.common.InvocationException;
import com.gh.bmd.jrt.common.RoutineException;

import java.lang.reflect.Constructor;
import java.util.List;

import javax.annotation.Nonnull;

import static com.gh.bmd.jrt.common.Reflection.findConstructor;

/**
 * Utility class for creating invocation factory objects.
 * 

* Created by davide on 2/12/15. */ public class Invocations { /** * Avoid direct instantiation. */ protected Invocations() { } /** * Builds and returns a new invocation factory creating instances of the specified class token. *

* Note that class tokens of inner and anonymous class can be passed as well. Remember however * that Java creates synthetic constructor for such classes, so be sure to specify the correct * arguments to guarantee proper instantiation. In fact, inner classes always have the outer * instance as first constructor parameter, and anonymous classes has both the outer instance * and all the variables captured in the closure. * * @param invocationToken the invocation class token. * @param the input data type. * @param the output data type. * @return the invocation factory. */ @Nonnull public static InvocationFactory factoryOf( @Nonnull final ClassToken> invocationToken) { return factoryOf(invocationToken.getRawClass()); } /** * Builds and returns a new invocation factory creating instances of the specified class. *

* Note that inner and anonymous classes can be passed as well. Remember however that Java * creates synthetic constructor for such classes, so be sure to specify the correct arguments * to guarantee proper instantiation. In fact, inner classes always have the outer instance as * first constructor parameter, and anonymous classes has both the outer instance and all the * variables captured in the closure. * * @param invocationClass the invocation class. * @param the input data type. * @param the output data type. * @return the invocation factory. */ @Nonnull public static InvocationFactory factoryOf( @Nonnull final Class> invocationClass) { return new DefaultInvocationFactory(invocationClass); } /** * Builds and returns a new factory of invocations calling the specified function.
* Remember to force the input order type, in case the function parameter position needs to be * preserved. *

* Note that the function object must be stateless in order to avoid concurrency issues. * * @param function the function instance. * @param the output data type. * @return the builder instance. */ @Nonnull public static InvocationFactory factoryOn( @Nonnull final Function function) { return new FunctionInvocationFactory(function); } /** * Interface defining a function taking an undefined number of parameters. * * @param the output data type. */ public interface Function { /** * Calls this function. * * @param params the array of parameters. * @return the result. */ OUTPUT call(@Nonnull Object... params); } /** * Default implementation of an invocation factory. * * @param the input data type. * @param the output data type. */ private static class DefaultInvocationFactory implements InvocationFactory { private final Class> mInvocationClass; private Constructor> mConstructor; /** * Constructor. * * @param invocationClass the invocation class. */ @SuppressWarnings("ConstantConditions") private DefaultInvocationFactory( @Nonnull final Class> invocationClass) { if (invocationClass == null) { throw new NullPointerException("the invocation class must be null"); } mInvocationClass = invocationClass; } @Nonnull public Invocation newInvocation(@Nonnull final Object... args) { // the arguments should never change, so it is safe to cache the constructor final Constructor> constructor; if (mConstructor == null) { constructor = findConstructor(mInvocationClass, args); mConstructor = constructor; } else { constructor = mConstructor; } try { return constructor.newInstance(args); } catch (final RoutineException e) { throw e; } catch (final Throwable t) { throw new InvocationException(t); } } } /** * Implementation of a factory of invocations calling a specific function. * * @param the output data type. */ private static class FunctionInvocationFactory implements InvocationFactory { private final Function mFunction; /** * Constructor. * * @param function the function instance. */ @SuppressWarnings("ConstantConditions") private FunctionInvocationFactory(@Nonnull final Function function) { if (function == null) { throw new NullPointerException("the function must not be null"); } mFunction = function; } @Nonnull public Invocation newInvocation(@Nonnull final Object... args) { return new SingleCallInvocation() { @Override public void onCall(@Nonnull final List objects, @Nonnull final ResultChannel result) { result.pass(mFunction.call(objects.toArray())); } }; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy