Introduced a ParameterProvider for the Functions

This commit is contained in:
Lennart Hensler committed 2014-12-15 15:59:24 +01:00
1 parent d2d7cf3783
commit dca9f1b172
15 files changed
+117 -51

No files matched your search

@@ -8,6 +8,7 @@ import org.junit.Before;
import org.junit.Test;
import com.sap.sse.datamining.functions.Function;
import com.sap.sse.datamining.functions.ParameterProvider;
import com.sap.sse.datamining.test.functions.test_classes.DataTypeWithContext;
import com.sap.sse.datamining.test.functions.test_classes.DataTypeWithContextImpl;
import com.sap.sse.datamining.test.functions.test_classes.SimpleClassWithMarkedMethods;
@@ -33,14 +34,26 @@ public class TestMethodWrappingFunctionInvocation {
@Test
public void testInvocationWithParameters() {
SimpleClassWithMarkedMethods instance = new SimpleClassWithMarkedMethods();
int valueToIncrement = 10;
assertThat(increment.tryToInvoke(instance, valueToIncrement), is(instance.increment(valueToIncrement)));
final int valueToIncrement = 10;
ParameterProvider parameterProvider = new ParameterProvider() {
@Override
public Object[] getParameters() {
return new Object[] {valueToIncrement};
}
};
assertThat(increment.tryToInvoke(instance, parameterProvider), is(instance.increment(valueToIncrement)));
}
@Test
public void testInvocationWithWrongParameters() {
DataTypeWithContext dataEntry = new DataTypeWithContextImpl("Regatta Name", "Race Name", 7);
assertThat(getRegattaName.tryToInvoke(dataEntry, "Wrong Parameter"), is(nullValue()));
ParameterProvider parameterProvider = new ParameterProvider() {
@Override
public Object[] getParameters() {
return new Object[] {"Wrong Parameter"};
}
};
assertThat(getRegattaName.tryToInvoke(dataEntry, parameterProvider), is(nullValue()));
SimpleClassWithMarkedMethods instance = new SimpleClassWithMarkedMethods();
assertThat(increment.tryToInvoke(instance), is(nullValue()));
@@ -14,7 +14,7 @@ public class TestMethodFilterCriterias {
@Test
public void testMethodIsCorrectDimensionFilterCriteria() {
FilterCriterion<Method> filterCriteria = new MethodIsCorrectDimensionFilterCriterion();
FilterCriterion<Method> filterCriteria = new MethodIsValidDimensionFilterCriterion();
Method dimension = FunctionTestsUtil.getMethodFromSimpleClassWithMarkedMethod("dimension");
assertThat(filterCriteria.matches(dimension), is(true));
@@ -28,7 +28,7 @@ public class TestMethodFilterCriterias {
@Test
public void testMethodIsCorrectSideEffectFreeValueFilterCriteria() {
FilterCriterion<Method> filterCriteria = new MethodIsCorrectStatisticFilterCriterion();
FilterCriterion<Method> filterCriteria = new MethodIsValidStatisticFilterCriterion();
Method sideEffectFreeValue = FunctionTestsUtil.getMethodFromSimpleClassWithMarkedMethod("sideEffectFreeValue");
assertThat(filterCriteria.matches(sideEffectFreeValue), is(true));
@@ -39,7 +39,7 @@ public class TestMethodFilterCriterias {
@Test
public void testMethodIsCorrectExternalLibraryFunctionFilterCriteria() {
FilterCriterion<Method> filterCriteria = new MethodIsCorrectExternalFunctionFilterCriterion();
FilterCriterion<Method> filterCriteria = new MethodIsValidExternalFunctionFilterCriterion();
Method foo = FunctionTestsUtil.getMethodFromExternalLibraryClass("foo");
assertThat(filterCriteria.matches(foo), is(true));
@@ -33,12 +33,13 @@ public interface Function<ReturnType> {
public ReturnType tryToInvoke(Object instance);
/**
* Tries to invoke the function for the given <code>instance</code> and the given <code>parameters</code>.
* Tries to invoke the function for the given <code>instance</code> and the <code>parameters</code> provided
* by the given {@link ParameterProvider}.
*
* @return The result of the function or <code>null</code>, if an {@link InvocationTargetException},
* {@link IllegalAccessException} or {@link IllegalArgumentException} was thrown.
*/
public ReturnType tryToInvoke(Object instance, Object... parameters);
public ReturnType tryToInvoke(Object instance, ParameterProvider parameterProvider);
public Unit getResultUnit();
@@ -0,0 +1,11 @@
package com.sap.sse.datamining.functions;
import com.sap.sse.datamining.impl.functions.NullParameterProvider;
public interface ParameterProvider {
public static final ParameterProvider NULL = new NullParameterProvider();
public Object[] getParameters();
}
@@ -27,8 +27,8 @@ public class ParallelMultiDimensionsValueNestingGroupingProcessor<DataType>
super(dataType, executor, resultReceivers, dimensions);
}
protected GroupKey createGroupKeyFor(DataType input, Function<?> mainDimension) {
Object keyValue = mainDimension.tryToInvoke(input);
protected GroupKey createGroupKeyFor(DataType input, Function<?> dimension) {
Object keyValue = dimension.tryToInvoke(input);
return new GenericGroupKey<Object>(keyValue);
}
@@ -6,6 +6,7 @@ import java.util.List;
import java.util.Locale;
import com.sap.sse.datamining.functions.Function;
import com.sap.sse.datamining.functions.ParameterProvider;
import com.sap.sse.datamining.i18n.DataMiningStringMessages;
import com.sap.sse.datamining.shared.Unit;
@@ -124,16 +125,16 @@ public class ConcatenatingCompoundFunction<ReturnType> extends AbstractFunction<
@Override
public ReturnType tryToInvoke(Object instance) {
return tryToInvoke(instance, new Object[0]);
return tryToInvoke(instance, ParameterProvider.NULL);
}
@SuppressWarnings("unchecked") // The cast has to work. The types were checked in the constructor.
@SuppressWarnings("unchecked")
@Override
public ReturnType tryToInvoke(Object instance, Object... parameters) {
public ReturnType tryToInvoke(Object instance, ParameterProvider parameterProvider) {
Iterator<Function<?>> functionsIterator = functions.iterator();
Object result = functionsIterator.next().tryToInvoke(instance, parameters);
Object result = functionsIterator.next().tryToInvoke(instance, parameterProvider);
while (functionsIterator.hasNext()) {
Function<?> function = (Function<?>) functionsIterator.next();
Function<?> function = functionsIterator.next();
result = function.tryToInvoke(result);
if (result == null) {
return null;
@@ -6,6 +6,7 @@ import java.util.Arrays;
import java.util.Locale;
import java.util.logging.Level;
import com.sap.sse.datamining.functions.ParameterProvider;
import com.sap.sse.datamining.i18n.DataMiningStringMessages;
import com.sap.sse.datamining.shared.Unit;
import com.sap.sse.datamining.shared.annotations.Connector;
@@ -81,9 +82,13 @@ public class MethodWrappingFunction<ReturnType> extends AbstractFunction<ReturnT
return tryToInvoke(instance, new Object[0]);
}
@SuppressWarnings("unchecked") // The cast has to work, because the constructor checks, that the return types match
@Override
public ReturnType tryToInvoke(Object instance, Object... parameters) {
public ReturnType tryToInvoke(Object instance, ParameterProvider parameterProvider) {
return tryToInvoke(instance, parameterProvider.getParameters());
}
@SuppressWarnings("unchecked") // The cast has to work, because the constructor checks, that the return types match
private ReturnType tryToInvoke(Object instance, Object... parameters) {
if (instance != null) {
try {
return (ReturnType) method.invoke(instance, parameters);
@@ -0,0 +1,12 @@
package com.sap.sse.datamining.impl.functions;
import com.sap.sse.datamining.functions.ParameterProvider;
public class NullParameterProvider implements ParameterProvider {
@Override
public Object[] getParameters() {
return new Object[0];
}
}
@@ -10,14 +10,21 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import com.sap.sse.datamining.components.FilterCriterion;
import com.sap.sse.datamining.factories.FunctionFactory;
import com.sap.sse.datamining.functions.Function;
import com.sap.sse.datamining.functions.FunctionRegistry;
import com.sap.sse.datamining.shared.annotations.Connector;
import com.sap.sse.datamining.shared.annotations.Dimension;
import com.sap.sse.datamining.shared.annotations.Statistic;
import com.sap.sse.datamining.impl.functions.criterias.MethodIsValidConnectorFilterCriterion;
import com.sap.sse.datamining.impl.functions.criterias.MethodIsValidDimensionFilterCriterion;
import com.sap.sse.datamining.impl.functions.criterias.MethodIsValidExternalFunctionFilterCriterion;
import com.sap.sse.datamining.impl.functions.criterias.MethodIsValidStatisticFilterCriterion;
public class SimpleFunctionRegistry implements FunctionRegistry {
private final FilterCriterion<Method> isValidDimension = new MethodIsValidDimensionFilterCriterion();
private final FilterCriterion<Method> isValidStatistic = new MethodIsValidStatisticFilterCriterion();
private final FilterCriterion<Method> isValidConnector = new MethodIsValidConnectorFilterCriterion();
private final FilterCriterion<Method> isValidExternalFunction = new MethodIsValidExternalFunctionFilterCriterion();
private final FunctionFactory functionFactory;
@@ -53,12 +60,12 @@ public class SimpleFunctionRegistry implements FunctionRegistry {
private void scanInternalClass(Class<?> internalClass, List<Function<?>> previousFunctions) {
for (Method method : internalClass.getMethods()) {
if (isValidDimension(method) || isValidStatistic(method)) {
if (isValidDimension.matches(method) || isValidStatistic.matches(method)) {
registerFunction(previousFunctions, method);
continue;
}
if (isConnector(method)) {
if (isValidConnector.matches(method)) {
handleConnectorMethod(method, previousFunctions);
}
}
@@ -101,29 +108,11 @@ public class SimpleFunctionRegistry implements FunctionRegistry {
scanInternalClass(returnType, previousFunctionsClone);
}
private boolean isValidDimension(Method method) {
return method.getAnnotation(Dimension.class) != null &&
!method.getReturnType().equals(Void.TYPE) &&
method.getParameterTypes().length == 0;
}
private boolean isValidStatistic(Method method) {
return method.getAnnotation(Statistic.class) != null &&
!method.getReturnType().equals(Void.TYPE) &&
method.getParameterTypes().length == 0;
}
private boolean isConnector(Method method) {
return method.getAnnotation(Connector.class) != null &&
!method.getReturnType().equals(Void.TYPE) &&
method.getParameterTypes().length == 0;
}
@Override
public void registerAllWithExternalFunctionPolicy(Iterable<Class<?>> externalClassesToScan) {
for (Class<?> externalClass : externalClassesToScan) {
for (Method method : externalClass.getMethods()) {
if (isValidExternalFunction(method)) {
if (isValidExternalFunction.matches(method)) {
Function<?> function = functionFactory.createMethodWrappingFunction(method);
addExternalFunction(function);
}
@@ -139,10 +128,6 @@ public class SimpleFunctionRegistry implements FunctionRegistry {
externalFunctions.get(declaringType).add(function);
}
private boolean isValidExternalFunction(Method method) {
return !method.getReturnType().equals(Void.TYPE) && !method.getDeclaringClass().equals(Object.class);
}
@Override
public void unregisterAllFunctionsOf(Iterable<Class<?>> classesToUnregister) {
for (Class<?> classToUnregister : classesToUnregister) {
@@ -0,0 +1,21 @@
package com.sap.sse.datamining.impl.functions;
import java.util.Locale;
import com.sap.sse.datamining.functions.ParameterProvider;
import com.sap.sse.datamining.i18n.DataMiningStringMessages;
public class StringMessagesParameterProvider implements ParameterProvider {
private final Object[] parameters;
public StringMessagesParameterProvider(Locale locale, DataMiningStringMessages stringMessages) {
parameters = new Object[] {locale, stringMessages};
}
@Override
public Object[] getParameters() {
return parameters;
}
}
@@ -53,7 +53,7 @@ public class IsDeclaringTypeFilterCriterion extends AbstractFunctionFilterCriter
return false;
}
public boolean isDeclaringTypeMatching(Function<?> function, Class<?> expectingType) {
private boolean isDeclaringTypeMatching(Function<?> function, Class<?> expectingType) {
return function.getDeclaringType().equals(expectingType);
}
@@ -0,0 +1,16 @@
package com.sap.sse.datamining.impl.functions.criterias;
import java.lang.reflect.Method;
import com.sap.sse.datamining.shared.annotations.Connector;
public class MethodIsValidConnectorFilterCriterion extends AbstractMethodFilterCriterion {
@Override
public boolean matches(Method method) {
return method.getAnnotation(Connector.class) != null &&
!method.getReturnType().equals(Void.TYPE) &&
method.getParameterTypes().length == 0;
}
}
@@ -4,7 +4,7 @@ import java.lang.reflect.Method;
import com.sap.sse.datamining.shared.annotations.Dimension;
public class MethodIsCorrectDimensionFilterCriterion extends AbstractMethodFilterCriterion {
public class MethodIsValidDimensionFilterCriterion extends AbstractMethodFilterCriterion {
@Override
public boolean matches(Method method) {
@@ -2,7 +2,7 @@ package com.sap.sse.datamining.impl.functions.criterias;
import java.lang.reflect.Method;
public class MethodIsCorrectExternalFunctionFilterCriterion extends AbstractMethodFilterCriterion {
public class MethodIsValidExternalFunctionFilterCriterion extends AbstractMethodFilterCriterion {
@Override
public boolean matches(Method method) {
@@ -4,11 +4,12 @@ import java.lang.reflect.Method;
import com.sap.sse.datamining.shared.annotations.Statistic;
public class MethodIsCorrectStatisticFilterCriterion extends AbstractMethodFilterCriterion {
public class MethodIsValidStatisticFilterCriterion extends AbstractMethodFilterCriterion {
@Override
public boolean matches(Method method) {
return method.getAnnotation(Statistic.class) != null;
return method.getAnnotation(Statistic.class) != null &&
!method.getReturnType().equals(Void.TYPE);
}
}