ParameterProviders for localization parameters are automatically resolved

This commit is contained in:
Lennart Hensler committed 2015-01-12 15:38:38 +01:00
1 parent 8c4cccd5e5
commit 1cecc06d03
18 files changed
+91 -282

No files matched your search

@@ -14,11 +14,13 @@ import java.util.concurrent.ExecutionException;
import org.junit.Before;
import org.junit.Test;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.datamining.DataRetrieverChainBuilder;
import com.sap.sse.datamining.DataRetrieverChainDefinition;
import com.sap.sse.datamining.Query;
import com.sap.sse.datamining.components.Processor;
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.impl.components.GroupedDataEntry;
import com.sap.sse.datamining.shared.GroupKey;
@@ -71,16 +73,16 @@ public class TestDimensionsValuesQuery {
protected Processor<Collection<Test_Regatta>, ?> createFirstProcessor() {
Processor<GroupedDataEntry<Object>, Map<GroupKey, Set<Object>>> resultCollector = ComponentTestsUtil.getProcessorFactory().createGroupedDataCollectingAsSetProcessor(this);
Collection<Function<?>> legDimensions = new ArrayList<>();
legDimensions.add(dimensionLegNumber);
legDimensions.add(dimensionCompetitorName);
legDimensions.add(dimensionCompetitorSailID);
Collection<Pair<Function<?>, ParameterProvider>> legDimensions = new ArrayList<>();
legDimensions.add(new Pair<>(dimensionLegNumber, ParameterProvider.NULL));
legDimensions.add(new Pair<>(dimensionCompetitorName, ParameterProvider.NULL));
legDimensions.add(new Pair<>(dimensionCompetitorSailID, ParameterProvider.NULL));
Collection<Function<?>> raceDimensions = new ArrayList<>();
raceDimensions.add(dimensionRegattaName);
raceDimensions.add(dimensionRaceName);
raceDimensions.add(dimensionBoatClassName);
raceDimensions.add(dimensionYear);
Collection<Pair<Function<?>, ParameterProvider>> raceDimensions = new ArrayList<>();
raceDimensions.add(new Pair<>(dimensionRegattaName, ParameterProvider.NULL));
raceDimensions.add(new Pair<>(dimensionRaceName, ParameterProvider.NULL));
raceDimensions.add(new Pair<>(dimensionBoatClassName, ParameterProvider.NULL));
raceDimensions.add(new Pair<>(dimensionYear, ParameterProvider.NULL));
DataRetrieverChainBuilder<Collection<Test_Regatta>> chainBuilder = dataRetrieverChainDefinition.startBuilding(ConcurrencyTestsUtil.getExecutor());
chainBuilder.stepFurther(); //Initialization
@@ -20,20 +20,20 @@ import java.util.concurrent.TimeoutException;
import org.junit.Before;
import org.junit.Test;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.datamining.AdditionalResultDataBuilder;
import com.sap.sse.datamining.Query;
import com.sap.sse.datamining.components.FilterCriterion;
import com.sap.sse.datamining.components.Processor;
import com.sap.sse.datamining.factories.ProcessorFactory;
import com.sap.sse.datamining.functions.Function;
import com.sap.sse.datamining.functions.FunctionProvider;
import com.sap.sse.datamining.functions.ParameterProvider;
import com.sap.sse.datamining.i18n.DataMiningStringMessages;
import com.sap.sse.datamining.impl.components.AbstractSimpleParallelProcessor;
import com.sap.sse.datamining.impl.components.AbstractSimpleRetrievalProcessor;
import com.sap.sse.datamining.impl.components.GroupedDataEntry;
import com.sap.sse.datamining.impl.components.ParallelFilteringProcessor;
import com.sap.sse.datamining.impl.criterias.AbstractFilterCriterion;
import com.sap.sse.datamining.impl.functions.FunctionManager;
import com.sap.sse.datamining.shared.GroupKey;
import com.sap.sse.datamining.shared.QueryResult;
import com.sap.sse.datamining.shared.Unit;
@@ -59,8 +59,7 @@ public class TestProcessorQuery {
@Before
public void initializeProcessorFactory() {
FunctionProvider emptyFunctionProvider = new FunctionManager();
processorFactory = new ProcessorFactory(ConcurrencyTestsUtil.getExecutor(), emptyFunctionProvider);
processorFactory = new ProcessorFactory(ConcurrencyTestsUtil.getExecutor());
}
@Test
@@ -118,11 +117,11 @@ public class TestProcessorQuery {
Method getCrossSumMethod = FunctionTestsUtil.getMethodFromClass(Number.class, "getCrossSum");
Function<Double> getCrossSumFunction = FunctionTestsUtil.getFunctionFactory().createMethodWrappingFunction(getCrossSumMethod);
Processor<GroupedDataEntry<Number>, GroupedDataEntry<Double>> crossSumExtractor = processorFactory.createExtractionProcessor(sumAggregator, getCrossSumFunction);
Processor<GroupedDataEntry<Number>, GroupedDataEntry<Double>> crossSumExtractor = processorFactory.createExtractionProcessor(sumAggregator, getCrossSumFunction, ParameterProvider.NULL);
List<Function<?>> dimensions = new ArrayList<>();
List<Pair<Function<?>, ParameterProvider>> dimensions = new ArrayList<>();
Function<Integer> getLengthFunction = FunctionTestsUtil.getFunctionFactory().createMethodWrappingFunction(FunctionTestsUtil.getMethodFromClass(Number.class, "getLength"));
dimensions.add(getLengthFunction);
dimensions.add(new Pair<>(getLengthFunction, ParameterProvider.NULL));
Processor<Number, GroupedDataEntry<Number>> lengthGrouper = processorFactory.createGroupingProcessor(Number.class, crossSumExtractor, dimensions);
Collection<Processor<Number, ?>> filtrationResultReceivers = new ArrayList<>();
filtrationResultReceivers.add(lengthGrouper);
@@ -11,9 +11,11 @@ import java.util.List;
import org.junit.Before;
import org.junit.Test;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.datamining.components.Processor;
import com.sap.sse.datamining.factories.ProcessorFactory;
import com.sap.sse.datamining.functions.Function;
import com.sap.sse.datamining.functions.ParameterProvider;
import com.sap.sse.datamining.impl.functions.MethodWrappingFunction;
import com.sap.sse.datamining.shared.GroupKey;
import com.sap.sse.datamining.shared.impl.GenericGroupKey;
@@ -46,9 +48,9 @@ public class TestParallelMultiDimensionalGroupingProcessor {
receivers = new ArrayList<>();
receivers.add(receiver);
List<Function<?>> dimensions = new ArrayList<Function<?>>();
dimensions.add(new MethodWrappingFunction<>(Number.class.getMethod("getLength", new Class<?>[0]), int.class));
dimensions.add(new MethodWrappingFunction<>(Number.class.getMethod("getCrossSum", new Class<?>[0]), int.class));
List<Pair<Function<?>, ParameterProvider>> dimensions = new ArrayList<>();
dimensions.add(new Pair<>(new MethodWrappingFunction<>(Number.class.getMethod("getLength", new Class<?>[0]), int.class), ParameterProvider.NULL));
dimensions.add(new Pair<>(new MethodWrappingFunction<>(Number.class.getMethod("getCrossSum", new Class<?>[0]), int.class), ParameterProvider.NULL));
processor = ComponentTestsUtil.getProcessorFactory().createGroupingProcessor(Number.class, receivers, dimensions);
}
@@ -60,15 +62,15 @@ public class TestParallelMultiDimensionalGroupingProcessor {
@Test(expected=IllegalArgumentException.class)
public void testConstructionWithEmptyDimensions() {
List<Function<?>> dimensions = new ArrayList<>();
List<Pair<Function<?>, ParameterProvider>> dimensions = new ArrayList<>();
processorFactory.createGroupingProcessor(Number.class, receivers, dimensions);
}
@Test(expected=IllegalArgumentException.class)
public void testConstructionWithFunctionsInsteadOfDimensions() {
List<Function<?>> functions = new ArrayList<>();
List<Pair<Function<?>, ParameterProvider>> functions = new ArrayList<>();
Method method = FunctionTestsUtil.getMethodFromSimpleClassWithMarkedMethod("sideEffectFreeValue");
functions.add(FunctionTestsUtil.getFunctionFactory().createMethodWrappingFunction(method));
functions.add(new Pair<>(FunctionTestsUtil.getFunctionFactory().createMethodWrappingFunction(method), ParameterProvider.NULL));
processorFactory.createGroupingProcessor(Number.class, receivers, functions);
}
@@ -5,7 +5,6 @@ import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
@@ -17,8 +16,6 @@ import org.junit.Test;
import com.sap.sse.datamining.DataRetrieverChainDefinition;
import com.sap.sse.datamining.components.Processor;
import com.sap.sse.datamining.functions.Function;
import com.sap.sse.datamining.functions.FunctionProvider;
import com.sap.sse.datamining.functions.ParameterProvider;
import com.sap.sse.datamining.i18n.DataMiningStringMessages;
import com.sap.sse.datamining.impl.SimpleDataRetrieverChainDefinition;
import com.sap.sse.datamining.shared.dto.FunctionDTO;
@@ -151,54 +148,5 @@ public class TestFunctionManagerAsFunctionProvider {
public void testGetFunctionForNullDTO() {
assertThat(functionManager.getFunctionForDTO(null), is(nullValue()));
}
@Test
public void testGetParameterProviderForNullaryFunction() {
Method nullaryDimensionMethod = FunctionTestsUtil.getMethodFromClass(SimpleClassWithMarkedMethods.class, "dimension");
Function<Object> nullaryDimension = FunctionTestsUtil.getFunctionFactory().createMethodWrappingFunction(nullaryDimensionMethod);
FunctionProvider functionProvider = new FunctionManager();
assertThat(functionProvider.getParameterProviderFor(nullaryDimension), is(ParameterProvider.NULL));
}
@Test
public void testGetPrameterProviderForFunctionsWithParameters() {
FunctionManager functionManager = new FunctionManager();
ParameterProvider intParameterProvider = new ParameterProvider() {
@Override
public Object[] getParameters() {
return new Object[] {1};
}
@Override
public Iterable<Class<?>> getParameterTypes() {
Collection<Class<?>> parameterTypes = new ArrayList<>();
parameterTypes.add(int.class);
return parameterTypes;
}
};
functionManager.registerParameterProvider(intParameterProvider);
LocalizationParameterProvider stringMessagesParameterProvider = new LocalizationParameterProvider(Locale.ENGLISH, stringMessages);
functionManager.registerParameterProvider(stringMessagesParameterProvider);
Method incrementMethod = FunctionTestsUtil.getMethodFromClass(SimpleClassWithMarkedMethods.class, "increment", int.class);
Function<Object> increment = FunctionTestsUtil.getFunctionFactory().createMethodWrappingFunction(incrementMethod);
assertThat(functionManager.getParameterProviderFor(increment), is(intParameterProvider));
Method getLocalizedNameMethod = FunctionTestsUtil.getMethodFromClass(SimpleClassWithMarkedMethods.class, "getLocalizedName", Locale.class, DataMiningStringMessages.class);
Function<Object> getLocalizedName = FunctionTestsUtil.getFunctionFactory().createMethodWrappingFunction(getLocalizedNameMethod);
assertThat(functionManager.getParameterProviderFor(getLocalizedName), is(stringMessagesParameterProvider));
}
@Test
public void testGetParameterProviderForFunctionWithoutAnAvailableParameterProvider() {
FunctionManager functionManager = new FunctionManager();
//Adding a wrong ParameterProvider to increase code coverage
functionManager.registerParameterProvider(new LocalizationParameterProvider(Locale.ENGLISH, stringMessages));
Method incrementMethod = FunctionTestsUtil.getMethodFromClass(SimpleClassWithMarkedMethods.class, "increment", int.class);
Function<Object> increment = FunctionTestsUtil.getFunctionFactory().createMethodWrappingFunction(incrementMethod);
assertThat(functionManager.getParameterProviderFor(increment), nullValue());
}
}
@@ -4,13 +4,10 @@ import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
import java.util.Collections;
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;
@@ -37,15 +34,13 @@ public class TestMethodWrappingFunctionInvocation {
public void testInvocationWithParameters() {
SimpleClassWithMarkedMethods instance = new SimpleClassWithMarkedMethods();
final int valueToIncrement = 10;
ParameterProvider parameterProvider = new SimpleParameterProvider(Collections.emptyList(), new Object[] {valueToIncrement});
assertThat(increment.tryToInvoke(instance, parameterProvider), is(instance.increment(valueToIncrement)));
assertThat(increment.tryToInvoke(instance, () -> {return new Object[] {valueToIncrement};} ), is(instance.increment(valueToIncrement)));
}
@Test
public void testInvocationWithWrongParameters() {
DataTypeWithContext dataEntry = new DataTypeWithContextImpl("Regatta Name", "Race Name", 7);
ParameterProvider parameterProvider = new SimpleParameterProvider(Collections.emptyList(), new Object[] {"Wrong Parameter"});
assertThat(getRegattaName.tryToInvoke(dataEntry, parameterProvider), is(nullValue()));
assertThat(getRegattaName.tryToInvoke(dataEntry, () -> {return new Object[] {"Wrong Parameter"};} ), is(nullValue()));
SimpleClassWithMarkedMethods instance = new SimpleClassWithMarkedMethods();
assertThat(increment.tryToInvoke(instance), is(nullValue()));
@@ -5,8 +5,6 @@ import java.util.Arrays;
import java.util.Collection;
import com.sap.sse.datamining.factories.ProcessorFactory;
import com.sap.sse.datamining.functions.FunctionProvider;
import com.sap.sse.datamining.impl.functions.FunctionManager;
import com.sap.sse.datamining.test.functions.registry.test_classes.Test_Boat;
import com.sap.sse.datamining.test.functions.registry.test_classes.Test_BoatClass;
import com.sap.sse.datamining.test.functions.registry.test_classes.Test_Competitor;
@@ -24,8 +22,7 @@ import com.sap.sse.datamining.test.functions.registry.test_classes.impl.Test_Tea
public final class ComponentTestsUtil {
private final static FunctionProvider emptyFunctionProvider = new FunctionManager();
private final static ProcessorFactory processorFactory = new ProcessorFactory(ConcurrencyTestsUtil.getExecutor(), emptyFunctionProvider);
private final static ProcessorFactory processorFactory = new ProcessorFactory(ConcurrencyTestsUtil.getExecutor());
public static ProcessorFactory getProcessorFactory() {
return processorFactory;
@@ -7,7 +7,6 @@ import java.util.concurrent.ExecutorService;
import com.sap.sse.datamining.functions.Function;
import com.sap.sse.datamining.functions.FunctionProvider;
import com.sap.sse.datamining.functions.ParameterProvider;
import com.sap.sse.datamining.i18n.DataMiningStringMessages;
import com.sap.sse.datamining.impl.DataRetrieverChainDefinitionProvider;
import com.sap.sse.datamining.shared.QueryDefinitionDTO;
@@ -35,8 +34,6 @@ public interface DataMiningServer {
* @return The first function, that matches the given DTO or <code>null</code>
*/
public Function<?> getFunctionForDTO(FunctionDTO functionDTO);
public ParameterProvider getParameterProviderFor(Function<?> function);
public DataRetrieverChainDefinitionProvider getDataRetrieverChainDefinitionProvider();
@@ -1,7 +1,6 @@
package com.sap.sse.datamining;
import com.sap.sse.datamining.functions.FunctionRegistry;
import com.sap.sse.datamining.functions.ParameterProvider;
import com.sap.sse.datamining.i18n.DataMiningStringMessages;
public interface ModifiableDataMiningServer extends DataMiningServer {
@@ -13,10 +12,8 @@ public interface ModifiableDataMiningServer extends DataMiningServer {
public void registerAllWithInternalFunctionPolicy(Iterable<Class<?>> classesToScan);
public void registerAllWithExternalFunctionPolicy(Iterable<Class<?>> externalClassesToScan);
public void registerParameterProvider(ParameterProvider parameterProvider);
public void unregisterAllFunctionsOf(Iterable<Class<?>> classesToUnregister);
public void unregisterParameterProvider(ParameterProvider parameterProvider);
public void registerDataRetrieverChainDefinition(DataRetrieverChainDefinition<?, ?> dataRetrieverChainDefinition);
public void unregisterDataRetrieverChainDefinition(DataRetrieverChainDefinition<?, ?> dataRetrieverChainDefinition);
@@ -11,7 +11,6 @@ import java.util.concurrent.ExecutorService;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.datamining.components.Processor;
import com.sap.sse.datamining.functions.Function;
import com.sap.sse.datamining.functions.FunctionProvider;
import com.sap.sse.datamining.functions.ParameterProvider;
import com.sap.sse.datamining.i18n.DataMiningStringMessages;
import com.sap.sse.datamining.impl.ProcessorQuery;
@@ -29,11 +28,9 @@ import com.sap.sse.datamining.shared.components.AggregatorType;
public class ProcessorFactory {
private final ExecutorService executor;
private final FunctionProvider functionProvider;
public ProcessorFactory(ExecutorService executor, FunctionProvider functionProvider) {
public ProcessorFactory(ExecutorService executor) {
this.executor = executor;
this.functionProvider = functionProvider;
}
/**
@@ -80,16 +77,14 @@ public class ProcessorFactory {
* Creates an extraction processor with the given aggregation processor as result receiver.
*/
public <ElementType, ResultType> Processor<GroupedDataEntry<ElementType>, GroupedDataEntry<ResultType>> createExtractionProcessor(
Processor<GroupedDataEntry<ResultType>, ?> aggregationProcessor, Function<ResultType> extractionFunction) {
Processor<GroupedDataEntry<ResultType>, ?> aggregationProcessor, Function<ResultType> extractionFunction, ParameterProvider parameterProvider) {
Collection<Processor<GroupedDataEntry<ResultType>, ?>> resultReceivers = new ArrayList<>();
resultReceivers.add(aggregationProcessor);
return createExtractionProcessor(resultReceivers, extractionFunction);
return createExtractionProcessor(resultReceivers, extractionFunction, parameterProvider);
}
public <ElementType, ResultType> Processor<GroupedDataEntry<ElementType>, GroupedDataEntry<ResultType>> createExtractionProcessor(
Collection<Processor<GroupedDataEntry<ResultType>, ?>> resultReceivers, Function<ResultType> extractionFunction) {
ParameterProvider parameterProvider = functionProvider.getParameterProviderFor(extractionFunction);
throwExceptionIfParameterProviderIsNull(extractionFunction, parameterProvider);
Collection<Processor<GroupedDataEntry<ResultType>, ?>> resultReceivers, Function<ResultType> extractionFunction, ParameterProvider parameterProvider) {
return new ParallelGroupedElementsValueExtractionProcessor<ElementType, ResultType>(executor,
resultReceivers, extractionFunction, parameterProvider);
}
@@ -97,27 +92,14 @@ public class ProcessorFactory {
/**
* Creates a grouping processor with the given extraction processor as result receiver.
*/
public <DataType> Processor<DataType, GroupedDataEntry<DataType>> createGroupingProcessor(Class<DataType> dataType, Processor<GroupedDataEntry<DataType>, ?> extractionProcessor, List<Function<?>> dimensionsToGroupBy) {
public <DataType> Processor<DataType, GroupedDataEntry<DataType>> createGroupingProcessor(Class<DataType> dataType, Processor<GroupedDataEntry<DataType>, ?> extractionProcessor, Iterable<Pair<Function<?>, ParameterProvider>> dimensionsToGroupByWithParameterProvider) {
Collection<Processor<GroupedDataEntry<DataType>, ?>> resultReceivers = new ArrayList<>();
resultReceivers.add(extractionProcessor);
return createGroupingProcessor(dataType, resultReceivers, dimensionsToGroupBy);
return createGroupingProcessor(dataType, resultReceivers, dimensionsToGroupByWithParameterProvider);
}
public <DataType> Processor<DataType, GroupedDataEntry<DataType>> createGroupingProcessor(Class<DataType> dataType, Collection<Processor<GroupedDataEntry<DataType>, ?>> resultReceivers, List<Function<?>> dimensionsToGroupBy) {
Collection<Pair<Function<?>, ParameterProvider>> dimensionsToGroupByWithNullParameterProvider = new ArrayList<>();
for (Function<?> dimension : dimensionsToGroupBy) {
ParameterProvider parameterProvider = functionProvider.getParameterProviderFor(dimension);
throwExceptionIfParameterProviderIsNull(dimension, parameterProvider);
dimensionsToGroupByWithNullParameterProvider.add(new Pair<Function<?>, ParameterProvider>(dimension, parameterProvider));
}
return new ParallelMultiDimensionsValueNestingGroupingProcessor<>(dataType, executor, resultReceivers, dimensionsToGroupByWithNullParameterProvider);
}
private void throwExceptionIfParameterProviderIsNull(Function<?> function, ParameterProvider parameterProvider) {
if (parameterProvider == null) {
throw new NullPointerException("There is no " + ParameterProvider.class.getSimpleName() + " available for the " +
Function.class.getSimpleName() + " '" + function.toString() + "'");
}
public <DataType> Processor<DataType, GroupedDataEntry<DataType>> createGroupingProcessor(Class<DataType> dataType, Collection<Processor<GroupedDataEntry<DataType>, ?>> resultReceivers, Iterable<Pair<Function<?>, ParameterProvider>> dimensionsToGroupByWithParameterProvider) {
return new ParallelMultiDimensionsValueNestingGroupingProcessor<>(dataType, executor, resultReceivers, dimensionsToGroupByWithParameterProvider);
}
public <DataType> Processor<DataType, GroupedDataEntry<DataType>> createGroupingProcessorWithParameter(Class<DataType> dataType, Collection<Processor<GroupedDataEntry<DataType>, ?>> resultReceivers, List<Pair<Function<?>, ParameterProvider>> dimensionsToGroupByWithParameterProvider) {
@@ -129,18 +111,18 @@ public class ProcessorFactory {
*/
@SuppressWarnings("unchecked")
public <DataType> Collection<Processor<DataType, GroupedDataEntry<DataType>>> createGroupingExtractorsForDimensions(Class<DataType> dataType,
Processor<GroupedDataEntry<Object>, ?> valueCollector, Iterable<Function<?>> dimensions,
Processor<GroupedDataEntry<Object>, ?> valueCollector, Iterable<Pair<Function<?>, ParameterProvider>> dimensionsToGroupByWithParameterProvider,
DataMiningStringMessages stringMessages, Locale locale) {
Collection<Processor<GroupedDataEntry<Object>, ?>> extractionResultReceivers = new ArrayList<>();
extractionResultReceivers.add(valueCollector);
Collection<Processor<DataType, GroupedDataEntry<DataType>>> groupingExtractors = new ArrayList<>();
for (Function<?> dimension : dimensions) {
Processor<GroupedDataEntry<DataType>, GroupedDataEntry<Object>> dimensionValueExtractor = createExtractionProcessor(extractionResultReceivers, (Function<Object>) dimension);
for (Pair<Function<?>, ParameterProvider> dimensionWithParameterProvider : dimensionsToGroupByWithParameterProvider) {
Processor<GroupedDataEntry<DataType>, GroupedDataEntry<Object>> dimensionValueExtractor = createExtractionProcessor(extractionResultReceivers, (Function<Object>) dimensionWithParameterProvider.getA(), dimensionWithParameterProvider.getB());
Collection<Processor<GroupedDataEntry<DataType>, ?>> groupingResultReceivers = new ArrayList<>();
groupingResultReceivers.add(dimensionValueExtractor);
Processor<DataType, GroupedDataEntry<DataType>> byDimensionGrouper = new ParallelByDimensionGroupingProcessor<>(dataType, executor, groupingResultReceivers, dimension, stringMessages, locale);
Processor<DataType, GroupedDataEntry<DataType>> byDimensionGrouper = new ParallelByDimensionGroupingProcessor<>(dataType, executor, groupingResultReceivers, dimensionWithParameterProvider.getA(), stringMessages, locale);
groupingExtractors.add(byDimensionGrouper);
}
return groupingExtractors;
@@ -3,12 +3,14 @@ package com.sap.sse.datamining.factories;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.datamining.DataRetrieverChainBuilder;
import com.sap.sse.datamining.DataRetrieverChainDefinition;
import com.sap.sse.datamining.Query;
@@ -16,7 +18,6 @@ import com.sap.sse.datamining.QueryDefinition;
import com.sap.sse.datamining.components.FilterCriterion;
import com.sap.sse.datamining.components.Processor;
import com.sap.sse.datamining.functions.Function;
import com.sap.sse.datamining.functions.FunctionProvider;
import com.sap.sse.datamining.functions.ParameterProvider;
import com.sap.sse.datamining.i18n.DataMiningStringMessages;
import com.sap.sse.datamining.impl.ProcessorQuery;
@@ -24,27 +25,28 @@ import com.sap.sse.datamining.impl.components.GroupedDataEntry;
import com.sap.sse.datamining.impl.criterias.AndCompoundFilterCriterion;
import com.sap.sse.datamining.impl.criterias.CompoundFilterCriterion;
import com.sap.sse.datamining.impl.criterias.FunctionValuesFilterCriterion;
import com.sap.sse.datamining.impl.functions.LocalizationParameterProvider;
import com.sap.sse.datamining.shared.GroupKey;
public class QueryFactory {
public <DataSourceType, DataType, ResultType> Query<ResultType> createQuery(DataSourceType dataSource, QueryDefinition<DataSourceType, DataType, ResultType> queryDefinition,
DataMiningStringMessages stringMessages, ExecutorService executor, FunctionProvider functionProvider) {
DataMiningStringMessages stringMessages, ExecutorService executor) {
return new ProcessorQuery<ResultType, DataSourceType>(dataSource, stringMessages, queryDefinition.getLocale()) {
@Override
protected Processor<DataSourceType, ?> createFirstProcessor() {
ProcessorFactory processorFactory = new ProcessorFactory(executor, functionProvider);
ProcessorFactory processorFactory = new ProcessorFactory(executor);
Function<ResultType> extractionFunction = queryDefinition.getStatisticToCalculate();
Class<DataType> dataTypeToRetrieve = queryDefinition.getDataType();
Processor<GroupedDataEntry<ResultType>, Map<GroupKey, ResultType>> aggregationProcessor = processorFactory.createAggregationProcessor(/*query*/ this, queryDefinition.getAggregatorType(), queryDefinition.getResultType());
Processor<GroupedDataEntry<DataType>, GroupedDataEntry<ResultType>> extractionProcessor = processorFactory.createExtractionProcessor(aggregationProcessor, extractionFunction);
Processor<GroupedDataEntry<DataType>, GroupedDataEntry<ResultType>> extractionProcessor = processorFactory.createExtractionProcessor(aggregationProcessor, extractionFunction, getParameterProviderFor(extractionFunction, stringMessages, queryDefinition.getLocale()));
Processor<DataType, GroupedDataEntry<DataType>> groupingProcessor = processorFactory.createGroupingProcessor(dataTypeToRetrieve, extractionProcessor, queryDefinition.getDimensionsToGroupBy());
Processor<DataType, GroupedDataEntry<DataType>> groupingProcessor = processorFactory.createGroupingProcessor(dataTypeToRetrieve, extractionProcessor, getParameterProvidersFor(queryDefinition.getDimensionsToGroupBy(), stringMessages, queryDefinition.getLocale()));
DataRetrieverChainBuilder<DataSourceType> chainBuilder = queryDefinition.getDataRetrieverChainDefinition().startBuilding(executor);
Map<Integer, FilterCriterion<?>> criteriaMappedByRetrieverLevel = createFilterCriteria(queryDefinition.getFilterSelection(), functionProvider);
Map<Integer, FilterCriterion<?>> criteriaMappedByRetrieverLevel = createFilterCriteria(queryDefinition.getFilterSelection());
while (chainBuilder.canStepFurther()) {
chainBuilder.stepFurther();
@@ -60,14 +62,45 @@ public class QueryFactory {
};
}
private Iterable<Pair<Function<?>, ParameterProvider>> getParameterProvidersFor(Iterable<Function<?>> functions, DataMiningStringMessages stringMessages, Locale locale) {
Collection<Pair<Function<?>, ParameterProvider>> functionsWithParameterProvider = new ArrayList<>();
for (Function<?> function : functions) {
functionsWithParameterProvider.add(new Pair<>(function, getParameterProviderFor(function, stringMessages, locale)));
}
return functionsWithParameterProvider;
}
private ParameterProvider getParameterProviderFor(Function<?> function, DataMiningStringMessages stringMessages, Locale locale) {
if (functionNeedsLocalizationParameters(function)) {
return new LocalizationParameterProvider(locale, stringMessages);
}
return ParameterProvider.NULL;
}
private boolean functionNeedsLocalizationParameters(Function<?> function) {
Iterator<Class<?>> parameterTypesIterator = function.getParameters().iterator();
int parameterCount = 0;
while (parameterTypesIterator.hasNext()) {
parameterCount++;
parameterTypesIterator.next();
}
if (parameterCount != 2) {
return false;
}
parameterTypesIterator = function.getParameters().iterator();
Class<?> firstParameter = parameterTypesIterator.next();
Class<?> secondParameter = parameterTypesIterator.next();
return firstParameter.isAssignableFrom(Locale.class) && secondParameter.isAssignableFrom(DataMiningStringMessages.class);
}
@SuppressWarnings("unchecked")
private <DataType> Map<Integer, FilterCriterion<?>> createFilterCriteria(Map<Integer, Map<Function<?>, Collection<?>>> filterSelection, FunctionProvider functionProvider) {
private <DataType> Map<Integer, FilterCriterion<?>> createFilterCriteria(Map<Integer, Map<Function<?>, Collection<?>>> filterSelection) {
Map<Integer, CompoundFilterCriterion<?>> criteriaMappedByRetrieverLevel = new HashMap<>();
for (Entry<Integer, Map<Function<?>, Collection<?>>> levelFilterSelection : filterSelection.entrySet()) {
for (Entry<Function<?>, Collection<?>> levelFilterSelectionEntry : levelFilterSelection.getValue().entrySet()) {
Function<?> function = levelFilterSelectionEntry.getKey();
ParameterProvider parameterProvider = functionProvider.getParameterProviderFor(function);
throwExceptionIfParameterProviderIsNull(function, parameterProvider);
ParameterProvider parameterProvider = ParameterProvider.NULL;
Class<DataType> dataType = (Class<DataType>) function.getDeclaringType();
if (!criteriaMappedByRetrieverLevel.containsKey(levelFilterSelection.getKey())) {
@@ -80,23 +113,15 @@ public class QueryFactory {
}
return (Map<Integer, FilterCriterion<?>>)(Map<Integer, ?>) criteriaMappedByRetrieverLevel;
}
private void throwExceptionIfParameterProviderIsNull(Function<?> function, ParameterProvider parameterProvider) {
if (parameterProvider == null) {
throw new NullPointerException("There is no " + ParameterProvider.class.getSimpleName() + " available for the " +
Function.class.getSimpleName() + " '" + function.toString() + "'");
}
}
public <DataSource> Query<Set<Object>> createDimensionValuesQuery(DataSource dataSource,
DataRetrieverChainDefinition<DataSource, ?> dataRetrieverChainDefinition, int retrieverLevel,
Iterable<Function<?>> dimensions, Locale locale,
DataMiningStringMessages stringMessages, ExecutorService executor,
FunctionProvider functionProvider) {
DataMiningStringMessages stringMessages, ExecutorService executor) {
return new ProcessorQuery<Set<Object>, DataSource>(dataSource, stringMessages, locale) {
@Override
protected Processor<DataSource, ?> createFirstProcessor() {
ProcessorFactory processorFactory = new ProcessorFactory(executor, functionProvider);
ProcessorFactory processorFactory = new ProcessorFactory(executor);
Processor<GroupedDataEntry<Object>, Map<GroupKey, Set<Object>>> valueCollector = processorFactory.createGroupedDataCollectingAsSetProcessor(/*query*/ this);
@@ -106,7 +131,7 @@ public class QueryFactory {
chainBuilder.stepFurther();
}
for (Processor<?, ?> resultReceiver : processorFactory.createGroupingExtractorsForDimensions(
chainBuilder.getCurrentRetrievedDataType(), valueCollector, dimensions, stringMessages, locale)) {
chainBuilder.getCurrentRetrievedDataType(), valueCollector, getParameterProvidersFor(dimensions, stringMessages, locale), stringMessages, locale)) {
chainBuilder.addResultReceiver(resultReceiver);
}
@@ -21,7 +21,5 @@ public interface FunctionProvider {
* @return The first function, that matches the given DTO or <code>null</code>
*/
public Function<?> getFunctionForDTO(FunctionDTO functionDTO);
public ParameterProvider getParameterProviderFor(Function<?> function);
}
@@ -6,10 +6,8 @@ public interface FunctionRegistry {
public void registerAllWithInternalFunctionPolicy(Iterable<Class<?>> classesToScan);
public void registerAllWithExternalFunctionPolicy(Iterable<Class<?>> externalClassesToScan);
public void registerParameterProvider(ParameterProvider parameterProvider);
public void unregisterAllFunctionsOf(Iterable<Class<?>> classesToUnregister);
public void unregisterParameterProvider(ParameterProvider parameterProvider);
public Collection<Function<?>> getAllFunctions();
public Collection<Function<?>> getAllFunctionsOf(Class<?> declaringType);
@@ -19,6 +17,5 @@ public interface FunctionRegistry {
public Collection<Function<?>> getDimensionsOf(Class<?> declaringType);
public Collection<Function<?>> getExternalFunctions();
public Collection<Function<?>> getExternalFunctionsOf(Class<?> declaringType);
public Iterable<ParameterProvider> getAllParameterProviders();
}
@@ -6,8 +6,6 @@ public interface ParameterProvider {
public static final ParameterProvider NULL = new NullParameterProvider();
public Iterable<Class<?>> getParameterTypes();
public Object[] getParameters();
@@ -17,9 +17,7 @@ import com.sap.sse.datamining.factories.QueryFactory;
import com.sap.sse.datamining.functions.Function;
import com.sap.sse.datamining.functions.FunctionProvider;
import com.sap.sse.datamining.functions.FunctionRegistry;
import com.sap.sse.datamining.functions.ParameterProvider;
import com.sap.sse.datamining.i18n.DataMiningStringMessages;
import com.sap.sse.datamining.impl.functions.LocalizationParameterProvider;
import com.sap.sse.datamining.impl.i18n.CompoundDataMiningStringMessages;
import com.sap.sse.datamining.shared.QueryDefinitionDTO;
import com.sap.sse.datamining.shared.dto.FunctionDTO;
@@ -43,19 +41,6 @@ public class DataMiningServerImpl implements ModifiableDataMiningServer {
this.functionRegistry = functionRegistry;
this.functionProvider = functionProvider;
this.dataRetrieverChainDefinitionRegistry = dataRetrieverChainDefinitionRegistry;
initializeStringMessagesParameterProvider();
}
private void initializeStringMessagesParameterProvider() {
//TODO enable after improved ParameterProvider handling
// for (Locale locale : DataMiningStringMessages.Util.getSupportedLocales()) {
// ParameterProvider stringMessagesParameterProvider = new LocalizationParameterProvider(locale, getStringMessages());
// registerParameterProvider(stringMessagesParameterProvider);
// }
//TODO remove after improved ParameterProvider handling
ParameterProvider stringMessagesParameterProvider = new LocalizationParameterProvider(Locale.ENGLISH, getStringMessages());
registerParameterProvider(stringMessagesParameterProvider);
}
@Override
@@ -93,20 +78,10 @@ public class DataMiningServerImpl implements ModifiableDataMiningServer {
functionRegistry.registerAllWithExternalFunctionPolicy(externalClassesToScan);
}
@Override
public void registerParameterProvider(ParameterProvider parameterProvider) {
functionRegistry.registerParameterProvider(parameterProvider);
}
@Override
public void unregisterAllFunctionsOf(Iterable<Class<?>> classesToUnregister) {
functionRegistry.unregisterAllFunctionsOf(classesToUnregister);
}
@Override
public void unregisterParameterProvider(ParameterProvider parameterProvider) {
functionRegistry.unregisterParameterProvider(parameterProvider);
}
@Override
public FunctionProvider getFunctionProvider() {
@@ -143,11 +118,6 @@ public class DataMiningServerImpl implements ModifiableDataMiningServer {
return functionProvider.getFunctionForDTO(functionDTO);
}
@Override
public ParameterProvider getParameterProviderFor(Function<?> function) {
return functionProvider.getParameterProviderFor(function);
}
@Override
public DataRetrieverChainDefinitionProvider getDataRetrieverChainDefinitionProvider() {
return dataRetrieverChainDefinitionRegistry;
@@ -215,14 +185,14 @@ public class DataMiningServerImpl implements ModifiableDataMiningServer {
@Override
public <DataSource, DataType, ResultType> Query<ResultType> createQuery(DataSource dataSource, QueryDefinition<DataSource, DataType, ResultType> queryDefinition) {
return queryFactory.createQuery(dataSource, queryDefinition, getStringMessages(), getExecutorService(), getFunctionProvider());
return queryFactory.createQuery(dataSource, queryDefinition, getStringMessages(), getExecutorService());
}
@Override
public <DataSource> Query<Set<Object>> createDimensionValuesQuery(DataSource dataSource,
DataRetrieverChainDefinition<DataSource, ?> dataRetrieverChainDefinition, int retrieverLevel,
Iterable<Function<?>> dimensions, Locale locale) {
return queryFactory.createDimensionValuesQuery(dataSource, dataRetrieverChainDefinition, retrieverLevel, dimensions, locale, getStringMessages(), getExecutorService(), getFunctionProvider());
return queryFactory.createDimensionValuesQuery(dataSource, dataRetrieverChainDefinition, retrieverLevel, dimensions, locale, getStringMessages(), getExecutorService());
}
}
@@ -6,11 +6,10 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -21,7 +20,6 @@ import com.sap.sse.datamining.factories.FunctionFactory;
import com.sap.sse.datamining.functions.Function;
import com.sap.sse.datamining.functions.FunctionProvider;
import com.sap.sse.datamining.functions.FunctionRegistry;
import com.sap.sse.datamining.functions.ParameterProvider;
import com.sap.sse.datamining.impl.DataRetrieverTypeWithInformation;
import com.sap.sse.datamining.impl.functions.criterias.FunctionMatchesDTOFilterCriterion;
import com.sap.sse.datamining.impl.functions.criterias.MethodIsValidConnectorFilterCriterion;
@@ -71,8 +69,6 @@ public class FunctionManager implements FunctionRegistry, FunctionProvider {
private final Map<Class<?>, Set<Function<?>>> externalFunctions;
private final Collection<Map<Class<?>, Set<Function<?>>>> functionMaps;
private final Collection<ParameterProvider> parameterProviders;
public FunctionManager() {
functionDTOFactory = new FunctionDTOFactory();
@@ -86,8 +82,6 @@ public class FunctionManager implements FunctionRegistry, FunctionProvider {
functionMaps.add(statistics);
functionMaps.add(dimensions);
functionMaps.add(externalFunctions);
parameterProviders = new HashSet<>();
}
@Override
@@ -170,11 +164,6 @@ public class FunctionManager implements FunctionRegistry, FunctionProvider {
}
externalFunctions.get(declaringType).add(function);
}
@Override
public void registerParameterProvider(ParameterProvider parameterProvider) {
parameterProviders.add(parameterProvider);
}
@Override
public void unregisterAllFunctionsOf(Iterable<Class<?>> classesToUnregister) {
@@ -188,11 +177,6 @@ public class FunctionManager implements FunctionRegistry, FunctionProvider {
functionMap.remove(classToUnregister);
}
}
@Override
public void unregisterParameterProvider(ParameterProvider parameterProvider) {
parameterProviders.remove(parameterProvider);
}
@Override
public Collection<Function<?>> getAllFunctions() {
@@ -253,11 +237,6 @@ public class FunctionManager implements FunctionRegistry, FunctionProvider {
return set;
}
@Override
public Iterable<ParameterProvider> getAllParameterProviders() {
return parameterProviders;
}
@Override
public Collection<Function<?>> getAllStatistics() {
return getStatistics();
@@ -381,40 +360,5 @@ public class FunctionManager implements FunctionRegistry, FunctionProvider {
private Function<?> getFunctionToReturn(Collection<Function<?>> functionsMatchingDTO) {
return functionsMatchingDTO.isEmpty() ? null : functionsMatchingDTO.iterator().next();
}
@Override
public ParameterProvider getParameterProviderFor(Function<?> function) {
Iterable<Class<?>> functionParameterTypes = function.getParameters();
if (!functionParameterTypes.iterator().hasNext()) {
return ParameterProvider.NULL;
}
for (ParameterProvider parameterProvider : getAllParameterProviders()) {
if (parametersAreMatching(function, parameterProvider)) {
return parameterProvider;
}
}
return null;
}
private boolean parametersAreMatching(Function<?> function, ParameterProvider parameterProvider) {
Iterator<Class<?>> functionParametersIterator = function.getParameters().iterator();
Iterator<Class<?>> parameterProviderIterator = parameterProvider.getParameterTypes().iterator();
while (functionParametersIterator.hasNext() && parameterProviderIterator.hasNext()) {
Class<?> functionParameter = functionParametersIterator.next();
Class<?> parameterProviderParameter = parameterProviderIterator.next();
if (!functionParameter.isAssignableFrom(parameterProviderParameter)) {
return false;
}
}
if (functionParametersIterator.hasNext() || parameterProviderIterator.hasNext()) {
return false;
}
return true;
}
}
@@ -1,7 +1,5 @@
package com.sap.sse.datamining.impl.functions;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Locale;
import com.sap.sse.datamining.i18n.DataMiningStringMessages;
@@ -9,14 +7,7 @@ import com.sap.sse.datamining.i18n.DataMiningStringMessages;
public class LocalizationParameterProvider extends SimpleParameterProvider {
public LocalizationParameterProvider(Locale locale, DataMiningStringMessages stringMessages) {
super(createParameterTypes(), new Object[] {locale, stringMessages});
}
private static Iterable<Class<?>> createParameterTypes() {
Collection<Class<?>> parameterTypes = new ArrayList<>();
parameterTypes.add(Locale.class);
parameterTypes.add(DataMiningStringMessages.class);
return parameterTypes;
super(new Object[] {locale, stringMessages});
}
}
@@ -1,11 +1,10 @@
package com.sap.sse.datamining.impl.functions;
import java.util.Collections;
public class NullParameterProvider extends SimpleParameterProvider {
public NullParameterProvider() {
super(Collections.emptyList(), new Object[0]);
super(new Object[0]);
}
}
@@ -4,47 +4,15 @@ import com.sap.sse.datamining.functions.ParameterProvider;
public class SimpleParameterProvider implements ParameterProvider {
private final Iterable<Class<?>> parameterTypes;
private final Object[] parameters;
public SimpleParameterProvider(Iterable<Class<?>> parameterTypes, Object[] parameters) {
this.parameterTypes = parameterTypes;
public SimpleParameterProvider(Object[] parameters) {
this.parameters = parameters;
}
@Override
public Iterable<Class<?>> getParameterTypes() {
return parameterTypes;
}
@Override
public Object[] getParameters() {
return parameters;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((parameterTypes == null) ? 0 : parameterTypes.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
SimpleParameterProvider other = (SimpleParameterProvider) obj;
if (parameterTypes == null) {
if (other.parameterTypes != null)
return false;
} else if (!parameterTypes.equals(other.parameterTypes))
return false;
return true;
}
}