Implemented the result enriching

With this task, I opened the I18N and enriched the Function annotations
This commit is contained in:
Lennart Hensler committed 2014-03-09 15:57:21 +01:00
1 parent 0350a54dec
commit 8edc00920a
38 files changed
+372 -266

No files matched your search

@@ -4,12 +4,13 @@ import java.io.Serializable;
import java.util.List;
import java.util.Map;
import com.google.gwt.i18n.client.LocaleInfo;
import com.sap.sse.datamining.components.AggregatorType;
import com.sap.sse.datamining.components.GrouperType;
public interface QueryDefinition extends Serializable {
public String getLocaleName();
public LocaleInfo getLocaleInfo();
public GrouperType getGrouperType();
@@ -17,7 +17,7 @@ import com.sap.sse.datamining.components.GrouperType;
public class SimpleQueryDefinition implements QueryDefinition {
private static final long serialVersionUID = 3476324726640558091L;
private String localeName;
private LocaleInfo localeInfo;
private GrouperType grouperType;
private StatisticType statisticType;
@@ -34,7 +34,7 @@ public class SimpleQueryDefinition implements QueryDefinition {
SimpleQueryDefinition() { }
public SimpleQueryDefinition(LocaleInfo localeInfo, GrouperType grouperType, StatisticType statisticType, AggregatorType aggregatorType, DataTypes dataType) {
this.localeName = localeInfo.getLocaleName();
this.localeInfo = localeInfo;
this.grouperType = grouperType;
this.statisticType = statisticType;
this.aggregatorType = aggregatorType;
@@ -45,8 +45,8 @@ public class SimpleQueryDefinition implements QueryDefinition {
}
@Override
public String getLocaleName() {
return localeName;
public LocaleInfo getLocaleInfo() {
return localeInfo;
}
@Override
@@ -7,46 +7,46 @@ import com.sap.sse.datamining.annotations.Dimension;
public interface GPSFixWithContext extends GPSFixMoving {
@Dimension("regatta")
@Dimension(messageKey="regatta")
public String getRegattaName();
@Dimension("race")
@Dimension(messageKey="race")
public String getRaceName();
@Dimension("legNumber")
@Dimension(messageKey="legNumber")
public int getLegNumber();
@Dimension("course")
@Dimension(messageKey="course")
public String getCourseAreaName();
@Dimension("fleet")
@Dimension(messageKey="fleet")
public String getFleetName();
@Dimension("boatClass")
@Dimension(messageKey="boatClass")
public String getBoatClassName();
/**
* The year of the start of the race.
*/
@Dimension("year")
@Dimension(messageKey="year")
public Integer getYear();
/**
* The leg type of the leg, which contains this gps fix. Can be <code>null</code> if there's no wind in the race.
*/
@Dimension("legType")
@Dimension(messageKey="legType")
public LegType getLegType();
@Dimension("competitor")
@Dimension(messageKey="competitor")
public String getCompetitorName();
@Dimension("sailID")
@Dimension(messageKey="sailID")
public String getCompetitorSailID();
@Dimension("nationality")
@Dimension(messageKey="nationality")
public String getCompetitorNationality();
@Dimension("windStrength")
@Dimension(messageKey="windStrength")
public WindStrengthCluster getWindStrength();
}
@@ -5,49 +5,50 @@ import com.sap.sailing.domain.common.Distance;
import com.sap.sailing.domain.common.LegType;
import com.sap.sse.datamining.annotations.Dimension;
import com.sap.sse.datamining.annotations.SideEffectFreeValue;
import com.sap.sse.datamining.shared.Unit;
public interface TrackedLegOfCompetitorWithContext {
@Dimension("regatta")
@Dimension(messageKey="regatta")
public String getRegattaName();
@Dimension("race")
@Dimension(messageKey="race")
public String getRaceName();
@Dimension("legNumber")
@Dimension(messageKey="legNumber")
public int getLegNumber();
@Dimension("course")
@Dimension(messageKey="course")
public String getCourseAreaName();
@Dimension("fleet")
@Dimension(messageKey="fleet")
public String getFleetName();
@Dimension("boatClass")
@Dimension(messageKey="boatClass")
public String getBoatClassName();
/**
* The year of the start of the race.
*/
@Dimension("year")
@Dimension(messageKey="year")
public Integer getYear();
@Dimension("legType")
@Dimension(messageKey="legType")
public LegType getLegType();
@Dimension("competitor")
@Dimension(messageKey="competitor")
public String getCompetitorName();
@Dimension("sailID")
@Dimension(messageKey="sailID")
public String getCompetitorSailID();
@Dimension("nationality")
@Dimension(messageKey="nationality")
public String getCompetitorNationality();
@Dimension("windStrength")
@Dimension(messageKey="windStrength")
public WindStrengthCluster getWindStrength();
@SideEffectFreeValue("distanceTraveled")
@SideEffectFreeValue(messageKey="distanceTraveled", resultUnit=Unit.Meters)
public Distance getDistanceTraveled();
}
@@ -1,8 +1,11 @@
package com.sap.sailing.datamining.factories;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ThreadPoolExecutor;
import com.google.gwt.i18n.client.LocaleInfo;
import com.sap.sailing.datamining.shared.QueryDefinition;
import com.sap.sailing.server.RacingEventService;
import com.sap.sse.datamining.Query;
@@ -20,12 +23,19 @@ import com.sap.sse.datamining.workers.WorkerBuilder;
public final class DataMiningFactory {
private static final DataMiningStringMessages stringMessages = DataMiningStringMessages.Util.getInstanceFor(Locale.ENGLISH);
private static final DataMiningStringMessages stringMessages = DataMiningStringMessages.Util.getDefaultStringMessages();
private static final String DEFAULT_LOCALE_NAME = "default";
private static final Map<String, Locale> supportedLocalesMappedByLocaleInfo = new HashMap<>(); {
supportedLocalesMappedByLocaleInfo.put(DEFAULT_LOCALE_NAME, Locale.ENGLISH);
supportedLocalesMappedByLocaleInfo.put("en", Locale.ENGLISH);
supportedLocalesMappedByLocaleInfo.put("de", Locale.GERMAN);
}
private DataMiningFactory() { }
public static <DataType, AggregatedType extends Number> Query<AggregatedType> createQuery(QueryDefinition queryDefinition, RacingEventService racingService) {
Locale locale = stringMessages.getLocaleFrom(queryDefinition.getLocaleName());
Locale locale = getLocaleFrom(queryDefinition.getLocaleInfo());
ParallelDataRetriever<DataType> retriever = DataRetrieverFactory.createDataRetriever(queryDefinition.getDataType(), racingService, getExecutor());
@@ -39,6 +49,11 @@ public final class DataMiningFactory {
return new QueryImpl<DataType, AggregatedType, AggregatedType>(stringMessages, locale, retriever, filter, grouper, extractor, aggregator);
}
private static Locale getLocaleFrom(LocaleInfo localeInfo) {
Locale locale = supportedLocalesMappedByLocaleInfo.get(localeInfo.getLocaleName());
return locale != null ? locale : supportedLocalesMappedByLocaleInfo.get(DEFAULT_LOCALE_NAME);
}
private static <DataType> ParallelFilter<DataType> createFilter(QueryDefinition queryDefinition) {
if (queryDefinition.getSelection().isEmpty()) {
return FilterFactory.createNonFilteringFilter();
@@ -6,6 +6,8 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.sap.sse.datamining.shared.Unit;
/**
* Methods marked with this annotation will be used as dimensions for the data mining framework. The method will be called,
* if the dimension value of a data element is requested.<br />
@@ -22,16 +24,16 @@ import java.lang.annotation.Target;
* <li>classes that implement <code>equals()</code>, <code>hashCode()</code> and <code>toString()</code>.
* </ul>
* Otherwise the grouping could become incorrect and the result presentation will be unreadable.
*
*
* @author Lennart Hensler (D054527)
*
*/
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Dimension {
public String value();
public String messageKey();
public Unit resultUnit() default Unit.None;
public int resultDecimals() default 0;
}
@@ -6,19 +6,22 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import com.sap.sse.datamining.shared.Unit;
/**
* Methods marked with this annotation will be used as function for the data mining framework. Functions can be used by the user to
* create new functions and dimensions.<br />
* The marked method has to be <b>side effect free</b>.<br />
*
* @author Lennart Hensler (D054527)
*
*/
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SideEffectFreeValue {
public String value();
public String messageKey();
public Unit resultUnit() default Unit.None;
public int resultDecimals() default 0;
}
@@ -3,5 +3,6 @@
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="resources"/>
<classpathentry kind="output" path="bin"/>
</classpath>
@@ -1,4 +1,5 @@
source.. = src/
source.. = src/,\
resources/
output.. = bin/
bin.includes = META-INF/,\
.
@@ -0,0 +1,6 @@
SimpleTestMessage=Deutsch
TestMessageWithParameters=Deutsch {0} - {1}
dimension = dimension-deutsch
value = sideEffectFreeValue-deutsch
regattaName = Regatta Name
crossSum = Quersumme
@@ -0,0 +1,6 @@
SimpleTestMessage=English
TestMessageWithParameters=English {0} - {1}
dimension = dimension-english
value = sideEffectFreeValue-english
regattaName = Regatta Name
crossSum = Cross Sum
@@ -36,11 +36,11 @@ import com.sap.sse.datamining.test.components.util.BlockingProcessor;
import com.sap.sse.datamining.test.components.util.Number;
import com.sap.sse.datamining.test.util.ConcurrencyTestsUtil;
import com.sap.sse.datamining.test.util.FunctionTestsUtil;
import com.sap.sse.datamining.test.util.StringMessagesForTests;
import com.sap.sse.datamining.test.util.TestsUtil;
public class TestProcessorQuery {
private final static DataMiningStringMessages stringMessages = new StringMessagesForTests();
private final static DataMiningStringMessages stringMessages = TestsUtil.getTestStringMessagesWithProductiveMessages();
private boolean receivedElementOrFinished;
private boolean receivedAbort;
@@ -129,14 +129,12 @@ public class TestProcessorQuery {
results.put(new GenericGroupKey<Integer>(3), 3.0);
results.put(new GenericGroupKey<Integer>(4), 10.0);
QueryResultImpl<Double> result = new QueryResultImpl<>(results, new AdditionalResultDataImpl(dataSource.size(), 2, "Cross sum (Sum)", Unit.None, 0, 0));
QueryResultImpl<Double> result = new QueryResultImpl<>(results, new AdditionalResultDataImpl(dataSource.size(), 2, "Cross Sum (Sum)", Unit.None, 0, 0));
return result;
}
private void verifyResult(QueryResult<Double> result, QueryResult<Double> expectedResult) {
assertThat("Result values aren't correct.", result.getResults(), is(expectedResult.getResults()));
// assertThat("Retrieved data amount isn't correct.", result.getRetrievedDataAmount(), is(expectedResult.getRetrievedDataAmount()));
assertThat("Filtered data amount isn't correct.", result.getFilteredDataAmount(), is(expectedResult.getFilteredDataAmount()));
assertThat("Result signifier isn't correct.", result.getResultSignifier(), is(expectedResult.getResultSignifier()));
assertThat("Unit isn't correct.", result.getUnit(), is(expectedResult.getUnit()));
assertThat("Value decimals aren't correct.", result.getValueDecimals(), is(expectedResult.getValueDecimals()));
@@ -13,16 +13,17 @@ import org.junit.Test;
import com.sap.sse.datamining.factories.FunctionFactory;
import com.sap.sse.datamining.functions.Function;
import com.sap.sse.datamining.i18n.DataMiningStringMessages;
import com.sap.sse.datamining.shared.dto.FunctionDTO;
import com.sap.sse.datamining.shared.impl.dto.FunctionDTOImpl;
import com.sap.sse.datamining.test.function.test_classes.ExternalLibraryClass;
import com.sap.sse.datamining.test.function.test_classes.SimpleClassWithMarkedMethods;
import com.sap.sse.datamining.test.util.FunctionTestsUtil;
import com.sap.sse.datamining.test.util.StringMessagesForTests;
import com.sap.sse.datamining.test.util.TestsUtil;
public class TestFunctionDTOConstruction {
private static final StringMessagesForTests stringMessages = new StringMessagesForTests();
private static final DataMiningStringMessages stringMessages = TestsUtil.getTestStringMessages();
private Method dimensionMethod;
private Method sideEffectFreeValueMethod;
@@ -30,11 +30,11 @@ import com.sap.sse.datamining.test.function.test_classes.ExtendingInterface;
import com.sap.sse.datamining.test.function.test_classes.ExternalLibraryClass;
import com.sap.sse.datamining.test.function.test_classes.SimpleClassWithMarkedMethods;
import com.sap.sse.datamining.test.util.FunctionTestsUtil;
import com.sap.sse.datamining.test.util.StringMessagesForTests;
import com.sap.sse.datamining.test.util.TestsUtil;
public class TestFunctionProvider {
private static final DataMiningStringMessages stringMessages = new StringMessagesForTests();
private static final DataMiningStringMessages stringMessages = TestsUtil.getTestStringMessagesWithProductiveMessages();
private FunctionRegistry functionRegistry;
@@ -11,11 +11,12 @@ import org.junit.Test;
import com.sap.sse.datamining.factories.FunctionFactory;
import com.sap.sse.datamining.functions.Function;
import com.sap.sse.datamining.i18n.DataMiningStringMessages;
import com.sap.sse.datamining.impl.functions.MethodWrappingFunction;
import com.sap.sse.datamining.test.function.test_classes.ExternalLibraryClass;
import com.sap.sse.datamining.test.function.test_classes.SimpleClassWithMarkedMethods;
import com.sap.sse.datamining.test.util.FunctionTestsUtil;
import com.sap.sse.datamining.test.util.StringMessagesForTests;
import com.sap.sse.datamining.test.util.TestsUtil;
public class TestMethodWrappingFunction {
@@ -50,7 +51,7 @@ public class TestMethodWrappingFunction {
@Test
public void testGetLocalizedName() {
StringMessagesForTests stringMessages = new StringMessagesForTests();
DataMiningStringMessages stringMessages = TestsUtil.getTestStringMessages();
Function<?> dimension = FunctionFactory.createMethodWrappingFunction(dimensionMethod);
String expectedEnglishName = "dimension-english";
@@ -8,36 +8,29 @@ import java.util.Locale;
import org.junit.Before;
import org.junit.Test;
import com.sap.sse.datamining.test.util.OpenResourceBundleManager;
import com.sap.sse.datamining.i18n.DataMiningStringMessages;
import com.sap.sse.datamining.test.util.TestsUtil;
public class TestI18N {
private static final String SIMPLE_TEST_MESSAGE_KEY = "SimpleTestMessage";
private static final String TEST_MESSAGE_WITH_PARAMETERS = "TestMessageWithParameters";
private OpenResourceBundleManager bundleManager;
private DataMiningStringMessages bundleManager;
@Before
public void initializeBundleManager() {
bundleManager = new OpenResourceBundleManager(Locale.ENGLISH);
bundleManager = TestsUtil.getTestStringMessages();
}
@Test
public void testGettingASimpleMessage() {
assertThat(bundleManager.get("default", SIMPLE_TEST_MESSAGE_KEY), is("English"));
assertThat(bundleManager.get("en", SIMPLE_TEST_MESSAGE_KEY), is("English"));
assertThat(bundleManager.get("de", SIMPLE_TEST_MESSAGE_KEY), is("Deutsch"));
assertThat(bundleManager.get(Locale.ENGLISH, SIMPLE_TEST_MESSAGE_KEY), is("English"));
assertThat(bundleManager.get(Locale.GERMAN, SIMPLE_TEST_MESSAGE_KEY), is("Deutsch"));
}
@Test
public void testGettingAMessageWithParameters() {
assertThat(bundleManager.get("default", TEST_MESSAGE_WITH_PARAMETERS, "Param0", "Param1"), is("English Param0 - Param1"));
assertThat(bundleManager.get("en", TEST_MESSAGE_WITH_PARAMETERS, "Param0", "Param1"), is("English Param0 - Param1"));
assertThat(bundleManager.get("de", TEST_MESSAGE_WITH_PARAMETERS, "Param0", "Param1"), is("Deutsch Param0 - Param1"));
assertThat(bundleManager.get(Locale.ENGLISH, TEST_MESSAGE_WITH_PARAMETERS, "Param0", "Param1"), is("English Param0 - Param1"));
assertThat(bundleManager.get(Locale.GERMAN, TEST_MESSAGE_WITH_PARAMETERS, "Param0", "Param1"), is("Deutsch Param0 - Param1"));
}
@@ -19,12 +19,12 @@ public class Number {
return value;
}
@Dimension("length")
@Dimension(messageKey="length")
public int getLength() {
return String.valueOf(value).length();
}
@Dimension("crossSum")
@Dimension(messageKey="crossSum")
public int getCrossSum() {
int crossSum = 0;
int value = this.value;
@@ -1,10 +1,11 @@
package com.sap.sse.datamining.test.function.test_classes;
import com.sap.sse.datamining.annotations.SideEffectFreeValue;
import com.sap.sse.datamining.shared.Unit;
public interface DataTypeInterface {
@SideEffectFreeValue("speedInKnots")
@SideEffectFreeValue(messageKey="speedInKnots", resultUnit=Unit.Knots, resultDecimals=2)
public int getSpeedInKnots();
}
@@ -9,13 +9,13 @@ import com.sap.sse.datamining.annotations.Dimension;
public interface DataTypeWithContext extends DataTypeInterface {
@Dimension("regattaName")
@Dimension(messageKey="regattaName")
public String getRegattaName();
@Dimension("raceName")
@Dimension(messageKey="raceName")
public String getRaceName();
@Dimension("legNumber")
@Dimension(messageKey="legNumber")
public int getLegNumber();
}
@@ -4,7 +4,7 @@ import com.sap.sse.datamining.annotations.Dimension;
public class DataTypeWithContextProcessor {
@Dimension("regattaAndRaceName")
@Dimension(messageKey="regattaAndRaceName")
public String getRegattaAndRaceName(DataTypeWithContext dataEntry) {
return dataEntry.getRegattaName() + " - " + dataEntry.getRaceName();
}
@@ -4,7 +4,7 @@ import com.sap.sse.datamining.annotations.SideEffectFreeValue;
public interface ExtendingInterface {
@SideEffectFreeValue("raceNameLength")
@SideEffectFreeValue(messageKey="raceNameLength")
public int getRaceNameLength();
}
@@ -10,18 +10,18 @@ import com.sap.sse.datamining.annotations.SideEffectFreeValue;
public class SimpleClassWithMarkedMethods {
@Dimension("dimension")
@Dimension(messageKey="dimension")
public String dimension() {
return "Method marked as dimension";
}
//Methods without a return value can't be dimensions
@Dimension("illegalDimension")
@Dimension(messageKey="illegalDimension")
public void illegalDimension() {
}
@SideEffectFreeValue("value")
@SideEffectFreeValue(messageKey="value")
public int sideEffectFreeValue() {
return 1;
}
@@ -8,7 +8,7 @@ import java.util.concurrent.TimeUnit;
import com.sap.sse.datamining.components.Processor;
public class ConcurrencyTestsUtil {
public class ConcurrencyTestsUtil extends TestsUtil {
private static final int THREAD_POOL_SIZE = Math.max(Runtime.getRuntime().availableProcessors(), 3);
private static ThreadPoolExecutor executor = createExecutor();
@@ -1,29 +0,0 @@
package com.sap.sse.datamining.test.util;
import java.util.Locale;
import com.sap.sse.datamining.impl.i18n.DataMiningResourceBundleManager;
public class OpenResourceBundleManager extends DataMiningResourceBundleManager {
public OpenResourceBundleManager(Locale defaultLocale) {
super(defaultLocale);
}
public String get(Locale locale, String message, String... parameters) {
return super.get(locale, message, parameters);
}
public String get(Locale locale, String message) {
return super.get(locale, message, new String[0]);
}
public String get(String localeName, String message, String... parameters) {
return this.get(getLocaleFrom(localeName), message, parameters);
}
public String get(String localeName, String message) {
return this.get(getLocaleFrom(localeName), message);
}
}
@@ -1,66 +0,0 @@
package com.sap.sse.datamining.test.util;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import com.sap.sse.datamining.i18n.DataMiningStringMessages;
import com.sap.sse.datamining.shared.Message;
public class StringMessagesForTests implements DataMiningStringMessages {
private final Map<Locale, Map<String, String>> messages;
public StringMessagesForTests() {
messages = new HashMap<>();
initializeEnglishMessages();
initializeGermanMessages();
}
private void initializeEnglishMessages() {
Map<String, String> englishMessages = new HashMap<>();
messages.put(Locale.ENGLISH, englishMessages);
englishMessages.put("dimension", "dimension-english");
englishMessages.put("value", "sideEffectFreeValue-english");
}
private void initializeGermanMessages() {
Map<String, String> germanMessages = new HashMap<>();
messages.put(Locale.GERMAN, germanMessages);
germanMessages.put("dimension", "dimension-deutsch");
germanMessages.put("value", "sideEffectFreeValue-deutsch");
}
@Override
public Locale getLocaleFrom(String localeName) {
throw new UnsupportedOperationException("Not implemented");
}
@Override
public String get(Locale locale, Message message) {
throw new UnsupportedOperationException("Not implemented");
}
@Override
public String get(Locale locale, Message message, String... parameters) {
throw new UnsupportedOperationException("Not implemented");
}
@Override
public String get(Locale locale, Message message, Message... parameters) {
throw new UnsupportedOperationException("Not implemented");
}
@Override
public String get(Locale locale, String messageKey) {
return messages.get(locale).get(messageKey);
}
@Override
public String get(Locale locale, String messageKey, String... parameters) {
throw new UnsupportedOperationException("Not implemented");
}
}
@@ -0,0 +1,23 @@
package com.sap.sse.datamining.test.util;
import com.sap.sse.datamining.i18n.DataMiningStringMessages;
public class TestsUtil {
private static final String TEST_STRING_MESSAGES_BASE_NAME = "stringmessages/Test_StringMessages";
private static final DataMiningStringMessages TEST_STRING_MESSAGES = DataMiningStringMessages.Util.getInstanceFor(TEST_STRING_MESSAGES_BASE_NAME);
private static final DataMiningStringMessages EXTENDED_STRING_MESSAGES = DataMiningStringMessages.Util.getCompoundStringMessages(
DataMiningStringMessages.Util.getDefaultStringMessagesBaseName(),
TEST_STRING_MESSAGES_BASE_NAME);
public static DataMiningStringMessages getTestStringMessages() {
return TEST_STRING_MESSAGES;
}
public static DataMiningStringMessages getTestStringMessagesWithProductiveMessages() {
return EXTENDED_STRING_MESSAGES;
}
protected TestsUtil() { }
}
@@ -33,5 +33,6 @@ Export-Package: com.sap.sse.datamining;uses:="com.sap.sse.datamining.functions,c
com.sap.sse.datamining.impl.workers.extractors,
com.sap.sse.datamining.impl.workers.retrievers,
com.sap.sse.datamining.workers
Require-Bundle: com.sap.sse.datamining.shared;bundle-version="1.0.0"
Require-Bundle: com.sap.sse.datamining.shared;bundle-version="1.0.0",
com.sap.sailing.domain.common;bundle-version="1.0.0"
Bundle-Activator: com.sap.sse.datamining.impl.DataMiningActivator
@@ -1,5 +1,3 @@
SimpleTestMessage=Deutsch
TestMessageWithParameters=Deutsch {0} - {1}
Average=Durchschnitt
Median=Median
Sum=Summe
@@ -1,5 +1,3 @@
SimpleTestMessage=English
TestMessageWithParameters=English {0} - {1}
Average=Average
Median=Median
Sum=Sum
@@ -2,9 +2,9 @@ package com.sap.sse.datamining;
import java.util.Locale;
import com.sap.sse.datamining.functions.Function;
import com.sap.sse.datamining.i18n.DataMiningStringMessages;
import com.sap.sse.datamining.shared.AdditionalResultData;
import com.sap.sse.datamining.shared.Unit;
/**
* These builders are used to collect the additional result data from different sources (e.g. the Processors)
@@ -18,13 +18,8 @@ public interface AdditionalResultDataBuilder {
public void setFilteredDataAmount(int filteredDataAmount);
public void setExtractedStatisticNameMessageKey(String extractedStatisticNameMessageKey);
public void setExtractionFunction(Function<?> extractionFunction);
public void setAggregationNameMessageKey(String aggregationNameMessageKey);
public void setUnit(Unit unit);
public void setValueDecimals(int valueDecimals);
}
@@ -6,6 +6,7 @@ import java.util.Locale;
import com.sap.sse.datamining.annotations.Dimension;
import com.sap.sse.datamining.annotations.SideEffectFreeValue;
import com.sap.sse.datamining.i18n.DataMiningStringMessages;
import com.sap.sse.datamining.shared.Unit;
import com.sap.sse.datamining.shared.dto.FunctionDTO;
public interface Function<ReturnType> {
@@ -46,6 +47,8 @@ public interface Function<ReturnType> {
*/
public FunctionDTO asDTO(Locale locale, DataMiningStringMessages stringMessages);
public String getMessageKey();
public Unit getResultUnit();
public int getResultDecimals();
}
@@ -1,16 +1,19 @@
package com.sap.sse.datamining.i18n;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import com.sap.sse.datamining.impl.i18n.DataMiningResourceBundleManager;
import com.sap.sse.datamining.impl.i18n.CompoundDataMiningStringMessages;
import com.sap.sse.datamining.impl.i18n.DataMiningStringMessagesImpl;
import com.sap.sse.datamining.shared.Message;
public interface DataMiningStringMessages {
public Locale getLocaleFrom(String localeName);
public String getResourceBaseName();
public String get(Locale locale, Message message);
public String get(Locale locale, Message message, String... parameters);
public String get(Locale locale, Message message, Message... parameters);
@@ -21,16 +24,40 @@ public interface DataMiningStringMessages {
//TODO Replace with static method, after Java 8 can be used
public static final class Util {
private Util () {
private static final String DEFAULT_STRING_MESSAGES_BASE_NAME = "stringmessages/StringMessages";
private static DataMiningStringMessages defaultStringMessages;
private static Map<String, DataMiningStringMessages> stringMessagesMappedByResourceBaseName = new HashMap<>();
public static String getDefaultStringMessagesBaseName() {
return DEFAULT_STRING_MESSAGES_BASE_NAME;
}
private static Map<Locale, DataMiningStringMessages> stringMessagesMappedByLocale = new HashMap<>();
public static DataMiningStringMessages getInstanceFor(Locale locale) {
if (!stringMessagesMappedByLocale.containsKey(locale)) {
stringMessagesMappedByLocale.put(locale, new DataMiningResourceBundleManager(locale));
public static DataMiningStringMessages getDefaultStringMessages() {
if (defaultStringMessages == null) {
defaultStringMessages = new DataMiningStringMessagesImpl(DEFAULT_STRING_MESSAGES_BASE_NAME);
}
return stringMessagesMappedByLocale.get(locale);
return defaultStringMessages;
}
public static DataMiningStringMessages getInstanceFor(String resourceBaseName) {
String key = resourceBaseName;
if (!stringMessagesMappedByResourceBaseName.containsKey(key)) {
stringMessagesMappedByResourceBaseName.put(key, new DataMiningStringMessagesImpl(resourceBaseName));
}
return stringMessagesMappedByResourceBaseName.get(key);
}
public static DataMiningStringMessages getCompoundStringMessages(String... resourceBaseNames) {
Collection<DataMiningStringMessages> stringMessages = new HashSet<>();
for (String resourceBaseName : resourceBaseNames) {
stringMessages.add(getInstanceFor(resourceBaseName));
}
return new CompoundDataMiningStringMessages(stringMessages);
}
private Util () {
}
}
@@ -3,6 +3,7 @@ package com.sap.sse.datamining.impl;
import java.util.Locale;
import com.sap.sse.datamining.AdditionalResultDataBuilder;
import com.sap.sse.datamining.functions.Function;
import com.sap.sse.datamining.i18n.DataMiningStringMessages;
import com.sap.sse.datamining.shared.AdditionalResultData;
import com.sap.sse.datamining.shared.Message;
@@ -21,10 +22,10 @@ public class SumBuildingAndOverwritingResultDataBuilder implements AdditionalRes
private int retrievedDataAmount;
private int filteredDataAmount;
private String extractedStatisticNameMessageKey;
private Function<?> extractionFunction;
private String aggregationNameMessageKey;
private Unit unit;
private int valueDecimals;
private int resultDecimals;
/**
* Creates a new builder with standard values for the additional data.
@@ -33,16 +34,20 @@ public class SumBuildingAndOverwritingResultDataBuilder implements AdditionalRes
retrievedDataAmount = 0;
filteredDataAmount = 0;
unit = Unit.None;
valueDecimals = 0;
resultDecimals = 0;
}
@Override
public AdditionalResultData build(long calculationTimeInNanos, DataMiningStringMessages stringMessages, Locale locale) {
return new AdditionalResultDataImpl(retrievedDataAmount, filteredDataAmount, buildResultSignifier(stringMessages, locale), unit, valueDecimals, calculationTimeInNanos);
return new AdditionalResultDataImpl(retrievedDataAmount, filteredDataAmount, buildResultSignifier(stringMessages, locale), unit, resultDecimals, calculationTimeInNanos);
}
private String buildResultSignifier(DataMiningStringMessages stringMessages, Locale locale) {
String extractedStatisticName = stringMessages.get(locale, extractedStatisticNameMessageKey);
if (extractionFunction == null || aggregationNameMessageKey == null) {
return "";
}
String extractedStatisticName = extractionFunction.getLocalizedName(locale, stringMessages);
String aggregationName = stringMessages.get(locale, aggregationNameMessageKey);
return stringMessages.get(locale, Message.ResultSignifier, extractedStatisticName, aggregationName);
}
@@ -58,8 +63,10 @@ public class SumBuildingAndOverwritingResultDataBuilder implements AdditionalRes
}
@Override
public void setExtractedStatisticNameMessageKey(String extractedStatisticNameMessageKey) {
this.extractedStatisticNameMessageKey = extractedStatisticNameMessageKey;
public void setExtractionFunction(Function<?> extractionFunction) {
this.extractionFunction = extractionFunction;
unit = extractionFunction.getResultUnit();
resultDecimals = extractionFunction.getResultDecimals();
}
@Override
@@ -67,14 +74,4 @@ public class SumBuildingAndOverwritingResultDataBuilder implements AdditionalRes
this.aggregationNameMessageKey = aggregationNameMessageKey;
}
@Override
public void setUnit(Unit unit) {
this.unit = unit;
}
@Override
public void setValueDecimals(int valueDecimals) {
this.valueDecimals = valueDecimals;
}
}
@@ -34,7 +34,7 @@ public class ParallelGroupedElementsValueExtractionProcessor<ElementType, Functi
@Override
protected void setAdditionalData(AdditionalResultDataBuilder additionalDataBuilder) {
additionalDataBuilder.setExtractedStatisticNameMessageKey(extractionFunction.getMessageKey());
additionalDataBuilder.setExtractionFunction(extractionFunction);
}
}
@@ -0,0 +1,29 @@
package com.sap.sse.datamining.impl.functions;
import com.sap.sse.datamining.shared.Unit;
public class AdditionalFunctionData {
private final String messageKey;
private final Unit resultUnit;
private final int resultDecimals;
public AdditionalFunctionData(String messageKey, Unit resultUnit, int resultValueDecimals) {
this.messageKey = messageKey;
this.resultUnit = resultUnit;
this.resultDecimals = resultValueDecimals;
}
public String getMessageKey() {
return messageKey;
}
public Unit getResultUnit() {
return resultUnit;
}
public int getResultDecimals() {
return resultDecimals;
}
}
@@ -11,6 +11,7 @@ import java.util.logging.Level;
import com.sap.sse.datamining.annotations.Dimension;
import com.sap.sse.datamining.annotations.SideEffectFreeValue;
import com.sap.sse.datamining.i18n.DataMiningStringMessages;
import com.sap.sse.datamining.shared.Unit;
import com.sap.sse.datamining.shared.dto.FunctionDTO;
import com.sap.sse.datamining.shared.impl.dto.FunctionDTOImpl;
@@ -19,6 +20,8 @@ public class MethodWrappingFunction<ReturnType> extends AbstractFunction<ReturnT
private Method method;
private String messageKey;
private int resultDecimals;
private Unit resultUnit;
/**
* Throws an {@link IllegalArgumentException}, if the return type of the method and the given <code>returnType</code>
@@ -29,7 +32,7 @@ public class MethodWrappingFunction<ReturnType> extends AbstractFunction<ReturnT
checkThatReturnTypesMatch(method, returnType);
this.method = method;
initializeMessageKey();
initializeAdditionalData();
}
private static boolean isMethodADimension(Method method) {
@@ -43,19 +46,19 @@ public class MethodWrappingFunction<ReturnType> extends AbstractFunction<ReturnT
}
}
private void initializeMessageKey() {
private void initializeAdditionalData() {
if (method.getAnnotation(Dimension.class) != null) {
setMessageKey(method.getAnnotation(Dimension.class).value());
messageKey = method.getAnnotation(Dimension.class).messageKey();
resultUnit = method.getAnnotation(Dimension.class).resultUnit();
resultDecimals = method.getAnnotation(Dimension.class).resultDecimals();
}
if (method.getAnnotation(SideEffectFreeValue.class) != null) {
setMessageKey(method.getAnnotation(SideEffectFreeValue.class).value());
messageKey = method.getAnnotation(SideEffectFreeValue.class).messageKey();
resultUnit = method.getAnnotation(SideEffectFreeValue.class).resultUnit();
resultDecimals = method.getAnnotation(SideEffectFreeValue.class).resultDecimals();
}
}
private void setMessageKey(String messageKey) {
this.messageKey = messageKey;
}
@Override
public Class<?> getDeclaringClass() {
return method.getDeclaringClass();
@@ -82,22 +85,27 @@ public class MethodWrappingFunction<ReturnType> extends AbstractFunction<ReturnT
return null;
}
@Override
public Unit getResultUnit() {
return resultUnit;
}
@Override
public int getResultDecimals() {
return resultDecimals;
}
@Override
public String getLocalizedName(Locale locale, DataMiningStringMessages stringMessages) {
if (getMessageKey() == null || getMessageKey().isEmpty()) {
if (messageKey == null || messageKey.isEmpty()) {
return getMethodName();
}
return stringMessages.get(locale, getMessageKey());
return stringMessages.get(locale, messageKey);
}
private String getMethodName() {
return method.getName();
}
@Override
public String getMessageKey() {
return messageKey;
}
@Override
public FunctionDTO asDTO() {
@@ -0,0 +1,110 @@
package com.sap.sse.datamining.impl.i18n;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.MissingResourceException;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.sap.sse.datamining.i18n.DataMiningStringMessages;
import com.sap.sse.datamining.shared.Message;
public class CompoundDataMiningStringMessages implements DataMiningStringMessages {
private static final Logger LOGGER = Logger.getLogger(CompoundDataMiningStringMessages.class.getSimpleName());
private final Collection<DataMiningStringMessages> stringMessages;
public CompoundDataMiningStringMessages(Collection<DataMiningStringMessages> stringMessages) {
this.stringMessages = new HashSet<>(stringMessages);
}
@Override
public String get(Locale locale, String messageKey) {
return get(locale, messageKey, new String[0]);
}
@Override
public String get(Locale locale, Message message) {
return get(locale, message.toString(), new String[0]);
}
@Override
public String get(Locale locale, Message message, String... parameters) {
return get(locale, message.toString(), parameters);
}
@Override
public String get(Locale locale, Message message, Message... parameters) {
String[] parametersAsString = new String[parameters.length];
for (int i = 0; i < parameters.length; i++) {
parametersAsString[i] = get(locale, parameters[i]);
}
return get(locale, message, parametersAsString);
}
@Override
public String get(Locale locale, String messageKey, String... parameters) {
Map<String, String> messages = new HashMap<>();
for (DataMiningStringMessages stringMessages : this.stringMessages) {
messages.put(stringMessages.getResourceBaseName(), getFrom(stringMessages, locale, messageKey, parameters));
}
return getBestMessageAndLogConflicts(messageKey, messages);
}
private String getFrom(DataMiningStringMessages stringMessages, Locale locale, String messageKey, String... parameters) {
try {
return stringMessages.get(locale, messageKey, parameters);
} catch (MissingResourceException e) {
return null;
}
}
private String getBestMessageAndLogConflicts(String messageKey, Map<String, String> messages) throws MissingResourceException {
String bestMessageResourceBaseName = null;
String bestMessage = null;
for (Entry<String, String> messagesEntry : messages.entrySet()) {
String message = messagesEntry.getValue();
if (message != null) {
if (bestMessage == null) {
bestMessage = message;
bestMessageResourceBaseName = messagesEntry.getKey();
} else {
logPossibleConflicts(messageKey, bestMessageResourceBaseName, bestMessage, messagesEntry);
}
}
}
if (bestMessage == null) {
throw new MissingResourceException("Can't find resource for bundle " + this.getClass().getName() + ", key "
+ messageKey, this.getClass().getName(), messageKey);
}
return bestMessage;
}
private void logPossibleConflicts(String messageKey, String bestMessageResourceBaseName, String bestMessage,
Entry<String, String> messagesEntry) {
String messageResourceBaseName = messagesEntry.getKey();
String message = messagesEntry.getValue();
if (bestMessage.equals(message)) {
LOGGER.log(Level.INFO, "The resources " + bestMessageResourceBaseName +
" and " + messageResourceBaseName + " contain the same message for the key '" +
messageKey + "'");
} else {
LOGGER.log(Level.INFO, "The resources " + bestMessageResourceBaseName +
" and " + messageResourceBaseName + " contain different messages for the key '" +
messageKey + "'");
}
}
@Override
public String getResourceBaseName() {
return "This implementations has multiple resource bundles";
}
}
@@ -1,28 +1,20 @@
package com.sap.sse.datamining.impl.i18n;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import com.sap.sse.datamining.i18n.DataMiningStringMessages;
import com.sap.sse.datamining.shared.Message;
public class DataMiningResourceBundleManager implements DataMiningStringMessages {
public class DataMiningStringMessagesImpl implements DataMiningStringMessages {
private static final String DEFAULT_LOCALE_NAME = "default";
private static final String STRING_MESSAGES_BASE_NAME = "stringmessages/StringMessages";
private static final String MESSAGE_PARAMETER_START = "\\{";
private static final String MESSAGE_PARAMETER_END = "\\}";
private Map<String, Locale> supportedLocalesMappedByLocaleInfo;
private Map<Locale, ResourceBundle> messagesMappedByLocale;
private final String resourceBaseName;
public DataMiningResourceBundleManager(Locale defaultLocale) {
supportedLocalesMappedByLocaleInfo = new HashMap<>();
messagesMappedByLocale = new HashMap<>();
initializeSupportedLocales(defaultLocale);
public DataMiningStringMessagesImpl(String resourceBaseName) {
this.resourceBaseName = resourceBaseName;
}
@Override
@@ -31,19 +23,13 @@ public class DataMiningResourceBundleManager implements DataMiningStringMessages
}
@Override
public String get(Locale locale, Message message, String... parameters) {
return get(locale, message.toString(), parameters);
public String get(Locale locale, Message message) {
return get(locale, message.toString(), new String[0]);
}
@Override
public String get(Locale locale, String messageKey, String... parameters) {
String result = getResourceBundle(locale).getString(messageKey);
for (int i = 0; i < parameters.length; i++) {
String replacementRegex = MESSAGE_PARAMETER_START + i + MESSAGE_PARAMETER_END;
result = result.replaceAll(replacementRegex, parameters[i]);
}
return result;
public String get(Locale locale, Message message, String... parameters) {
return get(locale, message.toString(), parameters);
}
@Override
@@ -56,27 +42,23 @@ public class DataMiningResourceBundleManager implements DataMiningStringMessages
}
@Override
public String get(Locale locale, Message message) {
return get(locale, message, new String[0]);
public String get(Locale locale, String messageKey, String... parameters) {
String result = getResourceBundle(locale).getString(messageKey);
for (int i = 0; i < parameters.length; i++) {
String replacementRegex = MESSAGE_PARAMETER_START + i + MESSAGE_PARAMETER_END;
result = result.replaceAll(replacementRegex, parameters[i]);
}
return result;
}
@Override
public Locale getLocaleFrom(String localeName) {
Locale locale = supportedLocalesMappedByLocaleInfo.get(localeName);
return locale != null ? locale : supportedLocalesMappedByLocaleInfo.get(DEFAULT_LOCALE_NAME);
private ResourceBundle getResourceBundle(Locale locale) {
return ResourceBundle.getBundle(resourceBaseName, locale);
}
private ResourceBundle getResourceBundle(Locale locale) {
if (!messagesMappedByLocale.containsKey(locale)) {
messagesMappedByLocale.put(locale, ResourceBundle.getBundle(STRING_MESSAGES_BASE_NAME, locale));
}
return messagesMappedByLocale.get(locale);
}
private void initializeSupportedLocales(Locale defaultLocale) {
supportedLocalesMappedByLocaleInfo.put(DEFAULT_LOCALE_NAME, defaultLocale);
supportedLocalesMappedByLocaleInfo.put("en", Locale.ENGLISH);
supportedLocalesMappedByLocaleInfo.put("de", Locale.GERMAN);
@Override
public String getResourceBaseName() {
return resourceBaseName;
}
}