From 722cb7f2ff8e548a9154631d32359df777f8789f Mon Sep 17 00:00:00 2001 From: Lennart Hensler Date: Mon, 12 Oct 2015 12:26:29 +0200 Subject: [PATCH 1/6] Cleaned the data mining DTOs --- .../sse/datamining/shared/impl/dto/DataRetrieverLevelDTO.java | 2 +- .../com/sap/sse/datamining/shared/impl/dto/FunctionDTO.java | 2 +- .../src/com/sap/sse/datamining/impl/DataMiningServerImpl.java | 4 ++-- ...eMemorInfoProvider.java => RuntimeMemoryInfoProvider.java} | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) rename java/com.sap.sse.datamining/src/com/sap/sse/datamining/impl/components/management/{RuntimeMemorInfoProvider.java => RuntimeMemoryInfoProvider.java} (75%) diff --git a/java/com.sap.sse.datamining.shared/src/com/sap/sse/datamining/shared/impl/dto/DataRetrieverLevelDTO.java b/java/com.sap.sse.datamining.shared/src/com/sap/sse/datamining/shared/impl/dto/DataRetrieverLevelDTO.java index 4e7858e663e..2d5850a4910 100644 --- a/java/com.sap.sse.datamining.shared/src/com/sap/sse/datamining/shared/impl/dto/DataRetrieverLevelDTO.java +++ b/java/com.sap.sse.datamining.shared/src/com/sap/sse/datamining/shared/impl/dto/DataRetrieverLevelDTO.java @@ -49,7 +49,7 @@ public class DataRetrieverLevelDTO implements Serializable, Comparable { } public String toString() { - return (isDimension() ? "Dimension " : "Function ") + sourceTypeName + "." + functionName + "(" + parametersAsString() + ") : " + returnTypeName; + return (isDimension() ? "Dimension " : "Function ") + getSourceTypeName() + "." + getFunctionName() + "(" + parametersAsString() + ") : " + getReturnTypeName(); } private String parametersAsString() { diff --git a/java/com.sap.sse.datamining/src/com/sap/sse/datamining/impl/DataMiningServerImpl.java b/java/com.sap.sse.datamining/src/com/sap/sse/datamining/impl/DataMiningServerImpl.java index 586b0e1dc00..e49fbfed5fe 100644 --- a/java/com.sap.sse.datamining/src/com/sap/sse/datamining/impl/DataMiningServerImpl.java +++ b/java/com.sap.sse.datamining/src/com/sap/sse/datamining/impl/DataMiningServerImpl.java @@ -36,7 +36,7 @@ import com.sap.sse.datamining.functions.Function; import com.sap.sse.datamining.impl.components.DataRetrieverLevel; import com.sap.sse.datamining.impl.components.management.AbstractMemoryMonitorAction; import com.sap.sse.datamining.impl.components.management.QueryManagerMemoryMonitor; -import com.sap.sse.datamining.impl.components.management.RuntimeMemorInfoProvider; +import com.sap.sse.datamining.impl.components.management.RuntimeMemoryInfoProvider; import com.sap.sse.datamining.impl.components.management.StrategyPerQueryTypeManager; import com.sap.sse.datamining.shared.DataMiningSession; import com.sap.sse.datamining.shared.dto.StatisticQueryDefinitionDTO; @@ -74,7 +74,7 @@ public class DataMiningServerImpl implements ModifiableDataMiningServer { componentsChangedTimepoint = new Date(); this.queryFactory = new QueryFactory(); dataMiningQueryManager = new StrategyPerQueryTypeManager(); - memoryMonitor = new QueryManagerMemoryMonitor(new RuntimeMemorInfoProvider(Runtime.getRuntime()), dataMiningQueryManager, + memoryMonitor = new QueryManagerMemoryMonitor(new RuntimeMemoryInfoProvider(Runtime.getRuntime()), dataMiningQueryManager, createMemoryMonitorActions(), MEMORY_CHECK_PERIOD, MEMORY_CHECK_PERIOD_UNIT); this.functionRegistry = functionRegistry; this.dataSourceProviderRegistry = dataSourceProviderRegistry; diff --git a/java/com.sap.sse.datamining/src/com/sap/sse/datamining/impl/components/management/RuntimeMemorInfoProvider.java b/java/com.sap.sse.datamining/src/com/sap/sse/datamining/impl/components/management/RuntimeMemoryInfoProvider.java similarity index 75% rename from java/com.sap.sse.datamining/src/com/sap/sse/datamining/impl/components/management/RuntimeMemorInfoProvider.java rename to java/com.sap.sse.datamining/src/com/sap/sse/datamining/impl/components/management/RuntimeMemoryInfoProvider.java index 1f06bcbfa05..6a861bb086a 100644 --- a/java/com.sap.sse.datamining/src/com/sap/sse/datamining/impl/components/management/RuntimeMemorInfoProvider.java +++ b/java/com.sap.sse.datamining/src/com/sap/sse/datamining/impl/components/management/RuntimeMemoryInfoProvider.java @@ -2,11 +2,11 @@ package com.sap.sse.datamining.impl.components.management; import com.sap.sse.datamining.components.management.MemoryInfoProvider; -public class RuntimeMemorInfoProvider implements MemoryInfoProvider { +public class RuntimeMemoryInfoProvider implements MemoryInfoProvider { private Runtime runtime; - public RuntimeMemorInfoProvider(Runtime runtime) { + public RuntimeMemoryInfoProvider(Runtime runtime) { this.runtime = runtime; } From a621d5d4b3a0144de7aea581c6d0f02518662e23 Mon Sep 17 00:00:00 2001 From: Lennart Hensler Date: Mon, 12 Oct 2015 13:02:34 +0200 Subject: [PATCH 2/6] Replaces simple class name with class name in the data mining DTOs --- .../functions/TestFunctionDTOConstruction.java | 18 +++++++++--------- .../factories/DataMiningDTOFactory.java | 14 +++++++------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/functions/TestFunctionDTOConstruction.java b/java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/functions/TestFunctionDTOConstruction.java index fe735d9affb..783b367a6cc 100644 --- a/java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/functions/TestFunctionDTOConstruction.java +++ b/java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/functions/TestFunctionDTOConstruction.java @@ -48,8 +48,8 @@ public class TestFunctionDTOConstruction { public FunctionDTO createExpectedDimensionDTO() { String functionName = dimensionMethod.getName(); - String sourceTypeName = dimensionMethod.getDeclaringClass().getSimpleName(); - String returnTypeName = dimensionMethod.getReturnType().getSimpleName(); + String sourceTypeName = dimensionMethod.getDeclaringClass().getName(); + String returnTypeName = dimensionMethod.getReturnType().getName(); List parameterTypeNames = new ArrayList<>(); String displayName = functionName; @@ -70,8 +70,8 @@ public class TestFunctionDTOConstruction { private FunctionDTO createExpectedNullarySideEffectFreeValueDTO() { String functionName = sideEffectFreeValueMethod.getName(); - String sourceTypeName = sideEffectFreeValueMethod.getDeclaringClass().getSimpleName(); - String returnTypeName = sideEffectFreeValueMethod.getReturnType().getSimpleName(); + String sourceTypeName = sideEffectFreeValueMethod.getDeclaringClass().getName(); + String returnTypeName = sideEffectFreeValueMethod.getReturnType().getName(); List parameterTypeNames = new ArrayList<>(); String displayName = functionName; @@ -92,8 +92,8 @@ public class TestFunctionDTOConstruction { private FunctionDTO createExpectedExternalLibraryFunctionDTO() { String functionName = externalLibraryMethod.getName(); - String sourceTypeName = externalLibraryMethod.getDeclaringClass().getSimpleName(); - String returnTypeName = externalLibraryMethod.getReturnType().getSimpleName(); + String sourceTypeName = externalLibraryMethod.getDeclaringClass().getName(); + String returnTypeName = externalLibraryMethod.getReturnType().getName(); List parameterTypeNames = new ArrayList<>(); String displayName = functionName; @@ -114,10 +114,10 @@ public class TestFunctionDTOConstruction { private FunctionDTO createFunctionDTOWithParameters() { String functionName = incrementMethod.getName(); - String sourceTypeName = incrementMethod.getDeclaringClass().getSimpleName(); - String returnTypeName = incrementMethod.getReturnType().getSimpleName(); + String sourceTypeName = incrementMethod.getDeclaringClass().getName(); + String returnTypeName = incrementMethod.getReturnType().getName(); List parameterTypeNames = new ArrayList<>(); - parameterTypeNames.add(int.class.getSimpleName()); + parameterTypeNames.add(int.class.getName()); String displayName = functionName; boolean isDimension = false; diff --git a/java/com.sap.sse.datamining/src/com/sap/sse/datamining/factories/DataMiningDTOFactory.java b/java/com.sap.sse.datamining/src/com/sap/sse/datamining/factories/DataMiningDTOFactory.java index df7801925c8..bc9d91aa6d0 100644 --- a/java/com.sap.sse.datamining/src/com/sap/sse/datamining/factories/DataMiningDTOFactory.java +++ b/java/com.sap.sse.datamining/src/com/sap/sse/datamining/factories/DataMiningDTOFactory.java @@ -39,8 +39,8 @@ public class DataMiningDTOFactory { private FunctionDTO createFunctionDTO(Function function, String displayName) { String functionName = function.getSimpleName(); - String sourceTypeName = function.getDeclaringType().getSimpleName(); - String returnTypeName = function.getReturnType().getSimpleName(); + String sourceTypeName = function.getDeclaringType().getName(); + String returnTypeName = function.getReturnType().getName(); List parameterTypeNames = getParameterTypeNames(function); return new FunctionDTO(function.isDimension(), functionName, sourceTypeName, returnTypeName, parameterTypeNames, displayName, function.getOrdinal()); } @@ -48,7 +48,7 @@ public class DataMiningDTOFactory { private List getParameterTypeNames(Function function) { List parameterTypeNames = new ArrayList<>(); for (Class parameterType : function.getParameters()) { - parameterTypeNames.add(parameterType.getSimpleName()); + parameterTypeNames.add(parameterType.getName()); } return parameterTypeNames; } @@ -72,8 +72,8 @@ public class DataMiningDTOFactory { private AggregationProcessorDefinitionDTO createAggregationProcessorDefinitionDTO(AggregationProcessorDefinition aggregatorDefinition, String displayName) { return new AggregationProcessorDefinitionDTO(aggregatorDefinition.getAggregationNameMessageKey(), - aggregatorDefinition.getExtractedType().getSimpleName(), - aggregatorDefinition.getAggregatedType().getSimpleName(), + aggregatorDefinition.getExtractedType().getName(), + aggregatorDefinition.getAggregatedType().getName(), displayName); } @@ -85,12 +85,12 @@ public class DataMiningDTOFactory { } return new DataRetrieverChainDefinitionDTO(dataRetrieverChainDefinition.getID(), dataRetrieverChainDefinition.getLocalizedName(locale, stringMessages), dataRetrieverChainDefinition - .getDataSourceType().getSimpleName(), retrieverLevels); + .getDataSourceType().getName(), retrieverLevels); } public DataRetrieverLevelDTO createDataRetrieverLevelDTO(DataRetrieverLevel retrieverLevel, ResourceBundleStringMessages stringMessages, Locale locale) { - String typeName = retrieverLevel.getRetrievedDataType().getSimpleName(); + String typeName = retrieverLevel.getRetrievedDataType().getName(); String displayName = retrieverLevel.getRetrievedDataTypeMessageKey() != null && !retrieverLevel.getRetrievedDataTypeMessageKey().isEmpty() ? stringMessages .get(locale, retrieverLevel.getRetrievedDataTypeMessageKey()) : typeName; From 7dd91ba5f232fab6c4d08f0dc5ccf30c0062204b Mon Sep 17 00:00:00 2001 From: Lennart Hensler Date: Tue, 13 Oct 2015 11:44:09 +0200 Subject: [PATCH 3/6] Added parameters to getName of DataMining-Methods and full qualified class names are used now --- .../shared/impl/dto/FunctionDTO.java | 15 +--- .../impl/functions/TestCompoundFunction.java | 2 +- .../TestFunctionDTOConstruction.java | 40 +++++------ .../functions/TestMethodWrappingFunction.java | 2 +- .../ConcatenatingCompoundFunction.java | 2 +- .../functions/MethodWrappingFunction.java | 70 +++++++++++-------- 6 files changed, 66 insertions(+), 65 deletions(-) diff --git a/java/com.sap.sse.datamining.shared/src/com/sap/sse/datamining/shared/impl/dto/FunctionDTO.java b/java/com.sap.sse.datamining.shared/src/com/sap/sse/datamining/shared/impl/dto/FunctionDTO.java index 3e1fced2afe..7bdb5e48351 100644 --- a/java/com.sap.sse.datamining.shared/src/com/sap/sse/datamining/shared/impl/dto/FunctionDTO.java +++ b/java/com.sap.sse.datamining.shared/src/com/sap/sse/datamining/shared/impl/dto/FunctionDTO.java @@ -69,20 +69,7 @@ public class FunctionDTO implements Serializable, Comparable { } public String toString() { - return (isDimension() ? "Dimension " : "Function ") + getSourceTypeName() + "." + getFunctionName() + "(" + parametersAsString() + ") : " + getReturnTypeName(); - } - - private String parametersAsString() { - StringBuilder parameterBuilder = new StringBuilder(); - boolean first = true; - for (String parameterTypeName : parameterTypeNames) { - if (!first) { - parameterBuilder.append(", "); - } - parameterBuilder.append(parameterTypeName); - first = false; - } - return parameterBuilder.toString(); + return (isDimension() ? "Dimension " : "Function ") + getSourceTypeName() + "." + getFunctionName() + " : " + getReturnTypeName(); } @Override diff --git a/java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/functions/TestCompoundFunction.java b/java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/functions/TestCompoundFunction.java index f142cc3a33e..35942421c61 100644 --- a/java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/functions/TestCompoundFunction.java +++ b/java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/functions/TestCompoundFunction.java @@ -49,7 +49,7 @@ public class TestCompoundFunction { //This is a workaround, because the assertion, that to types are equal checks for an instance of the given class instead. assertThat("The actual declaring class did'nt match the expected one.", compoundFunction.getDeclaringType().equals(MarkedContainer.class), is(true)); - assertThat(compoundFunction.getSimpleName(), is("getContainerElement -> getName")); + assertThat(compoundFunction.getSimpleName(), is("getContainerElement().getName()")); assertThat(compoundFunction.getLocalizedName(Locale.ENGLISH, TestsUtil.getTestStringMessages()), is("Name")); assertThat(compoundFunction.getResultDecimals(), is(0)); } diff --git a/java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/functions/TestFunctionDTOConstruction.java b/java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/functions/TestFunctionDTOConstruction.java index 783b367a6cc..5a41da75c33 100644 --- a/java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/functions/TestFunctionDTOConstruction.java +++ b/java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/functions/TestFunctionDTOConstruction.java @@ -40,16 +40,16 @@ public class TestFunctionDTOConstruction { public void testDimensionDTOConstruction() { Function dimension = FunctionTestsUtil.getFunctionFactory().createMethodWrappingFunction(dimensionMethod); - FunctionDTO expectedDimensionDTO = createExpectedDimensionDTO(); + FunctionDTO expectedDimensionDTO = createExpectedDimensionDTO(dimension); assertThat(FunctionTestsUtil.getDTOFactory().createFunctionDTO(dimension), is(expectedDimensionDTO)); assertThat(FunctionTestsUtil.getDTOFactory().createFunctionDTO(dimension, stringMessages, Locale.ENGLISH), is(expectedDimensionDTO)); assertThat(FunctionTestsUtil.getDTOFactory().createFunctionDTO(dimension, stringMessages, Locale.GERMAN), is(expectedDimensionDTO)); } - public FunctionDTO createExpectedDimensionDTO() { - String functionName = dimensionMethod.getName(); - String sourceTypeName = dimensionMethod.getDeclaringClass().getName(); - String returnTypeName = dimensionMethod.getReturnType().getName(); + public FunctionDTO createExpectedDimensionDTO(Function dimension) { + String functionName = dimension.getSimpleName(); + String sourceTypeName = dimension.getDeclaringType().getName(); + String returnTypeName = dimension.getReturnType().getName(); List parameterTypeNames = new ArrayList<>(); String displayName = functionName; @@ -63,15 +63,15 @@ public class TestFunctionDTOConstruction { public void testNullarySideEffectFreeValueDTOConstruction() { Function sideEffectFreeValue = FunctionTestsUtil.getFunctionFactory().createMethodWrappingFunction(sideEffectFreeValueMethod); - FunctionDTO expectedDTO = createExpectedNullarySideEffectFreeValueDTO(); + FunctionDTO expectedDTO = createExpectedNullarySideEffectFreeValueDTO(sideEffectFreeValue); assertThat(FunctionTestsUtil.getDTOFactory().createFunctionDTO(sideEffectFreeValue, stringMessages, Locale.ENGLISH), is(expectedDTO)); assertThat(FunctionTestsUtil.getDTOFactory().createFunctionDTO(sideEffectFreeValue, stringMessages, Locale.GERMAN), is(expectedDTO)); } - private FunctionDTO createExpectedNullarySideEffectFreeValueDTO() { - String functionName = sideEffectFreeValueMethod.getName(); - String sourceTypeName = sideEffectFreeValueMethod.getDeclaringClass().getName(); - String returnTypeName = sideEffectFreeValueMethod.getReturnType().getName(); + private FunctionDTO createExpectedNullarySideEffectFreeValueDTO(Function sideEffectFreeValue) { + String functionName = sideEffectFreeValue.getSimpleName(); + String sourceTypeName = sideEffectFreeValue.getDeclaringType().getName(); + String returnTypeName = sideEffectFreeValue.getReturnType().getName(); List parameterTypeNames = new ArrayList<>(); String displayName = functionName; @@ -85,15 +85,15 @@ public class TestFunctionDTOConstruction { public void testExternalLibraryFunctionDTOConstruction() { Function externalLibraryFunction = FunctionTestsUtil.getFunctionFactory().createMethodWrappingFunction(externalLibraryMethod); - FunctionDTO expectedDTO = createExpectedExternalLibraryFunctionDTO(); + FunctionDTO expectedDTO = createExpectedExternalLibraryFunctionDTO(externalLibraryFunction); assertThat(FunctionTestsUtil.getDTOFactory().createFunctionDTO(externalLibraryFunction, stringMessages, Locale.ENGLISH), is(expectedDTO)); assertThat(FunctionTestsUtil.getDTOFactory().createFunctionDTO(externalLibraryFunction, stringMessages, Locale.GERMAN), is(expectedDTO)); } - private FunctionDTO createExpectedExternalLibraryFunctionDTO() { - String functionName = externalLibraryMethod.getName(); - String sourceTypeName = externalLibraryMethod.getDeclaringClass().getName(); - String returnTypeName = externalLibraryMethod.getReturnType().getName(); + private FunctionDTO createExpectedExternalLibraryFunctionDTO(Function externalLibraryFunction) { + String functionName = externalLibraryFunction.getSimpleName(); + String sourceTypeName = externalLibraryFunction.getDeclaringType().getName(); + String returnTypeName = externalLibraryFunction.getReturnType().getName(); List parameterTypeNames = new ArrayList<>(); String displayName = functionName; @@ -107,15 +107,15 @@ public class TestFunctionDTOConstruction { public void testFunctionDTOConstructionForMethodWithParameters() { Function increment = FunctionTestsUtil.getFunctionFactory().createMethodWrappingFunction(incrementMethod); - FunctionDTO expectedDTO = createFunctionDTOWithParameters(); + FunctionDTO expectedDTO = createFunctionDTOWithParameters(increment); assertThat(FunctionTestsUtil.getDTOFactory().createFunctionDTO(increment, stringMessages, Locale.ENGLISH), is(expectedDTO)); assertThat(FunctionTestsUtil.getDTOFactory().createFunctionDTO(increment, stringMessages, Locale.GERMAN), is(expectedDTO)); } - private FunctionDTO createFunctionDTOWithParameters() { - String functionName = incrementMethod.getName(); - String sourceTypeName = incrementMethod.getDeclaringClass().getName(); - String returnTypeName = incrementMethod.getReturnType().getName(); + private FunctionDTO createFunctionDTOWithParameters(Function increment) { + String functionName = increment.getSimpleName(); + String sourceTypeName = increment.getDeclaringType().getName(); + String returnTypeName = increment.getReturnType().getName(); List parameterTypeNames = new ArrayList<>(); parameterTypeNames.add(int.class.getName()); diff --git a/java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/functions/TestMethodWrappingFunction.java b/java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/functions/TestMethodWrappingFunction.java index c3693c5d958..49744f33939 100644 --- a/java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/functions/TestMethodWrappingFunction.java +++ b/java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/functions/TestMethodWrappingFunction.java @@ -64,7 +64,7 @@ public class TestMethodWrappingFunction { assertThat(sideEffectFreeValue.getLocalizedName(Locale.GERMAN, stringMessages), is(expectedGermanName)); Function externalLibraryFunction = FunctionTestsUtil.getFunctionFactory().createMethodWrappingFunction(externalLibraryMethod); - String expectedName = "foo"; + String expectedName = "foo()"; assertThat(externalLibraryFunction.getLocalizedName(Locale.ENGLISH, stringMessages), is(expectedName)); assertThat(externalLibraryFunction.getLocalizedName(Locale.GERMAN, stringMessages), is(expectedName)); } diff --git a/java/com.sap.sse.datamining/src/com/sap/sse/datamining/impl/functions/ConcatenatingCompoundFunction.java b/java/com.sap.sse.datamining/src/com/sap/sse/datamining/impl/functions/ConcatenatingCompoundFunction.java index 118d4bbb4d3..0ed9e6c763b 100644 --- a/java/com.sap.sse.datamining/src/com/sap/sse/datamining/impl/functions/ConcatenatingCompoundFunction.java +++ b/java/com.sap.sse.datamining/src/com/sap/sse/datamining/impl/functions/ConcatenatingCompoundFunction.java @@ -19,7 +19,7 @@ import com.sap.sse.i18n.ResourceBundleStringMessages; */ public class ConcatenatingCompoundFunction extends AbstractFunction { - private static final String SIMPLE_NAME_CHAIN_CONNECTOR = " -> "; + private static final String SIMPLE_NAME_CHAIN_CONNECTOR = "."; private static final String LOCALIZED_NAME_CHAIN_CONNECTOR = " "; private final List> functions; diff --git a/java/com.sap.sse.datamining/src/com/sap/sse/datamining/impl/functions/MethodWrappingFunction.java b/java/com.sap.sse.datamining/src/com/sap/sse/datamining/impl/functions/MethodWrappingFunction.java index 99d71d71de0..7b34364e908 100644 --- a/java/com.sap.sse.datamining/src/com/sap/sse/datamining/impl/functions/MethodWrappingFunction.java +++ b/java/com.sap.sse.datamining/src/com/sap/sse/datamining/impl/functions/MethodWrappingFunction.java @@ -17,15 +17,15 @@ public class MethodWrappingFunction extends AbstractFunction returnType; private AdditionalMethodWrappingFunctionData additionalData; - + /** - * Throws an {@link IllegalArgumentException}, if the return type of the method and the given returnType - * aren't equal. + * Throws an {@link IllegalArgumentException}, if the return type of the method and the given + * returnType aren't equal. */ public MethodWrappingFunction(Method method, Class returnType) throws IllegalArgumentException { super(isMethodADimension(method)); checkThatReturnTypesMatch(method, returnType); - + this.method = method; this.returnType = returnType; initializeAdditionalData(); @@ -38,26 +38,29 @@ public class MethodWrappingFunction extends AbstractFunction returnType) { if (!method.getReturnType().equals(returnType)) { throw new IllegalArgumentException("The method return type " + method.getReturnType().getName() - + " and expected return type " + returnType.getName() + " don't match"); + + " and expected return type " + returnType.getName() + " don't match"); } } private void initializeAdditionalData() { additionalData = new AdditionalMethodWrappingFunctionData("", 0, Integer.MAX_VALUE); - + if (method.getAnnotation(Dimension.class) != null) { Dimension dimensionData = method.getAnnotation(Dimension.class); - additionalData = new AdditionalMethodWrappingFunctionData(dimensionData.messageKey(), 0, dimensionData.ordinal()); + additionalData = new AdditionalMethodWrappingFunctionData(dimensionData.messageKey(), 0, + dimensionData.ordinal()); } - + if (method.getAnnotation(Statistic.class) != null) { Statistic statisticData = method.getAnnotation(Statistic.class); - additionalData = new AdditionalMethodWrappingFunctionData(statisticData.messageKey(), statisticData.resultDecimals(), statisticData.ordinal()); + additionalData = new AdditionalMethodWrappingFunctionData(statisticData.messageKey(), + statisticData.resultDecimals(), statisticData.ordinal()); } - + if (method.getAnnotation(Connector.class) != null) { Connector connectorData = method.getAnnotation(Connector.class); - additionalData = new AdditionalMethodWrappingFunctionData(connectorData.messageKey(), 0, connectorData.ordinal()); + additionalData = new AdditionalMethodWrappingFunctionData(connectorData.messageKey(), 0, + connectorData.ordinal()); } } @@ -65,28 +68,29 @@ public class MethodWrappingFunction extends AbstractFunction getDeclaringType() { return method.getDeclaringClass(); } - + @Override public Iterable> getParameters() { return Arrays.asList(method.getParameterTypes()); } - + @Override public Class getReturnType() { return returnType; } - + @Override public ReturnType tryToInvoke(Object instance) { return tryToInvoke(instance, new Object[0]); } - + @Override public ReturnType tryToInvoke(Object instance, ParameterProvider parameterProvider) { return tryToInvoke(instance, parameterProvider.getParameters()); } - - @SuppressWarnings("unchecked") // The cast has to work, because the constructor checks, that the return types match + + @SuppressWarnings("unchecked") + // The cast has to work, because the constructor checks, that the return types match private ReturnType tryToInvoke(Object instance, Object... parameters) { if (instance != null) { try { @@ -102,7 +106,7 @@ public class MethodWrappingFunction extends AbstractFunction extends AbstractFunction parameterType : getParameters()) { + if (!first) { + parameterBuilder.append(", "); + } + parameterBuilder.append(parameterType.getName()); + first = false; + } + return parameterBuilder.toString(); + } + @Override public String getLocalizedName(Locale locale, ResourceBundleStringMessages stringMessages) { if (!isLocalizable()) { return getSimpleName(); } - String localizedName = ""; - if (!additionalData.getMessageKey().isEmpty()) { - localizedName = stringMessages.get(locale, additionalData.getMessageKey()); - } - return localizedName; + return stringMessages.get(locale, additionalData.getMessageKey()); } @Override public boolean isLocalizable() { return additionalData != null && (!additionalData.getMessageKey().isEmpty()); } - + @Override public String toString() { - return getDeclaringType().getSimpleName() + "." + method.getName() + "(" + parametersAsString() + ") : " + method.getReturnType().getSimpleName(); + return getDeclaringType().getSimpleName() + "." + method.getName() + "(" + parametersAsSimpleString() + ") : " + + method.getReturnType().getSimpleName(); } - private String parametersAsString() { + private String parametersAsSimpleString() { StringBuilder parameterBuilder = new StringBuilder(); boolean first = true; for (Class parameterType : getParameters()) { From 8a84e4e4f1671183e321cb3e8c3ff3e3755a91d6 Mon Sep 17 00:00:00 2001 From: Lennart Hensler Date: Tue, 13 Oct 2015 14:51:04 +0200 Subject: [PATCH 4/6] First attempt for group sorting --- .../sailing/gwt/ui/client/StringMessages.java | 6 +- .../gwt/ui/client/StringMessages.properties | 8 +- .../ui/client/StringMessages_de.properties | 8 +- .../ui/client/StringMessages_ru.properties | 8 +- .../AbstractResultsPresenter.java | 23 ++++ .../datamining/presentation/ResultsChart.java | 125 +++++++++++++++--- 6 files changed, 153 insertions(+), 25 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java index 9bdf2b324cf..f450869c19a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java @@ -1244,7 +1244,7 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, c String distanceTraveledIncludingGateStartTooltip(); String raceDistanceTraveledIncludingGateStartTooltip(); String results(); - String group(); + String groupName(); String valueAscending(); String valueDescending(); String sortBy(); @@ -1410,4 +1410,8 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, c String flightsCount(@PluralCount(DefaultRule_1_0n.class) int count); String viewQueryDefinition(); String queryDefinitionViewer(); + String groupAverageAscending(); + String groupAverageDescending(); + String groupMedianAscending(); + String groupMedianDescending(); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties index 3de6062dfdc..9531f3c3574 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties @@ -1212,7 +1212,7 @@ distanceIncludingGateStartInMeters=Distance (w/ Gate Start) distanceTraveledIncludingGateStartTooltip=The distance traveled from the leg start to the end\nor to the current time point, if the leg isn''t finished.\nIf the leg includes a gate start, the distance from the pin end to the starting position is included\nto make competitors comparable even when started at different times. raceDistanceTraveledIncludingGateStartTooltip=The distance traveled from the race start to the end\nor to the current time point, if the race isn''t finished. For a gate start, the distance from the pin end to the starting position is included\nto make competitors comparable even when started at different times. results=Results -group=Group +groupName=Group Name valueAscending=Value (Ascending) valueDescending=Value (Descending) sortBy=Sort by @@ -1381,4 +1381,8 @@ smartphoneTracking=Smartphone Tracking flightsCount={0,number} flights flightsCount[one]={0,number} flight viewQueryDefinition=View Query Definition -queryDefinitionViewer=Query Definition Viewer \ No newline at end of file +queryDefinitionViewer=Query Definition Viewer +groupAverageAscending=Group Average (Ascending) +groupAverageDescending=Group Average (Descending) +groupMedianAscending=Group Median (Ascending) +groupMedianDescending=Group Median (Descending) \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties index 318c02a6956..579b458e57f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties @@ -1201,7 +1201,7 @@ distanceIncludingGateStartInMeters=Distanz (m. Torstart) distanceTraveledIncludingGateStartTooltip=Die zurückgelegt Strecke vom Start des Schenkels bis zum Ende\noder bis zum aktuellen Zeitpunkt, falls der Schenkel noch nicht beendet ist.\nEnthält der Schenkel einen Torstart, so wird die Distanz vom Pin End bis zur Startposition des Teilnehmers hinzugezählt,\num so vergleichbare Distanzen auch für Teilneher zu erhalten, die zu verschiedenen Zeiten gestartet sind. raceDistanceTraveledIncludingGateStartTooltip=Die zurückgelegte Strecke vom Start des Rennens, bis zum Ende\noder bis zum aktuellen Zeitpunkt, falls das Rennen noch nicht beendet ist. Bei einem Torstart wird die Distanz vom Pin End bis zur Startposition des Teilnehmers hinzugezählt,\num so vergleichbare Distanzen auch für Teilneher zu erhalten, die zu verschiedenen Zeiten gestartet sind. results=Ergebnisse -group=Gruppe +groupName=Gruppename valueAscending=Wert (Aufsteigend) valueDescending=Wert (Absteigend) sortBy=Sortiert nach @@ -1370,4 +1370,8 @@ smartphoneTracking=Smartphone Tracking flightsCount={0,number} Läufe flightsCount[one]={0,number} Lauf viewQueryDefinition=Query Definition anzeigen -queryDefinitionViewer=Query Definition Anzeiger \ No newline at end of file +queryDefinitionViewer=Query Definition Anzeiger +groupAverageAscending=Gruppe Durchschnitt (Aufsteigend) +groupAverageDescending=Gruppe Durchschnitt (Absteigend) +groupMedianAscending=Gruppe Median (Aufsteigend) +groupMedianDescending=Gruppe Median (Absteigend) \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties index dc9dfeead1a..8101a6d836c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties @@ -1145,7 +1145,7 @@ distanceIncludingGateStartInMeters=Distance (w/ Gate Start) distanceTraveledIncludingGateStartTooltip=The distance traveled from the leg start to the end\nor to the current time point, if the leg isn''t finished.\nIf the leg includes a gate start, the distance from the pin end to the starting position is included\nto make competitors comparable even when started at different times. raceDistanceTraveledIncludingGateStartTooltip=The distance traveled from the race start to the end\nor to the current time point, if the race isn''t finished. For a gate start, the distance from the pin end to the starting position is included\nto make competitors comparable even when started at different times. results=Results -group=Group +groupName=Group Name valueAscending=Value (Ascending) valueDescending=Value (Descending) sortBy=Sort by @@ -1310,4 +1310,8 @@ actionAnalyze=Analyze viewQueryDefinition=View Query Definition queryDefinitionViewer=Query Definition Viewer flightsCount={0,number} flights -flightsCount[one]={0,number} flight \ No newline at end of file +flightsCount[one]={0,number} flight +groupAverageAscending=Group Average (Ascending) +groupAverageDescending=Group Average (Descending) +groupMedianAscending=Group Median (Ascending) +groupMedianDescending=Group Median (Descending) \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/datamining/presentation/AbstractResultsPresenter.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/datamining/presentation/AbstractResultsPresenter.java index 727653b0f8b..7462c4dabc7 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/datamining/presentation/AbstractResultsPresenter.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/datamining/presentation/AbstractResultsPresenter.java @@ -16,6 +16,7 @@ import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.controls.AbstractObjectRenderer; import com.sap.sailing.gwt.ui.datamining.ResultsPresenterWithControls; import com.sap.sse.common.settings.Settings; +import com.sap.sse.datamining.shared.GroupKey; import com.sap.sse.datamining.shared.impl.dto.QueryResultDTO; public abstract class AbstractResultsPresenter implements ResultsPresenterWithControls { @@ -34,6 +35,7 @@ public abstract class AbstractResultsPresenter im private final HTML labeledBusyIndicator; private QueryResultDTO currentResult; + private boolean isCurrentResultSimple; public AbstractResultsPresenter(StringMessages stringMessages) { this.stringMessages = stringMessages; @@ -99,11 +101,13 @@ public abstract class AbstractResultsPresenter im } this.currentResult = result; + updateIsCurrentResultSimple(); internalShowResults(getCurrentResult()); } else { this.currentResult = null; + updateIsCurrentResultSimple(); showError(getStringMessages().noDataFound() + "."); } } @@ -121,6 +125,7 @@ public abstract class AbstractResultsPresenter im } currentResult = null; + updateIsCurrentResultSimple(); presentationPanel.setWidget(errorLabel); } @@ -142,6 +147,24 @@ public abstract class AbstractResultsPresenter im } currentResult = null; + updateIsCurrentResultSimple(); + } + + private void updateIsCurrentResultSimple() { + if (currentResult != null) { + for (GroupKey groupKey : getCurrentResult().getResults().keySet()) { + if (groupKey.hasSubKey()) { + isCurrentResultSimple = false; + } + } + isCurrentResultSimple = true; + } else { + isCurrentResultSimple = false; + } + } + + protected boolean isCurrentResultSimple() { + return isCurrentResultSimple; } protected StringMessages getStringMessages() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/datamining/presentation/ResultsChart.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/datamining/presentation/ResultsChart.java index 71a02206cbc..10f6ba57dc1 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/datamining/presentation/ResultsChart.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/datamining/presentation/ResultsChart.java @@ -48,7 +48,7 @@ public class ResultsChart extends AbstractResultsPresenterWithDataProviders ascendingByValueKeyComparator = new Comparator() { @@ -73,6 +73,46 @@ public class ResultsChart extends AbstractResultsPresenterWithDataProviders ascendingByGroupAverageComparator = new Comparator() { + @Override + public int compare(GroupKey key1, GroupKey key2) { + GroupKey mainKey1 = key1.getMainKey(); + GroupKey mainKey2 = key2.getMainKey(); + return Double.compare(averagePerMainKey.get(mainKey1), averagePerMainKey.get(mainKey2)); + } + public String toString() { + return getStringMessages().groupAverageAscending(); + }; + }; + private final Comparator descendingByGroupAverageComparator = new Comparator() { + @Override + public int compare(GroupKey key1, GroupKey key2) { + return -1 * ascendingByGroupAverageComparator.compare(key1, key2); + } + public String toString() { + return getStringMessages().groupAverageDescending(); + }; + }; + private final Comparator ascendingByGroupMedianComparator = new Comparator() { + @Override + public int compare(GroupKey key1, GroupKey key2) { + GroupKey mainKey1 = key1.getMainKey(); + GroupKey mainKey2 = key2.getMainKey(); + return Double.compare(medianPerMainKey.get(mainKey1), medianPerMainKey.get(mainKey2)); + } + public String toString() { + return getStringMessages().groupMedianAscending(); + }; + }; + private final Comparator descendingByGroupMedianComparator = new Comparator() { + @Override + public int compare(GroupKey key1, GroupKey key2) { + return -1 * ascendingByGroupMedianComparator.compare(key1, key2); + } + public String toString() { + return getStringMessages().groupMedianDescending(); + }; + }; private final HorizontalPanel sortByPanel; private final ValueListBox> keyComparatorListBox; @@ -80,11 +120,14 @@ public class ResultsChart extends AbstractResultsPresenterWithDataProviders seriesMappedByGroupKey; + private final Map seriesMappedByGroupKey; private final GroupKey simpleResultSeriesKey; - private Map mainKeyToXValueMap; + private final Map mainKeyToXValueMap; private Map currentResultValues; + private final Map averagePerMainKey; + private final Map medianPerMainKey; + public ResultsChart(StringMessages stringMessages) { super(stringMessages); @@ -137,6 +180,9 @@ public class ResultsChart extends AbstractResultsPresenterWithDataProviders(); simpleResultSeriesKey = new GenericGroupKey(stringMessages.results()); + mainKeyToXValueMap = new HashMap<>(); + averagePerMainKey = new HashMap<>(); + medianPerMainKey = new HashMap<>(); } @Override @@ -159,10 +205,17 @@ public class ResultsChart extends AbstractResultsPresenterWithDataProviders valueToBeSelected = standardKeyComparator; Collection> acceptableValues = new ArrayList<>(); acceptableValues.add(valueToBeSelected); - if (getCurrentResult() != null && isCurrentResultSimple()) { + if (getCurrentResult() != null) { valueToBeSelected = getKeyComparator() != null ? getKeyComparator() : valueToBeSelected; - acceptableValues.add(ascendingByValueKeyComparator); - acceptableValues.add(descendingByValueKeyComparator); + if (isCurrentResultSimple()) { + acceptableValues.add(ascendingByValueKeyComparator); + acceptableValues.add(descendingByValueKeyComparator); + } else { + acceptableValues.add(ascendingByGroupAverageComparator); + acceptableValues.add(descendingByGroupAverageComparator); + acceptableValues.add(ascendingByGroupMedianComparator); + acceptableValues.add(descendingByGroupMedianComparator); + } visible = true; } keyComparatorListBox.setValue(valueToBeSelected); @@ -170,18 +223,9 @@ public class ResultsChart extends AbstractResultsPresenterWithDataProviders(); + seriesMappedByGroupKey.clear(); } private void updateChartLabels() { @@ -198,21 +242,66 @@ public class ResultsChart extends AbstractResultsPresenterWithDataProviders> valuesPerMainKey = new HashMap<>(); for (Entry resultEntry : currentResultValues.entrySet()) { GroupKey mainKey = resultEntry.getKey().getMainKey(); - Point point = new Point(mainKeyToXValueMap.get(mainKey), resultEntry.getValue()); + Number value = resultEntry.getValue(); + + if (!isCurrentResultSimple()) { + if (!valuesPerMainKey.containsKey(mainKey)) { + valuesPerMainKey.put(mainKey, new ArrayList()); + } + valuesPerMainKey.get(mainKey).add(value); + } + + Point point = new Point(mainKeyToXValueMap.get(mainKey), value); point.setName(mainKey.asString()); seriesMappedByGroupKey.get(groupKeyToSeriesKey(resultEntry.getKey())) .addPoint(point, false, false, false); } + averagePerMainKey.clear(); + medianPerMainKey.clear(); + if (!isCurrentResultSimple()) { + for (GroupKey mainKey : valuesPerMainKey.keySet()) { + List values = valuesPerMainKey.get(mainKey); + averagePerMainKey.put(mainKey, getAverageFromValues(values)); + medianPerMainKey.put(mainKey, getMedianFromValues(values)); + } + } + chart.redraw(); } + private Double getAverageFromValues(Collection values) { + double sum = 0; + for (Number value : values) { + sum += value.doubleValue(); + } + return sum / values.size(); + } + + private Double getMedianFromValues(List values) { + Collections.sort(values, new Comparator() { + @Override + public int compare(Number n1, Number n2) { + return Double.compare(n1.doubleValue(), n2.doubleValue()); + } + }); + if (values.size() % 2 == 0) { + int index1 = (values.size() / 2) - 1; + int index2 = index1 + 1; + return (values.get(index1).doubleValue() + values.get(index2).doubleValue()) / 2; + } else { + int index = ((values.size() + 1) / 2) - 1; + return values.get(index).doubleValue(); + } + } + private void buildMainKeyMapAndSetXAxisCategories() { List sortedMainKeys = getSortedMainKeys(); String[] categories = new String[sortedMainKeys.size()]; - mainKeyToXValueMap = new HashMap<>(); + mainKeyToXValueMap.clear(); for (int i = 0; i < sortedMainKeys.size(); i++) { GroupKey mainKey = sortedMainKeys.get(i); categories[i] = mainKey.asString(); From b8d791007b1beb762f58998883c03322f4b645b4 Mon Sep 17 00:00:00 2001 From: Lennart Hensler Date: Tue, 13 Oct 2015 17:23:15 +0200 Subject: [PATCH 5/6] Fixed the method isCurrentResultSimple() in AbstractResultsPresenter --- .../presentation/AbstractResultsPresenter.java | 10 +++++----- .../gwt/ui/datamining/presentation/ResultsChart.java | 1 - 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/datamining/presentation/AbstractResultsPresenter.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/datamining/presentation/AbstractResultsPresenter.java index 7462c4dabc7..c61343c3b4d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/datamining/presentation/AbstractResultsPresenter.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/datamining/presentation/AbstractResultsPresenter.java @@ -104,7 +104,6 @@ public abstract class AbstractResultsPresenter im updateIsCurrentResultSimple(); internalShowResults(getCurrentResult()); - } else { this.currentResult = null; updateIsCurrentResultSimple(); @@ -151,16 +150,17 @@ public abstract class AbstractResultsPresenter im } private void updateIsCurrentResultSimple() { + boolean isSimple = false; if (currentResult != null) { + isSimple = true; for (GroupKey groupKey : getCurrentResult().getResults().keySet()) { if (groupKey.hasSubKey()) { - isCurrentResultSimple = false; + isSimple = false; + break; } } - isCurrentResultSimple = true; - } else { - isCurrentResultSimple = false; } + isCurrentResultSimple = isSimple; } protected boolean isCurrentResultSimple() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/datamining/presentation/ResultsChart.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/datamining/presentation/ResultsChart.java index 10f6ba57dc1..fed2ca0a63d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/datamining/presentation/ResultsChart.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/datamining/presentation/ResultsChart.java @@ -206,7 +206,6 @@ public class ResultsChart extends AbstractResultsPresenterWithDataProviders> acceptableValues = new ArrayList<>(); acceptableValues.add(valueToBeSelected); if (getCurrentResult() != null) { - valueToBeSelected = getKeyComparator() != null ? getKeyComparator() : valueToBeSelected; if (isCurrentResultSimple()) { acceptableValues.add(ascendingByValueKeyComparator); acceptableValues.add(descendingByValueKeyComparator); From 271a32750b1dc056e50e778d2d45da0a794d4dc7 Mon Sep 17 00:00:00 2001 From: Lennart Hensler Date: Wed, 14 Oct 2015 10:02:50 +0200 Subject: [PATCH 6/6] Fixed the SailingGWT.launch --- java/com.sap.sailing.gwt.ui/SailingGWT.launch | 1 + 1 file changed, 1 insertion(+) diff --git a/java/com.sap.sailing.gwt.ui/SailingGWT.launch b/java/com.sap.sailing.gwt.ui/SailingGWT.launch index c421871c83d..9d6b95e813a 100755 --- a/java/com.sap.sailing.gwt.ui/SailingGWT.launch +++ b/java/com.sap.sailing.gwt.ui/SailingGWT.launch @@ -64,6 +64,7 @@ +