First attempt for correct transitive annotation handling

This commit is contained in:
Lennart Hensler committed 2014-06-05 17:56:08 +02:00
1 parent 9ca4744652
commit a3b29e6e0f
30 files changed
+469 -251

No files matched your search

@@ -45,7 +45,7 @@ public class TestSailingFunctionsRegistration {
public void testImportantRegisteredFunctions() { public void testImportantRegisteredFunctions() {
// This tests for the methods marked as SideEffectFreeValue, that will be used for the data extraction // This tests for the methods marked as SideEffectFreeValue, that will be used for the data extraction
Function<?>[] expectedFunctions = createExpectedImportantRegisteredFunctions(); Function<?>[] expectedFunctions = createExpectedImportantRegisteredFunctions();
assertThat(functionRegistry.getAllFunctions(), hasItems(expectedFunctions)); assertThat(functionRegistry.getAllStatistics(), hasItems(expectedFunctions));
} }
private Function<?>[] createExpectedImportantRegisteredFunctions() { private Function<?>[] createExpectedImportantRegisteredFunctions() {
@@ -28,7 +28,6 @@ import com.sap.sse.datamining.test.functions.test_classes.ExtendingInterface;
import com.sap.sse.datamining.test.functions.test_classes.ExternalLibraryClass; import com.sap.sse.datamining.test.functions.test_classes.ExternalLibraryClass;
import com.sap.sse.datamining.test.functions.test_classes.MarkedContainer; import com.sap.sse.datamining.test.functions.test_classes.MarkedContainer;
import com.sap.sse.datamining.test.functions.test_classes.SimpleClassWithMarkedMethods; import com.sap.sse.datamining.test.functions.test_classes.SimpleClassWithMarkedMethods;
import com.sap.sse.datamining.test.util.ConcurrencyTestsUtil;
import com.sap.sse.datamining.test.util.FunctionTestsUtil; import com.sap.sse.datamining.test.util.FunctionTestsUtil;
import com.sap.sse.datamining.test.util.TestsUtil; import com.sap.sse.datamining.test.util.TestsUtil;
@@ -40,7 +39,7 @@ public class TestFunctionProvider {
@Before @Before
public void initializeFunctionRegistry() { public void initializeFunctionRegistry() {
functionRegistry = new SimpleFunctionRegistry(ConcurrencyTestsUtil.getExecutor()); functionRegistry = new SimpleFunctionRegistry();
Collection<Class<?>> internalClassesToScan = new HashSet<>(); Collection<Class<?>> internalClassesToScan = new HashSet<>();
internalClassesToScan.add(SimpleClassWithMarkedMethods.class); internalClassesToScan.add(SimpleClassWithMarkedMethods.class);
@@ -1,47 +0,0 @@
package com.sap.sse.datamining.impl.functions;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import java.util.Collection;
import java.util.HashSet;
import org.junit.Before;
import org.junit.Test;
import com.sap.sse.datamining.functions.Function;
import com.sap.sse.datamining.functions.FunctionRegistry;
import com.sap.sse.datamining.impl.functions.SimpleFunctionRegistry;
import com.sap.sse.datamining.test.functions.test_classes.DataTypeWithContext;
import com.sap.sse.datamining.test.functions.test_classes.ExternalLibraryClass;
import com.sap.sse.datamining.test.functions.test_classes.SimpleClassWithMarkedMethods;
import com.sap.sse.datamining.test.util.ConcurrencyTestsUtil;
import com.sap.sse.datamining.test.util.FunctionTestsUtil;
public class TestSimpleFunctionRegistryAccess {
private FunctionRegistry functionRegistry;
@Before
public void initializeTheFunctionRegistry() {
functionRegistry = new SimpleFunctionRegistry(ConcurrencyTestsUtil.getExecutor());
Collection<Class<?>> internalClassesToScan = new HashSet<>();
internalClassesToScan.add(SimpleClassWithMarkedMethods.class);
internalClassesToScan.add(DataTypeWithContext.class);
functionRegistry.registerAllWithInternalFunctionPolicy(internalClassesToScan);
Collection<Class<?>> externalClassesToScan = new HashSet<>();
externalClassesToScan.add(ExternalLibraryClass.class);
functionRegistry.registerAllWithExternalFunctionPolicy(externalClassesToScan);
}
@Test
public void testGetAllDimensions() {
Collection<Function<?>> modifiableExpectedDimensions = FunctionTestsUtil.getDimensionsFor(DataTypeWithContext.class);
modifiableExpectedDimensions.addAll(FunctionTestsUtil.getDimensionsFor(SimpleClassWithMarkedMethods.class));
Collection<Function<?>> expectedDimensions = modifiableExpectedDimensions;
assertThat(functionRegistry.getAllDimensions(), is(expectedDimensions));
}
}
@@ -4,72 +4,97 @@ import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import com.sap.sse.datamining.factories.FunctionFactory; import com.sap.sse.datamining.factories.FunctionFactory;
import com.sap.sse.datamining.functions.Function; import com.sap.sse.datamining.functions.Function;
import com.sap.sse.datamining.functions.FunctionRegistry; import com.sap.sse.datamining.functions.FunctionRegistry;
import com.sap.sse.datamining.impl.functions.SimpleFunctionRegistry; import com.sap.sse.datamining.test.functions.registry.test_classes.Test_Boat;
import com.sap.sse.datamining.test.functions.test_classes.ExternalLibraryClass; import com.sap.sse.datamining.test.functions.registry.test_classes.Test_Competitor;
import com.sap.sse.datamining.test.functions.test_classes.SimpleClassWithMarkedMethods; import com.sap.sse.datamining.test.functions.registry.test_classes.Test_Leg;
import com.sap.sse.datamining.test.util.ConcurrencyTestsUtil; import com.sap.sse.datamining.test.functions.registry.test_classes.Test_Named;
import com.sap.sse.datamining.test.util.FunctionTestsUtil; import com.sap.sse.datamining.test.functions.registry.test_contexts.Test_HasLegContext;
import com.sap.sse.datamining.test.functions.registry.test_contexts.Test_HasRaceContext;
public class TestSimpleFunctionRegistryRegistrations { public class TestSimpleFunctionRegistryRegistrations {
@Test private Set<Class<?>> internalClassesToScan;
public void testSimpleRegistration() {
Method dimension = FunctionTestsUtil.getMethodFromSimpleClassWithMarkedMethod("dimension"); @Before
public void initializeClassesToScan() {
FunctionRegistry registry = new SimpleFunctionRegistry(ConcurrencyTestsUtil.getExecutor()); internalClassesToScan = new HashSet<>();
registry.register(dimension); internalClassesToScan.add(Test_HasLegContext.class);
internalClassesToScan.add(Test_HasRaceContext.class);
Set<Function<?>> expectedRegisteredFunctionsAsSet = new HashSet<>();
expectedRegisteredFunctionsAsSet.add(FunctionFactory.createMethodWrappingFunction(dimension));
Iterable<Function<?>> expectedRegisteredFunctions = expectedRegisteredFunctionsAsSet;
assertThat(registry.getAllFunctions(), is(expectedRegisteredFunctions));
assertThat(registry.getFunctionsOf(SimpleClassWithMarkedMethods.class), is(expectedRegisteredFunctions));
} }
@Test @Test
public void testRegistrationByFunctionRetrievers() { public void testRegistration() throws NoSuchMethodException, SecurityException {
FunctionRegistry registry = new SimpleFunctionRegistry(ConcurrencyTestsUtil.getExecutor()); FunctionRegistry registry = new SimpleFunctionRegistry();
registerMethodsOfTestClasses(registry);
Set<Function<?>> expectedRegisteredFunctionsAsSet = new HashSet<>();
expectedRegisteredFunctionsAsSet.addAll(FunctionTestsUtil.getMarkedMethodsOfSimpleClassWithMarkedMethod());
expectedRegisteredFunctionsAsSet.addAll(FunctionTestsUtil.getMethodsOfExternalLibraryClass());
Iterable<Function<?>> expectedRegisteredFunctions = expectedRegisteredFunctionsAsSet;
assertThat(registry.getAllFunctions(), is(expectedRegisteredFunctions));
}
private void registerMethodsOfTestClasses(FunctionRegistry registry) {
Collection<Class<?>> internalClassesToScan = new HashSet<>();
internalClassesToScan.add(SimpleClassWithMarkedMethods.class);
registry.registerAllWithInternalFunctionPolicy(internalClassesToScan); registry.registerAllWithInternalFunctionPolicy(internalClassesToScan);
Collection<Class<?>> externalClassesToScan = new HashSet<>(); Collection<Function<?>> expectedDimensions = createExpectedDimensions();
externalClassesToScan.add(ExternalLibraryClass.class); assertThat(registry.getAllDimensions(), is(expectedDimensions));
registry.registerAllWithExternalFunctionPolicy(externalClassesToScan);
Collection<Function<?>> expectedStatistics = createExpectedStatistics();
assertThat(registry.getAllStatistics(), is(expectedStatistics));
} }
@Test private Collection<Function<?>> createExpectedDimensions() throws NoSuchMethodException, SecurityException {
public void testTheMultipleRegistrationOfTheSameFunction() { Collection<Function<?>> dimensions = new HashSet<>();
Method dimension = FunctionTestsUtil.getMethodFromSimpleClassWithMarkedMethod("dimension");
FunctionRegistry registry = new SimpleFunctionRegistry(ConcurrencyTestsUtil.getExecutor()); Method getNameMethod = Test_Named.class.getMethod("getName", new Class<?>[0]);
registry.register(dimension); Function<?> getName = FunctionFactory.createMethodWrappingFunction(getNameMethod);
registry.register(dimension);
registry.register(dimension);
Set<Function<?>> expectedRegisteredFunctionsAsSet = new HashSet<>(); Method getRegattaMethod = Test_HasRaceContext.class.getMethod("getRegatta", new Class<?>[0]);
expectedRegisteredFunctionsAsSet.add(FunctionFactory.createMethodWrappingFunction(dimension)); Function<?> getRegatta = FunctionFactory.createMethodWrappingFunction(getRegattaMethod);
Iterable<Function<?>> expectedRegisteredFunctions = expectedRegisteredFunctionsAsSet; dimensions.add(FunctionFactory.createCompoundFunction(null, Arrays.asList(getRegatta, getName)));
assertThat(registry.getAllFunctions(), is(expectedRegisteredFunctions));
Method getRaceMethod = Test_HasRaceContext.class.getMethod("getRace", new Class<?>[0]);
Function<?> getRace = FunctionFactory.createMethodWrappingFunction(getRaceMethod);
dimensions.add(FunctionFactory.createCompoundFunction(null, Arrays.asList(getRace, getName)));
Method getBoatClassMethod = Test_HasRaceContext.class.getMethod("getBoatClass", new Class<?>[0]);
Function<?> getBoatClass = FunctionFactory.createMethodWrappingFunction(getBoatClassMethod);
dimensions.add(FunctionFactory.createCompoundFunction(null, Arrays.asList(getBoatClass, getName)));
Method getYearMethod = Test_HasRaceContext.class.getMethod("getYear", new Class<?>[0]);
dimensions.add(FunctionFactory.createMethodWrappingFunction(getYearMethod));
Method getLegNumberMethod = Test_HasLegContext.class.getMethod("getLegNumber", new Class<?>[0]);
dimensions.add(FunctionFactory.createMethodWrappingFunction(getLegNumberMethod));
Method getCompetitorMethod = Test_HasLegContext.class.getMethod("getCompetitor", new Class<?>[0]);
Function<?> getCompetitor = FunctionFactory.createMethodWrappingFunction(getCompetitorMethod);
Method getTeamMethod = Test_Competitor.class.getMethod("getTeam", new Class<?>[0]);
Function<?> getTeam = FunctionFactory.createMethodWrappingFunction(getTeamMethod);
dimensions.add(FunctionFactory.createCompoundFunction(null, Arrays.asList(getCompetitor, getTeam, getName)));
Method getBoatMethod = Test_Competitor.class.getMethod("getBoat", new Class<?>[0]);
Function<?> getBoat = FunctionFactory.createMethodWrappingFunction(getBoatMethod);
Method getSailIDMethod = Test_Boat.class.getMethod("getSailID", new Class<?>[0]);
Function<?> getSailID = FunctionFactory.createMethodWrappingFunction(getSailIDMethod);
dimensions.add(FunctionFactory.createCompoundFunction(null, Arrays.asList(getCompetitor, getBoat, getSailID)));
return dimensions;
}
private Collection<Function<?>> createExpectedStatistics() throws NoSuchMethodException, SecurityException {
Method getLegMethod = Test_HasLegContext.class.getMethod("getLeg", new Class<?>[0]);
Function<?> getLeg = FunctionFactory.createMethodWrappingFunction(getLegMethod);
Method getDistanceTraveledMethod = Test_Leg.class.getMethod("getDistanceTraveled", new Class<?>[0]);
Function<?> getDistanceTraveled = FunctionFactory.createMethodWrappingFunction(getDistanceTraveledMethod);
Collection<Function<?>> statistics = new HashSet<>();
statistics.add(FunctionFactory.createCompoundFunction("getDistanceTraveled", Arrays.asList(getLeg, getDistanceTraveled)));
return statistics;
} }
} }
@@ -0,0 +1,10 @@
package com.sap.sse.datamining.test.functions.registry.test_classes;
import com.sap.sse.datamining.shared.annotations.Dimension;
public interface Test_Boat {
@Dimension(messageKey="SailID")
public String getSailID();
}
@@ -0,0 +1,5 @@
package com.sap.sse.datamining.test.functions.registry.test_classes;
public interface Test_BoatClass extends Test_Named {
}
@@ -0,0 +1,13 @@
package com.sap.sse.datamining.test.functions.registry.test_classes;
import com.sap.sse.datamining.shared.annotations.Connector;
public interface Test_Competitor {
@Connector
public Test_Team getTeam();
@Connector
public Test_Boat getBoat();
}
@@ -0,0 +1,11 @@
package com.sap.sse.datamining.test.functions.registry.test_classes;
import com.sap.sse.datamining.shared.Unit;
import com.sap.sse.datamining.shared.annotations.Statistic;
public interface Test_Leg {
@Statistic(messageKey="DistanceTraveled", resultUnit=Unit.Meters, resultDecimals=0)
public double getDistanceTraveled();
}
@@ -0,0 +1,10 @@
package com.sap.sse.datamining.test.functions.registry.test_classes;
import com.sap.sse.datamining.shared.annotations.Dimension;
public interface Test_Named {
@Dimension(messageKey="Name")
public String getName();
}
@@ -0,0 +1,5 @@
package com.sap.sse.datamining.test.functions.registry.test_classes;
public interface Test_Race extends Test_Named {
}
@@ -0,0 +1,5 @@
package com.sap.sse.datamining.test.functions.registry.test_classes;
public interface Test_Regatta extends Test_Named {
}
@@ -0,0 +1,5 @@
package com.sap.sse.datamining.test.functions.registry.test_classes;
public interface Test_Team extends Test_Named {
}
@@ -0,0 +1,11 @@
package com.sap.sse.datamining.test.functions.registry.test_classes.impl;
import com.sap.sse.datamining.test.functions.registry.test_classes.Test_BoatClass;
public class Test_BoatClassImpl extends Test_NamedImpl implements Test_BoatClass {
public Test_BoatClassImpl(String name) {
super(name);
}
}
@@ -0,0 +1,18 @@
package com.sap.sse.datamining.test.functions.registry.test_classes.impl;
import com.sap.sse.datamining.test.functions.registry.test_classes.Test_Boat;
public class Test_BoatImpl implements Test_Boat {
private String sailID;
public Test_BoatImpl(String sailID) {
this.sailID = sailID;
}
@Override
public String getSailID() {
return sailID;
}
}
@@ -0,0 +1,27 @@
package com.sap.sse.datamining.test.functions.registry.test_classes.impl;
import com.sap.sse.datamining.test.functions.registry.test_classes.Test_Boat;
import com.sap.sse.datamining.test.functions.registry.test_classes.Test_Competitor;
import com.sap.sse.datamining.test.functions.registry.test_classes.Test_Team;
public class Test_CompetitorImpl implements Test_Competitor {
private Test_Team team;
private Test_Boat boat;
public Test_CompetitorImpl(Test_Team team, Test_Boat boat) {
this.team = team;
this.boat = boat;
}
@Override
public Test_Team getTeam() {
return team;
}
@Override
public Test_Boat getBoat() {
return boat;
}
}
@@ -0,0 +1,18 @@
package com.sap.sse.datamining.test.functions.registry.test_classes.impl;
import com.sap.sse.datamining.test.functions.registry.test_classes.Test_Leg;
public class Test_LegImpl implements Test_Leg {
private double distanceTraveled;
public Test_LegImpl(double distanceTraveled) {
this.distanceTraveled = distanceTraveled;
}
@Override
public double getDistanceTraveled() {
return distanceTraveled;
}
}
@@ -0,0 +1,18 @@
package com.sap.sse.datamining.test.functions.registry.test_classes.impl;
import com.sap.sse.datamining.test.functions.registry.test_classes.Test_Named;
public abstract class Test_NamedImpl implements Test_Named {
private String name;
public Test_NamedImpl(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
}
@@ -0,0 +1,11 @@
package com.sap.sse.datamining.test.functions.registry.test_classes.impl;
import com.sap.sse.datamining.test.functions.registry.test_classes.Test_Race;
public class Test_RaceImpl extends Test_NamedImpl implements Test_Race {
public Test_RaceImpl(String name) {
super(name);
}
}
@@ -0,0 +1,11 @@
package com.sap.sse.datamining.test.functions.registry.test_classes.impl;
import com.sap.sse.datamining.test.functions.registry.test_classes.Test_Regatta;
public class Test_RegattaImpl extends Test_NamedImpl implements Test_Regatta {
public Test_RegattaImpl(String name) {
super(name);
}
}
@@ -0,0 +1,11 @@
package com.sap.sse.datamining.test.functions.registry.test_classes.impl;
import com.sap.sse.datamining.test.functions.registry.test_classes.Test_Team;
public class Test_TeamImpl extends Test_NamedImpl implements Test_Team {
public Test_TeamImpl(String name) {
super(name);
}
}
@@ -0,0 +1,19 @@
package com.sap.sse.datamining.test.functions.registry.test_contexts;
import com.sap.sse.datamining.shared.annotations.Connector;
import com.sap.sse.datamining.shared.annotations.Dimension;
import com.sap.sse.datamining.test.functions.registry.test_classes.Test_Competitor;
import com.sap.sse.datamining.test.functions.registry.test_classes.Test_Leg;
public interface Test_HasLegContext extends Test_HasRaceContext {
@Connector
public Test_Leg getLeg();
@Dimension(messageKey="LegNumber")
public int getLegNumber();
@Connector
public Test_Competitor getCompetitor();
}
@@ -0,0 +1,38 @@
package com.sap.sse.datamining.test.functions.registry.test_contexts;
import com.sap.sse.datamining.test.functions.registry.test_classes.Test_BoatClass;
import com.sap.sse.datamining.test.functions.registry.test_classes.Test_Competitor;
import com.sap.sse.datamining.test.functions.registry.test_classes.Test_Leg;
import com.sap.sse.datamining.test.functions.registry.test_classes.Test_Race;
import com.sap.sse.datamining.test.functions.registry.test_classes.Test_Regatta;
public class Test_HasLegContextImpl extends Test_HasRaceContextImpl implements Test_HasLegContext {
private Test_Leg leg;
private int legNumber;
private Test_Competitor competitor;
public Test_HasLegContextImpl(Test_Regatta regatta, Test_Race race, Test_BoatClass boatClass, int year,
Test_Leg leg, int legNumber, Test_Competitor competitor) {
super(regatta, race, boatClass, year);
this.leg = leg;
this.legNumber = legNumber;
this.competitor = competitor;
}
@Override
public Test_Leg getLeg() {
return leg;
}
@Override
public int getLegNumber() {
return legNumber;
}
@Override
public Test_Competitor getCompetitor() {
return competitor;
}
}
@@ -0,0 +1,23 @@
package com.sap.sse.datamining.test.functions.registry.test_contexts;
import com.sap.sse.datamining.shared.annotations.Connector;
import com.sap.sse.datamining.shared.annotations.Dimension;
import com.sap.sse.datamining.test.functions.registry.test_classes.Test_BoatClass;
import com.sap.sse.datamining.test.functions.registry.test_classes.Test_Race;
import com.sap.sse.datamining.test.functions.registry.test_classes.Test_Regatta;
public interface Test_HasRaceContext {
@Connector
public Test_Regatta getRegatta();
@Connector
public Test_Race getRace();
@Connector
public Test_BoatClass getBoatClass();
@Dimension(messageKey="Year")
public int getYear();
}
@@ -0,0 +1,41 @@
package com.sap.sse.datamining.test.functions.registry.test_contexts;
import com.sap.sse.datamining.test.functions.registry.test_classes.Test_BoatClass;
import com.sap.sse.datamining.test.functions.registry.test_classes.Test_Race;
import com.sap.sse.datamining.test.functions.registry.test_classes.Test_Regatta;
public class Test_HasRaceContextImpl implements Test_HasRaceContext {
private Test_Regatta regatta;
private Test_Race race;
private Test_BoatClass boatClass;
private int year;
public Test_HasRaceContextImpl(Test_Regatta regatta, Test_Race race, Test_BoatClass boatClass, int year) {
this.regatta = regatta;
this.race = race;
this.boatClass = boatClass;
this.year = year;
}
@Override
public Test_Regatta getRegatta() {
return regatta;
}
@Override
public Test_Race getRace() {
return race;
}
@Override
public Test_BoatClass getBoatClass() {
return boatClass;
}
@Override
public int getYear() {
return year;
}
}
@@ -1,6 +1,7 @@
package com.sap.sse.datamining.factories; package com.sap.sse.datamining.factories;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
@@ -18,7 +19,7 @@ public class FunctionFactory {
private FunctionFactory() { } private FunctionFactory() { }
public static FunctionRegistry createFunctionRegistry(ExecutorService executor) { public static FunctionRegistry createFunctionRegistry(ExecutorService executor) {
return new SimpleFunctionRegistry(executor); return new SimpleFunctionRegistry();
} }
public static FunctionProvider createRegistryFunctionProvider(FunctionRegistry... functionRegistries) { public static FunctionProvider createRegistryFunctionProvider(FunctionRegistry... functionRegistries) {
@@ -51,4 +52,11 @@ public class FunctionFactory {
return new CompoundFunction<ReturnType>(name, functions, (Class<ReturnType>) functions.get(functions.size() - 1).getReturnType()); return new CompoundFunction<ReturnType>(name, functions, (Class<ReturnType>) functions.get(functions.size() - 1).getReturnType());
} }
public static Function<?> createCompoundFunction(String name, List<Function<?>> previousFunctions,
Function<?> lastFunction) {
List<Function<?>> functions = new ArrayList<>(previousFunctions);
functions.add(lastFunction);
return createCompoundFunction(name, functions);
}
} }
@@ -1,19 +1,13 @@
package com.sap.sse.datamining.functions; package com.sap.sse.datamining.functions;
import java.lang.reflect.Method;
import java.util.Collection; import java.util.Collection;
public interface FunctionRegistry { public interface FunctionRegistry {
public void register(Method method);
public void register(Function<?> function);
public void registerAll(Iterable<Function<?>> functions);
public void registerAllWithInternalFunctionPolicy(Collection<Class<?>> classesToScan); public void registerAllWithInternalFunctionPolicy(Collection<Class<?>> classesToScan);
public void registerAllWithExternalFunctionPolicy(Collection<Class<?>> externalClassesToScan); public void registerAllWithExternalFunctionPolicy(Collection<Class<?>> externalClassesToScan);
public Collection<Function<?>> getAllFunctions(); public Collection<Function<?>> getAllStatistics();
public Collection<Function<?>> getFunctionsOf(Class<?> declaringClass);
public Collection<Function<?>> getAllDimensions(); public Collection<Function<?>> getAllDimensions();
public Collection<Function<?>> getDimensionsOf(Class<?> declaringClass);
} }
@@ -79,7 +79,7 @@ public class DataMiningActivator implements BundleActivator {
} }
private FunctionRegistry createAndBuildFunctionRegistry() { private FunctionRegistry createAndBuildFunctionRegistry() {
FunctionRegistry functionRegistry = new SimpleFunctionRegistry(getExecutor()); FunctionRegistry functionRegistry = new SimpleFunctionRegistry();
Set<Class<?>> internalClassesWithMarkedMethods = new HashSet<>(); Set<Class<?>> internalClassesWithMarkedMethods = new HashSet<>();
Set<Class<?>> externalLibraryClasses = new HashSet<>(); Set<Class<?>> externalLibraryClasses = new HashSet<>();
@@ -127,6 +127,11 @@ public class CompoundFunction<ReturnType> extends AbstractFunction<ReturnType> {
private Function<?> getLastFunction() { private Function<?> getLastFunction() {
return functions.get(functions.size() - 1); return functions.get(functions.size() - 1);
} }
@Override
public String toString() {
return getSimpleName();
}
@Override @Override
public int hashCode() { public int hashCode() {
@@ -65,7 +65,8 @@ public class RegistryFunctionProvider implements FunctionProvider {
Collection<Function<?>> dimensions = new HashSet<>(); Collection<Function<?>> dimensions = new HashSet<>();
for (FunctionRegistry functionRegistry : functionRegistries) { for (FunctionRegistry functionRegistry : functionRegistries) {
for (Class<?> typeToRetrieve : typesToRetrieve) { for (Class<?> typeToRetrieve : typesToRetrieve) {
dimensions.addAll(functionRegistry.getDimensionsOf(typeToRetrieve)); // dimensions.addAll(functionRegistry.getDimensionsOf(typeToRetrieve));
//TODO after the registry works transitive
} }
} }
return dimensions; return dimensions;
@@ -82,7 +83,8 @@ public class RegistryFunctionProvider implements FunctionProvider {
Collection<Function<?>> dimensions = new HashSet<>(); Collection<Function<?>> dimensions = new HashSet<>();
for (FunctionRegistry functionRegistry : functionRegistries) { for (FunctionRegistry functionRegistry : functionRegistries) {
for (Class<?> typeToRetrieve : typesToRetrieve) { for (Class<?> typeToRetrieve : typesToRetrieve) {
dimensions.addAll(functionRegistry.getFunctionsOf(typeToRetrieve)); // dimensions.addAll(functionRegistry.getStatisticsOf(typeToRetrieve));
//TODO after the registry works transitive
} }
} }
return dimensions; return dimensions;
@@ -144,7 +146,7 @@ public class RegistryFunctionProvider implements FunctionProvider {
Collection<Function<?>> functionsMatchingDTO = new HashSet<>(); Collection<Function<?>> functionsMatchingDTO = new HashSet<>();
FilterCriteria<Function<?>> functionDTOFilterCriteria = new FunctionMatchesDTOFilterCriteria(functionDTO); FilterCriteria<Function<?>> functionDTOFilterCriteria = new FunctionMatchesDTOFilterCriteria(functionDTO);
for (FunctionRegistry functionRegistry : functionRegistries) { for (FunctionRegistry functionRegistry : functionRegistries) {
for (Function<?> function : functionRegistry.getAllFunctions()) { for (Function<?> function : functionRegistry.getAllStatistics()) {
if (functionDTOFilterCriteria.matches(function)) { if (functionDTOFilterCriteria.matches(function)) {
functionsMatchingDTO.add(function); functionsMatchingDTO.add(function);
} }
@@ -2,176 +2,98 @@ package com.sap.sse.datamining.impl.functions;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.sap.sse.datamining.AdditionalResultDataBuilder;
import com.sap.sse.datamining.components.Processor;
import com.sap.sse.datamining.factories.FunctionFactory; import com.sap.sse.datamining.factories.FunctionFactory;
import com.sap.sse.datamining.functions.Function; import com.sap.sse.datamining.functions.Function;
import com.sap.sse.datamining.functions.FunctionRegistry; import com.sap.sse.datamining.functions.FunctionRegistry;
import com.sap.sse.datamining.functions.FunctionRetrievalProcessor; import com.sap.sse.datamining.shared.annotations.Connector;
import com.sap.sse.datamining.impl.functions.components.ExternalFunctionRetrievalProcessor; import com.sap.sse.datamining.shared.annotations.Dimension;
import com.sap.sse.datamining.impl.functions.components.InternalFunctionRetrievalProcessor; import com.sap.sse.datamining.shared.annotations.Statistic;
public class SimpleFunctionRegistry implements FunctionRegistry { public class SimpleFunctionRegistry implements FunctionRegistry {
private static final Logger LOGGER = Logger.getLogger(SimpleFunctionRegistry.class.getName()); private final Set<Function<?>> statistics;
private final Set<Function<?>> dimensions;
private final ExecutorService executor; public SimpleFunctionRegistry() {
private final Processor<Collection<Function<?>>> functionsReceiver; statistics = new HashSet<>();
dimensions = new HashSet<>();
private final Map<Class<?>, Collection<Function<?>>> functionsMappedByDeclaringClass;
private final Map<Class<?>, Collection<Function<?>>> dimensionsMappedByDeclaringClass;
public SimpleFunctionRegistry(ExecutorService executor) {
this.executor = executor;
functionsReceiver = new FunctionsReceiver();
functionsMappedByDeclaringClass = new HashMap<>();
dimensionsMappedByDeclaringClass = new HashMap<>();
} }
@Override @Override
public void registerAllWithInternalFunctionPolicy(Collection<Class<?>> internalClassesToScan) { public void registerAllWithInternalFunctionPolicy(Collection<Class<?>> internalClassesToScan) {
FunctionRetrievalProcessor internalFunctionsRetriever = new InternalFunctionRetrievalProcessor(executor, Arrays.asList(functionsReceiver)); for (Class<?> internalClass : internalClassesToScan) {
internalFunctionsRetriever.onElement(internalClassesToScan); scanInternalClass(internalClass);
try { }
internalFunctionsRetriever.finish(); }
} catch (InterruptedException exception) {
LOGGER.log(Level.SEVERE, "The functions retrieval got interrupted. Data-Mining won't work!", exception); private void scanInternalClass(Class<?> internalClass) {
scanInternalClass(internalClass, new ArrayList<Function<?>>());
}
private void scanInternalClass(Class<?> internalClass, List<Function<?>> previousFunctions) {
for (Method method : internalClass.getMethods()) {
Function<?> function = FunctionFactory.createMethodWrappingFunction(method);
if (isValidDimension(method) || isValidStatistic(method)) {
if (!previousFunctions.isEmpty()) {
function = FunctionFactory.createCompoundFunction(null, previousFunctions, function);
}
registerInternalFunction(function);
continue;
}
if (isConnector(method)) {
Class<?> returnType = method.getReturnType();
List<Function<?>> previousFunctionsClone = new ArrayList<>(previousFunctions);
previousFunctions.add(function);
scanInternalClass(returnType, previousFunctionsClone);
continue;
}
}
}
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;
}
private void registerInternalFunction(Function<?> function) {
if (function.isDimension()) {
dimensions.add(function);
} else {
statistics.add(function);
} }
} }
@Override @Override
public void registerAllWithExternalFunctionPolicy(Collection<Class<?>> externalClassesToScan) { public void registerAllWithExternalFunctionPolicy(Collection<Class<?>> externalClassesToScan) {
FunctionRetrievalProcessor externalFunctionsRetriever = new ExternalFunctionRetrievalProcessor(executor, Arrays.asList(functionsReceiver)); // TODO Not yet implemented
externalFunctionsRetriever.onElement(externalClassesToScan);
try {
externalFunctionsRetriever.finish();
} catch (InterruptedException exception) {
LOGGER.log(Level.SEVERE, "The functions retrieval got interrupted. Data-Mining won't work!", exception);
}
} }
@Override @Override
public void registerAll(Iterable<Function<?>> functions) { public Collection<Function<?>> getAllStatistics() {
for (Function<?> function : functions) { return statistics;
register(function);
}
}
@Override
public void register(Method method) {
register(FunctionFactory.createMethodWrappingFunction(method));
}
@Override
public void register(Function<?> function) {
putFunctionIntoMap(function);
putToDimensionsIfFunctionIsADimension(function);
}
private void putFunctionIntoMap(Function<?> function) {
Class<?> key = function.getDeclaringType();
if (!functionsMappedByDeclaringClass.containsKey(key)) {
functionsMappedByDeclaringClass.put(key, new HashSet<Function<?>>());
}
functionsMappedByDeclaringClass.get(key).add(function);
}
private void putToDimensionsIfFunctionIsADimension(Function<?> function) {
if (function.isDimension()) {
Class<?> key = function.getDeclaringType();
if (!dimensionsMappedByDeclaringClass.containsKey(key)) {
dimensionsMappedByDeclaringClass.put(key, new HashSet<Function<?>>());
}
dimensionsMappedByDeclaringClass.get(key).add(function);
}
}
@Override
public Collection<Function<?>> getFunctionsOf(Class<?> declaringClass) {
Collection<Function<?>> functions = functionsMappedByDeclaringClass.get(declaringClass);
return functions != null ? functions : new HashSet<Function<?>>();
}
@Override
public Collection<Function<?>> getDimensionsOf(Class<?> declaringClass) {
Collection<Function<?>> dimensions = dimensionsMappedByDeclaringClass.get(declaringClass);
return dimensions != null ? dimensions : new HashSet<Function<?>>();
}
@Override
public Collection<Function<?>> getAllFunctions() {
return collectAllFunctionsIn(functionsMappedByDeclaringClass);
} }
@Override @Override
public Collection<Function<?>> getAllDimensions() { public Collection<Function<?>> getAllDimensions() {
return collectAllFunctionsIn(dimensionsMappedByDeclaringClass); return dimensions;
}
private Collection<Function<?>> collectAllFunctionsIn(Map<Class<?>, Collection<Function<?>>> functionsMap) {
Set<Function<?>> registeredFunctions = new HashSet<>();
for (Collection<Function<?>> registeredMethodsOfClass : functionsMap.values()) {
registeredFunctions.addAll(registeredMethodsOfClass);
}
return registeredFunctions;
}
private class FunctionsReceiver implements Processor<Collection<Function<?>>> {
private final Lock functionsRegistrationLock;
private final List<Throwable> occuredFailures;
public FunctionsReceiver() {
functionsRegistrationLock = new ReentrantLock();
occuredFailures = new ArrayList<>();
}
@Override
public void onElement(Collection<Function<?>> element) {
functionsRegistrationLock.lock();
try {
SimpleFunctionRegistry.this.registerAll(element);
} finally {
functionsRegistrationLock.unlock();
}
}
@Override
public void onFailure(Throwable failure) {
occuredFailures.add(failure);
}
@Override
public void finish() throws InterruptedException {
for (Throwable failure : occuredFailures) {
LOGGER.log(Level.SEVERE, "An error occured during the processing of an instruction: ", failure);
}
}
@Override
public void abort() {
}
@Override
public AdditionalResultDataBuilder getAdditionalResultData(AdditionalResultDataBuilder additionalDataBuilder) {
return additionalDataBuilder;
}
} }
} }