/******************************************************************************
* Copyright (C) 2014 Yevgeny Krasik *
* *
* 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.github.ykrasik.jaci.reflection.method;
import com.github.ykrasik.jaci.command.CommandDef;
import com.github.ykrasik.jaci.command.CommandOutputPromise;
import com.github.ykrasik.jaci.reflection.ReflectionMethod;
import com.github.ykrasik.jaci.reflection.method.factory.DefaultAnnotationMethodCommandFactory;
import com.github.ykrasik.jaci.reflection.method.factory.MethodCommandFactory;
import com.github.ykrasik.jaci.reflection.method.factory.ToggleAnnotationMethodCommandFactory;
import com.github.ykrasik.jaci.util.opt.Opt;
import java.util.Arrays;
import java.util.List;
/**
* Creates {@link CommandDef}s out of {@link ReflectionMethod}s if they are accepted by one of the {@link MethodCommandFactory}s.
*
* @author Yevgeny Krasik
*/
public class ReflectionMethodProcessor {
private final List<MethodCommandFactory> factories;
/**
* @param outputPromise An {@link CommandOutputPromise} that will be injected into the instance containing the methods.
*/
public ReflectionMethodProcessor(CommandOutputPromise outputPromise) {
this(new DefaultAnnotationMethodCommandFactory(outputPromise), new ToggleAnnotationMethodCommandFactory());
}
/**
* Package-protected for testing.
*/
ReflectionMethodProcessor(MethodCommandFactory... factories) {
this.factories = Arrays.asList(factories);
}
/**
* Process the method and create a {@link CommandDef} out of it, if it is accepted by one of the {@link MethodCommandFactory}s.
*
* @param instance Instance of a class to which this method belongs.
* @param method ReflectionMethod to be processed.
* @return A {@code present} {@link CommandDef} if any of the factories managed to process the method.
*/
public Opt<CommandDef> process(Object instance, ReflectionMethod method) {
try {
return doCreateCommand(instance, method);
} catch (Exception e) {
// Unfortunately, this happens in GWT and kills the whole application if the exception is thrown.
System.err.println("Error creating command: class="+method.getDeclaringClass()+", method=" + method.getName());
e.printStackTrace(System.err);
return Opt.absent();
}
}
private Opt<CommandDef> doCreateCommand(Object instance, ReflectionMethod method) throws Exception {
for (MethodCommandFactory factory : factories) {
final Opt<CommandDef> commandDef = factory.create(instance, method);
if (commandDef.isPresent()) {
return commandDef;
}
}
// None of the registered factories managed to create a commandDef out of the method.
return Opt.absent();
}
}