java/com.sap.sailing.polars/src/com/sap/sailing/polars/impl/PolarDataServiceImpl.java
... ...
@@ -74,6 +74,13 @@ public class PolarDataServiceImpl extends AbstractReplicableWithObjectInputStrea
74 74
resetState();
75 75
}
76 76
77
+ public PolarDataServiceImpl filterToBoatClasses(Iterable<BoatClass> boatClassesToFilterTo) {
78
+ final PolarDataMiner filteredPolarDataMiner = polarDataMiner.filterToBoatClasses(boatClassesToFilterTo);
79
+ final PolarDataServiceImpl filteredService = new PolarDataServiceImpl();
80
+ filteredService.polarDataMiner = filteredPolarDataMiner;
81
+ return filteredService;
82
+ }
83
+
77 84
@Override
78 85
public void resetState() {
79 86
PolarSheetGenerationSettings settings = PolarSheetGenerationSettingsImpl.createBackendPolarSettings();
java/com.sap.sailing.polars/src/com/sap/sailing/polars/jaxrs/api/PolarDataResource.java
... ...
@@ -2,11 +2,13 @@ package com.sap.sailing.polars.jaxrs.api;
2 2
3 3
import java.io.IOException;
4 4
import java.io.OutputStream;
5
+import java.util.List;
5 6
import java.util.logging.Logger;
6 7
7 8
import javax.ws.rs.GET;
8 9
import javax.ws.rs.Path;
9 10
import javax.ws.rs.Produces;
11
+import javax.ws.rs.QueryParam;
10 12
import javax.ws.rs.WebApplicationException;
11 13
import javax.ws.rs.core.Response;
12 14
import javax.ws.rs.core.StreamingOutput;
... ...
@@ -14,9 +16,12 @@ import javax.ws.rs.core.StreamingOutput;
14 16
import org.apache.shiro.SecurityUtils;
15 17
import org.apache.shiro.subject.Subject;
16 18
19
+import com.sap.sailing.domain.base.BoatClass;
17 20
import com.sap.sailing.domain.common.security.SecuredDomainType;
21
+import com.sap.sailing.polars.impl.PolarDataServiceImpl;
18 22
import com.sap.sailing.polars.jaxrs.AbstractPolarResource;
19 23
import com.sap.sse.ServerInfo;
24
+import com.sap.sse.common.Util;
20 25
import com.sap.sse.security.shared.HasPermissions.DefaultActions;
21 26
import com.sap.sse.security.shared.TypeRelativeObjectIdentifier;
22 27
... ...
@@ -26,7 +31,7 @@ public class PolarDataResource extends AbstractPolarResource {
26 31
27 32
@GET
28 33
@Produces("application/octet-stream;charset=UTF-8")
29
- public Response getRegressions() throws IOException {
34
+ public Response getRegressions(@QueryParam("boatClassName") final List<String> boatClassNames) throws IOException {
30 35
final Subject subject = SecurityUtils.getSubject();
31 36
logger.info("Polar Data requested by "+ (subject.getPrincipal() == null ? "anonymous user" : subject.getPrincipal().toString()));
32 37
subject.checkPermission(SecuredDomainType.POLAR_DATA.getStringPermissionForTypeRelativeIdentifier(DefaultActions.READ,
... ...
@@ -34,7 +39,24 @@ public class PolarDataResource extends AbstractPolarResource {
34 39
return Response.ok(new StreamingOutput() {
35 40
@Override
36 41
public void write(OutputStream output) throws IOException, WebApplicationException {
37
- getPolarDataServiceImpl().serializeForInitialReplication(output);
42
+ PolarDataServiceImpl polarDataService = getPolarDataServiceImpl();
43
+ @SuppressWarnings("unchecked")
44
+ final Iterable<BoatClass>[] boatClassesToFilterTo = new Iterable[1];
45
+ if (boatClassNames == null || boatClassNames.isEmpty()) {
46
+ boatClassesToFilterTo[0] = null;
47
+ } else {
48
+ try {
49
+ polarDataService.runWithDomainFactory(domainFactory->{
50
+ boatClassesToFilterTo[0] = Util.map(boatClassNames, bcn->domainFactory.getBoatClass(bcn));
51
+ });
52
+ } catch (InterruptedException e) {
53
+ throw new RuntimeException(e);
54
+ }
55
+ }
56
+ if (boatClassesToFilterTo[0] != null) {
57
+ polarDataService = polarDataService.filterToBoatClasses(boatClassesToFilterTo[0]);
58
+ }
59
+ polarDataService.serializeForInitialReplication(output);
38 60
}
39 61
}).header("Content-Type", "application/octet-stream").build();
40 62
}
java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/CubicRegressionPerCourseProcessor.java
... ...
@@ -18,11 +18,13 @@ import com.sap.sailing.domain.common.Tack;
18 18
import com.sap.sailing.domain.common.polars.NotEnoughDataHasBeenAddedException;
19 19
import com.sap.sailing.domain.polars.PolarsChangedListener;
20 20
import com.sap.sse.common.Speed;
21
+import com.sap.sse.common.Util;
21 22
import com.sap.sse.datamining.components.AdditionalResultDataBuilder;
22 23
import com.sap.sse.datamining.components.Processor;
23 24
import com.sap.sse.datamining.factories.GroupKeyFactory;
24 25
import com.sap.sse.datamining.impl.components.GroupedDataEntry;
25 26
import com.sap.sse.datamining.shared.GroupKey;
27
+import com.sap.sse.datamining.shared.impl.GenericGroupKey;
26 28
27 29
/**
28 30
* Groups incoming fixes by boatclass and legtype into {@link AngleAndSpeedRegression} instances and
... ...
@@ -45,6 +47,40 @@ public class CubicRegressionPerCourseProcessor implements
45 47
*/
46 48
private transient ConcurrentMap<BoatClass, Set<PolarsChangedListener>> listeners;
47 49
50
+ public CubicRegressionPerCourseProcessor filterToBoatClasses(Iterable<BoatClass> boatClasses) {
51
+ final Set<BoatClass> allowedBoatClasses = Util.asSet(boatClasses);
52
+ final CubicRegressionPerCourseProcessor filteredProcessor = new CubicRegressionPerCourseProcessor();
53
+ for (final Map.Entry<GroupKey, AngleAndSpeedRegression> entry : regressions.entrySet()) {
54
+ GroupKey key = entry.getKey();
55
+ BoatClass boatClass = extractBoatClass(key);
56
+ if (boatClass != null && allowedBoatClasses.contains(boatClass)) {
57
+ filteredProcessor.regressions.put(key, entry.getValue());
58
+ }
59
+ }
60
+ return filteredProcessor;
61
+ }
62
+
63
+ private BoatClass extractBoatClass(GroupKey key) {
64
+ final BoatClass result;
65
+ if (key.hasSubKeys()) {
66
+ // In the compound key, BoatClass is the second dimension (index 1)
67
+ GroupKey boatClassKey = key.getKeys().get(1);
68
+ if (boatClassKey instanceof GenericGroupKey) {
69
+ Object value = ((GenericGroupKey<?>) boatClassKey).getValue();
70
+ if (value instanceof BoatClass) {
71
+ result = (BoatClass) value;
72
+ } else {
73
+ result = null;
74
+ }
75
+ } else {
76
+ result = null;
77
+ }
78
+ } else {
79
+ result = null;
80
+ }
81
+ return result;
82
+ }
83
+
48 84
@Override
49 85
public boolean canProcessElements() {
50 86
return true;
... ...
@@ -109,7 +145,6 @@ public class CubicRegressionPerCourseProcessor implements
109 145
110 146
private GroupKey createGroupKey(final BoatClass boatClass, final LegType legType) {
111 147
LegTypePolarClusterKey key = new LegTypePolarClusterKey() {
112
-
113 148
@Override
114 149
public BoatClass getBoatClass() {
115 150
return boatClass;
java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/PolarDataDimensionCollectionFactory.java
... ...
@@ -40,7 +40,6 @@ public class PolarDataDimensionCollectionFactory {
40 40
Collection<Function<?>> dimensions = new ArrayList<>();
41 41
FunctionFactory functionFactory = new FunctionFactory();
42 42
addTackAndLegTypeDimensions(dimensions, functionFactory);
43
-
44 43
addPolarBaseDimension(dimensions, functionFactory);
45 44
return dimensions;
46 45
}
java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/PolarDataMiner.java
... ...
@@ -136,6 +136,13 @@ public class PolarDataMiner {
136 136
throw new RuntimeException(e);
137 137
}
138 138
}
139
+
140
+ public PolarDataMiner filterToBoatClasses(Iterable<BoatClass> boatClasses) {
141
+ return new PolarDataMiner(backendPolarSheetGenerationSettings,
142
+ cubicRegressionPerCourseProcessor.filterToBoatClasses(boatClasses),
143
+ speedRegressionPerAngleClusterProcessor.filterToBoatClasses(boatClasses),
144
+ angleClusterGroup);
145
+ }
139 146
140 147
private void setUpWorkflow() throws ClassCastException, NoSuchMethodException, SecurityException {
141 148
Collection<Processor<GroupedDataEntry<GPSFixMovingWithPolarContext>, ?>> regressionPerCourseGrouperResultReceivers = new ArrayList<Processor<GroupedDataEntry<GPSFixMovingWithPolarContext>, ?>>();
java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/SpeedRegressionPerAngleClusterProcessor.java
... ...
@@ -23,6 +23,7 @@ import com.sap.sailing.polars.regression.IncrementalLeastSquares;
23 23
import com.sap.sailing.polars.regression.impl.IncrementalAnyOrderLeastSquaresImpl;
24 24
import com.sap.sse.common.Bearing;
25 25
import com.sap.sse.common.Speed;
26
+import com.sap.sse.common.Util;
26 27
import com.sap.sse.common.Util.Pair;
27 28
import com.sap.sse.common.impl.DegreeBearingImpl;
28 29
import com.sap.sse.datamining.components.AdditionalResultDataBuilder;
... ...
@@ -32,6 +33,7 @@ import com.sap.sse.datamining.data.ClusterGroup;
32 33
import com.sap.sse.datamining.factories.GroupKeyFactory;
33 34
import com.sap.sse.datamining.impl.components.GroupedDataEntry;
34 35
import com.sap.sse.datamining.shared.GroupKey;
36
+import com.sap.sse.datamining.shared.impl.GenericGroupKey;
35 37
36 38
/**
37 39
* Holds one speed regression per BoatClass, WindSpeed, Beat Angle Range combination and provides means for adding and
... ...
@@ -63,6 +65,49 @@ public class SpeedRegressionPerAngleClusterProcessor implements
63 65
this.angleClusterGroup = angleClusterGroup;
64 66
}
65 67
68
+ public SpeedRegressionPerAngleClusterProcessor filterToBoatClasses(Iterable<BoatClass> boatClasses) {
69
+ final Set<BoatClass> allowedBoatClasses = Util.asSet(boatClasses);
70
+ final SpeedRegressionPerAngleClusterProcessor filteredProcessor = new SpeedRegressionPerAngleClusterProcessor(angleClusterGroup);
71
+ synchronized (regressions) {
72
+ for (Map.Entry<GroupKey, IncrementalLeastSquares> entry : regressions.entrySet()) {
73
+ GroupKey key = entry.getKey();
74
+ BoatClass boatClass = extractBoatClass(key);
75
+ if (boatClass != null && allowedBoatClasses.contains(boatClass)) {
76
+ filteredProcessor.regressions.put(key, entry.getValue());
77
+ }
78
+ }
79
+ }
80
+ synchronized (fixCountPerBoatClass) {
81
+ for (Map.Entry<BoatClass, Long> entry : fixCountPerBoatClass.entrySet()) {
82
+ if (allowedBoatClasses.contains(entry.getKey())) {
83
+ filteredProcessor.fixCountPerBoatClass.put(entry.getKey(), entry.getValue());
84
+ }
85
+ }
86
+ }
87
+ return filteredProcessor;
88
+ }
89
+
90
+ private BoatClass extractBoatClass(GroupKey key) {
91
+ final BoatClass result;
92
+ if (key.hasSubKeys()) {
93
+ // In the compound key, BoatClass is the first dimension (index 0)
94
+ GroupKey boatClassKey = key.getKeys().get(0);
95
+ if (boatClassKey instanceof GenericGroupKey) {
96
+ Object value = ((GenericGroupKey<?>) boatClassKey).getValue();
97
+ if (value instanceof BoatClass) {
98
+ result = (BoatClass) value;
99
+ } else {
100
+ result = null;
101
+ }
102
+ } else {
103
+ result = null;
104
+ }
105
+ } else {
106
+ result = null;
107
+ }
108
+ return result;
109
+ }
110
+
66 111
@Override
67 112
public boolean canProcessElements() {
68 113
// TODO Auto-generated method stub