basic bundles and draft version of yachtscoring result importer (XRR)

This commit is contained in:
fmittag
2016-03-10 15:54:48 +01:00
parent 5e92ad226e
commit 633ca7d803
39 changed files with 3426 additions and 523 deletions
+7
View File
@@ -247,6 +247,13 @@ Computes leaderboard information for sailing races and offers RESTful APIs to al
version="0.0.0"
unpack="false"/>
<plugin
id="com.sap.sailing.yachtscoring.resultimport"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="com.sap.sailing.velum.resultimport"
download-size="0"
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="resources"/>
<classpathentry kind="output" path="bin"/>
</classpath>
@@ -0,0 +1,2 @@
bin/
/bin
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>com.sap.sailing.yachtscoring.resultimport.test</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
@@ -0,0 +1,12 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.8
@@ -0,0 +1,3 @@
eclipse.preferences.version=1
pluginProject.extensions=false
resolve.requirebundle=false
@@ -0,0 +1,21 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Yachtscoring result import tests
Bundle-SymbolicName: com.sap.sailing.yachtscoring.resultimport.test
Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: SAP
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Import-Package: com.sap.sailing.domain.common,
com.sap.sailing.domain.leaderboard,
com.sap.sailing.domain.persistence,
com.sap.sailing.server,
com.sap.sailing.server.impl,
com.sap.sailing.xrr.schema,
org.osgi.framework;version="1.5.0"
Fragment-Host: com.sap.sailing.yachtscoring.resultimport
Require-Bundle: org.junit4;bundle-version="4.8.2",
com.sap.sse.common,
org.mockito.mockito-core;bundle-version="1.9.5",
org.objenesis;bundle-version="1.3.0",
org.hamcrest;bundle-version="1.1.0",
com.sap.sse
@@ -0,0 +1,5 @@
source.. = src/,\
resources/
output.. = bin/
bin.includes = META-INF/,\
.
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>root</artifactId>
<groupId>com.sap.sailing</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>com.sap.sailing.yachtscoring.resultimport.test</artifactId>
<packaging>eclipse-test-plugin</packaging>
</project>
@@ -0,0 +1,39 @@
package com.sap.sailing.yachtscoring.resultimport.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import org.junit.Test;
import com.sap.sailing.yachtscoring.EventResultDescriptor;
import com.sap.sailing.yachtscoring.YachtscoringEventResultsParserImpl;
public class EventResultJsonServiceTest {
private static final String EVENT_RESULTS_JSON = "eventResults.json";
private static final String RESOURCES = "resources/";
@Test
public void testParsingEventResultsFromJson() throws IOException {
YachtscoringEventResultsParserImpl parser = new YachtscoringEventResultsParserImpl();
EventResultDescriptor eventResult = parser.getEventResult(getInputStream(EVENT_RESULTS_JSON));
assertNotNull(eventResult);
assertEquals(14, eventResult.getRegattaResults().size());
}
private InputStream getInputStream(String filename) throws FileNotFoundException, IOException {
return new FileInputStream(getFile(filename));
}
private File getFile(String filename) {
return new File(RESOURCES + filename);
}
}
@@ -0,0 +1,118 @@
package com.sap.sailing.yachtscoring.resultimport.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Mockito.mock;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.xml.bind.DatatypeConverter;
import javax.xml.bind.JAXBException;
import javax.xml.parsers.ParserConfigurationException;
import org.junit.Test;
import org.xml.sax.SAXException;
import com.sap.sailing.domain.persistence.DomainObjectFactory;
import com.sap.sailing.domain.persistence.MongoObjectFactory;
import com.sap.sailing.resultimport.ResultDocumentDescriptor;
import com.sap.sailing.resultimport.ResultDocumentProvider;
import com.sap.sailing.resultimport.ResultUrlRegistry;
import com.sap.sailing.resultimport.impl.ResultDocumentDescriptorImpl;
import com.sap.sailing.resultimport.impl.ResultUrlRegistryImpl;
import com.sap.sailing.xrr.resultimport.ParserFactory;
import com.sap.sailing.xrr.schema.RegattaResults;
import com.sap.sailing.yachtscoring.resultimport.ScoreCorrectionProviderImpl;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.impl.MillisecondsTimePoint;
public class ParserTest {
private static final String SAMPLE_INPUT_NAME_KEYWESTRACEWEEEK = "event1390_KeyWestRaceWeek2016_xrr.xml";
private static final String KEYWESTRACEWEEEK_EVENT_NAME = "Key West Race Week 2016";
private static final String ISAF_ID_29ER = "29ER";
private static final String RESOURCES = "resources/";
private InputStream getInputStream(String filename) throws FileNotFoundException, IOException {
return new FileInputStream(getFile(filename));
}
private File getFile(String filename) {
return new File(RESOURCES + filename);
}
private ResultDocumentProvider getTestDocumentProvider() {
return new ResultDocumentProvider() {
@Override
public Iterable<ResultDocumentDescriptor> getResultDocumentDescriptors() throws IOException {
try {
List<ResultDocumentDescriptor> result = new ArrayList<ResultDocumentDescriptor>();
Date _29erDate = DatatypeConverter.parseDateTime("2016-01-19T12:55:08.000Z").getTime();
result.add(new ResultDocumentDescriptorImpl(getInputStream(SAMPLE_INPUT_NAME_KEYWESTRACEWEEEK),
null, new MillisecondsTimePoint(_29erDate), KEYWESTRACEWEEEK_EVENT_NAME , null, ISAF_ID_29ER));
return result;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
};
}
@Test
public void testSimpleParsingSomeYachtscoringDocuments() throws JAXBException, IOException {
RegattaResults r1 = ParserFactory.INSTANCE.createParser(getInputStream(SAMPLE_INPUT_NAME_KEYWESTRACEWEEEK), KEYWESTRACEWEEEK_EVENT_NAME).parse();
assertNotNull(r1);
}
@Test
public void testScoreCorrectionProviderFeedingAndHasResults() throws IOException, SAXException,
ParserConfigurationException, JAXBException {
ResultUrlRegistry resultUrlRegistry = new ResultUrlRegistryImpl(mock(MongoObjectFactory.class),
mock(DomainObjectFactory.class));
ScoreCorrectionProviderImpl scoreCorrectionProvider = new ScoreCorrectionProviderImpl(
getTestDocumentProvider(), ParserFactory.INSTANCE, resultUrlRegistry);
Map<String, Set<com.sap.sse.common.Util.Pair<String, TimePoint>>> hasResultsFor = scoreCorrectionProvider.getHasResultsForBoatClassFromDateByEventName();
Set<com.sap.sse.common.Util.Pair<String, TimePoint>> resultsForYES = hasResultsFor.get(KEYWESTRACEWEEEK_EVENT_NAME);
assertNotNull(resultsForYES);
assertEquals(3, resultsForYES.size());
}
// @Test
// public void testScoreCorrectionProvider() throws Exception {
// ResultUrlRegistry resultUrlRegistry = new ResultUrlRegistryImpl(mock(MongoObjectFactory.class),
// mock(DomainObjectFactory.class));
// ScoreCorrectionProviderImpl scoreCorrectionProvider = new ScoreCorrectionProviderImpl(
// getTestDocumentProvider(), ParserFactory.INSTANCE, resultUrlRegistry);
// Map<String, Set<com.sap.sse.common.Util.Pair<String, TimePoint>>> hasResultsFor = scoreCorrectionProvider.getHasResultsForBoatClassFromDateByEventName();
// Set<com.sap.sse.common.Util.Pair<String, TimePoint>> resultsForYES = hasResultsFor.get(YES_EVENT_NAME);
// com.sap.sse.common.Util.Pair<String, TimePoint> resultFor29er = null;
// for(com.sap.sse.common.Util.Pair<String, TimePoint> result: resultsForYES) {
// if(result.getA().equals(ISAF_ID_29ER)) {
// resultFor29er = result;
// break;
// }
// }
// assertNotNull(resultFor29er);
//
// RegattaScoreCorrections _29erResult = scoreCorrectionProvider.getScoreCorrections(YES_EVENT_NAME, ISAF_ID_29ER , resultFor29er.getB());
// assertNotNull(_29erResult);
// Iterable<ScoreCorrectionsForRace> scoreCorrectionsForRaces = _29erResult.getScoreCorrectionsForRaces();
// assertNotNull(scoreCorrectionsForRaces);
// assertEquals(8, Util.size(scoreCorrectionsForRaces));
// }
}
@@ -0,0 +1,48 @@
package com.sap.sailing.yachtscoring.resultimport.test;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
import java.util.Set;
import junit.framework.Assert;
import org.junit.Test;
import com.sap.sailing.domain.persistence.DomainObjectFactory;
import com.sap.sailing.domain.persistence.MongoObjectFactory;
import com.sap.sailing.resultimport.ResultUrlRegistry;
import com.sap.sailing.resultimport.impl.ResultUrlRegistryImpl;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.impl.RacingEventServiceImpl;
@SuppressWarnings("restriction")
public class PersistenceTest {
@Test
public void testResultUrlStoring() throws MalformedURLException {
RacingEventService racingEventService = new RacingEventServiceImpl();
DomainObjectFactory domainObjectFactory = racingEventService.getDomainObjectFactory();
MongoObjectFactory mongoObjectFactory = racingEventService.getMongoObjectFactory();
ResultUrlRegistry resultUrlRegistry = new ResultUrlRegistryImpl(mongoObjectFactory, domainObjectFactory);
String testProviderName = "TestProvider";
URL testUrl = new URL("http://www.yachtscoring.com/results_xrr.cfm?Spec_Race=6&eid=1220");
resultUrlRegistry.registerResultUrl(testProviderName, testUrl);
Map<String, Set<URL>> resultUrls = domainObjectFactory.loadResultUrls();
Assert.assertTrue(resultUrls.containsKey(testProviderName));
Set<URL> urls = resultUrls.get(testProviderName);
Assert.assertEquals(1, urls.size());
URL url = urls.iterator().next();
Assert.assertEquals(testUrl, url);
resultUrlRegistry.unregisterResultUrl(testProviderName, testUrl);
resultUrls = domainObjectFactory.loadResultUrls();
Assert.assertFalse(resultUrls.containsKey(testProviderName));
}
}
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="output" path="bin"/>
</classpath>
@@ -0,0 +1 @@
bin/
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>com.sap.sailing.yachtscoring.resultimport</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
@@ -0,0 +1,12 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.8
@@ -0,0 +1,3 @@
eclipse.preferences.version=1
pluginProject.extensions=false
resolve.requirebundle=false
@@ -0,0 +1,17 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Yachtscoring Result import
Bundle-SymbolicName: com.sap.sailing.yachtscoring.resultimport
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: com.sap.sailing.yachtscoring.resultimport.Activator
Bundle-Vendor: SAP
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Import-Package: org.osgi.framework;version="1.5.0",
org.osgi.util.tracker;version="1.5.1"
Bundle-ActivationPolicy: lazy
Require-Bundle: com.sap.sailing.yachtscoring,
com.sap.sailing.domain.common,
com.sap.sailing.resultimport,
com.sap.sailing.xrr.resultimport,
com.sap.sse.common,
com.sap.sailing.xrr.schema
@@ -0,0 +1,4 @@
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>root</artifactId>
<groupId>com.sap.sailing</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>com.sap.sailing.yachtscoring.resultimport</artifactId>
<packaging>eclipse-plugin</packaging>
</project>
@@ -0,0 +1,35 @@
package com.sap.sailing.yachtscoring.resultimport;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.util.tracker.ServiceTracker;
import com.sap.sailing.domain.common.ScoreCorrectionProvider;
import com.sap.sailing.resultimport.ResultUrlRegistry;
import com.sap.sailing.resultimport.impl.ResultUrlRegistryServiceTrackerCustomizer;
import com.sap.sailing.xrr.resultimport.ParserFactory;
public class Activator implements BundleActivator {
private ServiceTracker<ResultUrlRegistry, ResultUrlRegistry> resultUrlRegistryServiceTracker;
public void start(BundleContext bundleContext) throws Exception {
resultUrlRegistryServiceTracker = new ServiceTracker<>(bundleContext, ResultUrlRegistry.class,
new ResultUrlRegistryServiceTrackerCustomizer(bundleContext) {
@Override
protected ScoreCorrectionProvider configureScoreCorrectionProvider(
ResultUrlRegistry resultUrlRegistry) {
final ScoreCorrectionProviderImpl service = new ScoreCorrectionProviderImpl(
ParserFactory.INSTANCE, resultUrlRegistry);
return service;
}
});
resultUrlRegistryServiceTracker.open();
}
public void stop(BundleContext bundleContext) throws Exception {
resultUrlRegistryServiceTracker.close();
}
}
@@ -0,0 +1,143 @@
package com.sap.sailing.yachtscoring.resultimport;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import javax.xml.bind.JAXBException;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.SAXException;
import com.sap.sailing.domain.common.RegattaScoreCorrections;
import com.sap.sailing.domain.common.ScoreCorrectionProvider;
import com.sap.sailing.resultimport.ResultDocumentDescriptor;
import com.sap.sailing.resultimport.ResultDocumentProvider;
import com.sap.sailing.resultimport.ResultUrlProvider;
import com.sap.sailing.resultimport.ResultUrlRegistry;
import com.sap.sailing.xrr.resultimport.Parser;
import com.sap.sailing.xrr.resultimport.ParserFactory;
import com.sap.sailing.xrr.resultimport.impl.XRRRegattaResultsAsScoreCorrections;
import com.sap.sailing.xrr.schema.Division;
import com.sap.sailing.xrr.schema.Event;
import com.sap.sailing.xrr.schema.EventGender;
import com.sap.sailing.xrr.schema.RegattaResults;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Util;
public class ScoreCorrectionProviderImpl implements ScoreCorrectionProvider, ResultUrlProvider {
private static final Logger logger = Logger.getLogger(ScoreCorrectionProviderImpl.class.getName());
private static final long serialVersionUID = 222663322974305822L;
public static final String NAME = "Yachtscoring XRR Result Importer";
private final ParserFactory parserFactory;
private final ResultUrlRegistry resultUrlRegistry;
private final ResultDocumentProvider documentProvider;
public ScoreCorrectionProviderImpl(ResultDocumentProvider documentProvider, ParserFactory parserFactory, ResultUrlRegistry resultUrlRegistry) {
this.documentProvider = documentProvider;
this.parserFactory = parserFactory;
this.resultUrlRegistry = resultUrlRegistry;
}
public ScoreCorrectionProviderImpl(ParserFactory parserFactory, ResultUrlRegistry resultUrlRegistry) {
this.documentProvider = new YachtscoringResultDocumentProvider(this);
this.parserFactory = parserFactory;
this.resultUrlRegistry = resultUrlRegistry;
}
@Override
public String getName() {
return NAME;
}
@Override
public Map<String, Set<Util.Pair<String, TimePoint>>> getHasResultsForBoatClassFromDateByEventName() {
Map<String, Set<Util.Pair<String, TimePoint>>> result = new HashMap<String, Set<Util.Pair<String,TimePoint>>>();
try {
for (ResultDocumentDescriptor resultDocDescr : documentProvider.getResultDocumentDescriptors()) {
String eventName = resultDocDescr.getEventName() != null ? resultDocDescr.getEventName() : resultDocDescr.getRegattaName();
String boatClass = resultDocDescr.getBoatClass();
if(boatClass != null && eventName != null) {
if(resultDocDescr.getCompetitorGenderType() != null) {
boatClass += ", " + resultDocDescr.getCompetitorGenderType().name();
}
Set<Util.Pair<String, TimePoint>> eventResultsSet = result.get(eventName);
if(eventResultsSet == null) {
eventResultsSet = new HashSet<Util.Pair<String, TimePoint>>();
result.put(eventName, eventResultsSet);
}
eventResultsSet.add(new Util.Pair<String, TimePoint>(boatClass, resultDocDescr.getLastModified()));
}
}
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
@Override
public RegattaScoreCorrections getScoreCorrections(String eventName, String boatClassName,
TimePoint timePointPublished) throws IOException, SAXException, ParserConfigurationException {
Parser parser = resolveParser(eventName, boatClassName);
try {
RegattaResults regattaResults = parser.parse();
for (Object o : regattaResults.getPersonOrBoatOrTeam()) {
if (o instanceof Event) {
Event event = (Event) o;
if (event.getTitle().equals(eventName)) {
for (Object eventO : event.getRaceOrDivisionOrRegattaSeriesResult()) {
if (eventO instanceof Division) {
Division division = (Division) eventO;
EventGender divisionGender = division.getGender();
String divisionBoatClassAndGender = parser.getBoatClassName(division);
if(divisionGender != null) {
divisionBoatClassAndGender += ", " + divisionGender.name();
}
if (boatClassName.equalsIgnoreCase(divisionBoatClassAndGender) || boatClassName.contains(divisionBoatClassAndGender)) {
return new XRRRegattaResultsAsScoreCorrections(event, division, this,
parser);
}
}
}
}
}
// }
}
} catch (JAXBException e) {
logger.info("Parse error during XRR import. Ignoring document " + parser.toString());
logger.throwing(ScoreCorrectionProviderImpl.class.getName(), "getHasResultsForBoatClassFromDateByEventName", e);
}
return null;
}
private Parser resolveParser(String eventName, String boatClassName) throws IOException {
Parser result = null;
for (ResultDocumentDescriptor resultDocDescr : documentProvider.getResultDocumentDescriptors()) {
String boatClassAndGenderType = resultDocDescr.getBoatClass();
if(resultDocDescr.getCompetitorGenderType() != null) {
boatClassAndGenderType += ", " + resultDocDescr.getCompetitorGenderType().name();
}
if(eventName.equals(resultDocDescr.getEventName()) && boatClassName.equals(boatClassAndGenderType)) {
result = parserFactory.createParser(resultDocDescr.getInputStream(), resultDocDescr.getEventName());
break;
}
}
return result;
}
@Override
public Iterable<URL> getUrls() {
return resultUrlRegistry.getResultUrls(NAME);
}
@Override
public String getOptionalSampleURL() {
return "http://www.yachtscoring.com/results_xrr.cfm?Spec_Race=6&eid=1220";
}
}
@@ -0,0 +1,59 @@
package com.sap.sailing.yachtscoring.resultimport;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import com.sap.sailing.yachtscoring.EventResultDescriptor;
import com.sap.sailing.yachtscoring.YachtscoringEventResultsParserImpl;
import com.sap.sailing.yachtscoring.RegattaResultDescriptor;
import com.sap.sailing.resultimport.ResultDocumentDescriptor;
import com.sap.sailing.resultimport.ResultDocumentProvider;
import com.sap.sailing.resultimport.ResultUrlProvider;
import com.sap.sailing.resultimport.impl.ResultDocumentDescriptorImpl;
import com.sap.sse.common.impl.MillisecondsTimePoint;
public class YachtscoringResultDocumentProvider implements ResultDocumentProvider {
private final ResultUrlProvider resultUrlProvider;
public YachtscoringResultDocumentProvider(final ResultUrlProvider resultUrlProvider) {
this.resultUrlProvider = resultUrlProvider;
}
@Override
public Iterable<ResultDocumentDescriptor> getResultDocumentDescriptors() throws IOException {
List<ResultDocumentDescriptor> result = new ArrayList<>();
YachtscoringEventResultsParserImpl parser = new YachtscoringEventResultsParserImpl();
for (URL url : resultUrlProvider.getUrls()) {
URLConnection eventResultConn = url.openConnection();
EventResultDescriptor eventResult = parser.getEventResult((InputStream) eventResultConn.getContent());
if (eventResult != null) {
for (RegattaResultDescriptor regattaResult : eventResult.getRegattaResults()) {
// Depending on the regatta type the boat class in the XRR is set or not (in the division tag)
// Olympic boat classes -> IFClassID="2.4M" Title="2.4M open"
// International boat classes -> IFClassID="" Title="Coachboat"
// Open boat classes (ORC) -> IFClassID="" Title="Welcome Race ORC-Club"
// -> therefore we need to take the regatta title as boat class where the IsafID is not available
String boatClass = regattaResult.getIsafId() != null && !regattaResult.getIsafId().isEmpty() ? regattaResult.getIsafId() : regattaResult.getName();
if (regattaResult.getIsFinal() != null && regattaResult.getPublishedAt() != null) {
if (regattaResult.getIsFinal() && regattaResult.getXrrFinalUrl() != null) {
URLConnection regattaResultConn = regattaResult.getXrrFinalUrl().openConnection();
result.add(new ResultDocumentDescriptorImpl((InputStream) regattaResultConn.getContent(),
regattaResult.getXrrPreliminaryUrl().toString(), new MillisecondsTimePoint(regattaResult.getPublishedAt()),
eventResult.getName(), regattaResult.getName(), boatClass, regattaResult.getCompetitorGenderType()));
} else if (regattaResult.getXrrPreliminaryUrl() != null) {
URLConnection regattaResultConn = regattaResult.getXrrPreliminaryUrl().openConnection();
result.add(new ResultDocumentDescriptorImpl((InputStream) regattaResultConn.getContent(),
regattaResult.getXrrPreliminaryUrl().toString(), new MillisecondsTimePoint(regattaResult.getPublishedAt()),
eventResult.getName(), regattaResult.getName(), boatClass, regattaResult.getCompetitorGenderType()));
}
}
}
}
}
return result;
}
}
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="output" path="bin"/>
</classpath>
@@ -0,0 +1,3 @@
bin/
/bin/
/bin/
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>com.sap.sailing.yachtscoring</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
@@ -0,0 +1,12 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.8
@@ -0,0 +1,3 @@
eclipse.preferences.version=1
pluginProject.extensions=false
resolve.requirebundle=false
@@ -0,0 +1,13 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Yachtscoring
Bundle-SymbolicName: com.sap.sailing.yachtscoring
Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: SAP
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-ActivationPolicy: lazy
Require-Bundle: org.json.simple;bundle-version="1.1.0",
com.sap.sailing.domain.common,
com.sap.sailing.domain,
com.sap.sse
Export-Package: com.sap.sailing.yachtscoring
@@ -0,0 +1,5 @@
source.. = src/,\
resources/
output.. = bin/
bin.includes = META-INF/,\
.
+12
View File
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>root</artifactId>
<groupId>com.sap.sailing</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>com.sap.sailing.yachtscoring</artifactId>
<packaging>eclipse-plugin</packaging>
</project>
@@ -0,0 +1,81 @@
package com.sap.sailing.yachtscoring;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
/**
* Reads the list of regattas for an event with a given yachtscoring event id
* @author Frank
*
*/
public class EventResultDescriptor {
private List<RegattaResultDescriptor> regattaResults;
private String id;
private String isafId;
private String name;
private URL xrrUrl;
private String trackingDataHost;
private Integer trackingDataPort;
public EventResultDescriptor() {
regattaResults = new ArrayList<RegattaResultDescriptor>();
}
public List<RegattaResultDescriptor> getRegattaResults() {
return regattaResults;
}
public void setRegattaResults(List<RegattaResultDescriptor> regattaResults) {
this.regattaResults = regattaResults;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public URL getXrrUrl() {
return xrrUrl;
}
public void setXrrUrl(URL xrrUrl) {
this.xrrUrl = xrrUrl;
}
public String getIsafId() {
return isafId;
}
public void setIsafId(String isafId) {
this.isafId = isafId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTrackingDataHost() {
return trackingDataHost;
}
public void setTrackingDataHost(String trackingDataHost) {
this.trackingDataHost = trackingDataHost;
}
public Integer getTrackingDataPort() {
return trackingDataPort;
}
public void setTrackingDataPort(Integer trackingDataPort) {
this.trackingDataPort = trackingDataPort;
}
}
@@ -0,0 +1,80 @@
package com.sap.sailing.yachtscoring;
import java.util.Date;
public class RaceResultDescriptor {
private String id;
private String name;
private Integer raceColumnNumber;
private String seriesName;
private String fleetName;
private Boolean isTracked;
private Date startTime;
/** Possible states: Scheduled, StartSequence, Racing, Finished, GeneralRecall, Postponed, Abandoned */
private String status;
public Integer getRaceColumnNumber() {
return raceColumnNumber;
}
public void setRaceColumnNumber(Integer raceColumnNumber) {
this.raceColumnNumber = raceColumnNumber;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getSeriesName() {
return seriesName;
}
public void setSeriesName(String seriesName) {
this.seriesName = seriesName;
}
public String getFleetName() {
return fleetName;
}
public void setFleetName(String fleetName) {
this.fleetName = fleetName;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Boolean isTracked() {
return isTracked;
}
public void setTracked(Boolean isTracked) {
this.isTracked = isTracked;
}
public Date getStartTime() {
return startTime;
}
public void setStartTime(Date startTime) {
this.startTime = startTime;
}
}
@@ -0,0 +1,118 @@
package com.sap.sailing.yachtscoring;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.sap.sailing.domain.common.CompetitorGenderType;
public class RegattaResultDescriptor {
private String id;
private String isafId;
private String externalId;
private String name;
private String className;
private CompetitorGenderType competitorGenderType;
private URL pdfUrl;
private URL xrrPreliminaryUrl;
private URL xrrFinalUrl;
private URL xrrEntriesUrl;
private URL htmlUrl;
private Date publishedAt;
private Boolean isFinal;
private List<RaceResultDescriptor> raceResults;
public RegattaResultDescriptor() {
raceResults = new ArrayList<RaceResultDescriptor>();
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getIsafId() {
return isafId;
}
public void setIsafId(String isafId) {
this.isafId = isafId;
}
public String getExternalId() {
return externalId;
}
public void setExternalId(String externalId) {
this.externalId = externalId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public URL getPdfUrl() {
return pdfUrl;
}
public void setPdfUrl(URL pdfUrl) {
this.pdfUrl = pdfUrl;
}
public URL getXrrPreliminaryUrl() {
return xrrPreliminaryUrl;
}
public void setXrrPreliminaryUrl(URL xrrPreliminaryUrl) {
this.xrrPreliminaryUrl = xrrPreliminaryUrl;
}
public URL getXrrFinalUrl() {
return xrrFinalUrl;
}
public void setXrrFinalUrl(URL xrrFinalUrl) {
this.xrrFinalUrl = xrrFinalUrl;
}
public URL getHtmlUrl() {
return htmlUrl;
}
public void setHtmlUrl(URL htmlUrl) {
this.htmlUrl = htmlUrl;
}
public Date getPublishedAt() {
return publishedAt;
}
public void setPublishedAt(Date publishedAt) {
this.publishedAt = publishedAt;
}
public Boolean getIsFinal() {
return isFinal;
}
public void setIsFinal(Boolean isFinal) {
this.isFinal = isFinal;
}
public CompetitorGenderType getCompetitorGenderType() {
return competitorGenderType;
}
public void setCompetitorGenderType(CompetitorGenderType competitorGenderType) {
this.competitorGenderType = competitorGenderType;
}
public List<RaceResultDescriptor> getRaceResults() {
return raceResults;
}
public void setRaceResults(List<RaceResultDescriptor> raceResults) {
this.raceResults = raceResults;
}
public URL getXrrEntriesUrl() {
return xrrEntriesUrl;
}
public void setXrrEntriesUrl(URL xrrEntriesUrl) {
this.xrrEntriesUrl = xrrEntriesUrl;
}
}
@@ -0,0 +1,8 @@
package com.sap.sailing.yachtscoring;
import java.io.IOException;
import java.io.InputStream;
public interface YachtscoringEventResultsParser {
public EventResultDescriptor getEventResult(InputStream is) throws IOException;
}
@@ -0,0 +1,151 @@
package com.sap.sailing.yachtscoring;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Date;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import com.sap.sailing.domain.common.CompetitorGenderType;
import com.sap.sse.InvalidDateException;
import com.sap.sse.util.DateParser;
/**
* URLs should be of the form
* <pre>
* http://www.yachtscoring.com/results_xrr.cfm?Spec_Race=6&eid=1390
* </pre>
* where eid the event ID. Events can be discovered by the yachtscoring.com website.
*
* @author Frank Mittag (C5163874)
*
*/
public class YachtscoringEventResultsParserImpl implements YachtscoringEventResultsParser {
/**
* @param is closed before the method returns, also in case of exception
* @throws IOException
*/
public EventResultDescriptor getEventResult(InputStream is) throws IOException {
EventResultDescriptor result = null;
try {
JSONObject jsonRoot = (JSONObject) new JSONParser().parse(new InputStreamReader(is, "UTF-8"));
result = new EventResultDescriptor();
result.setId((String) jsonRoot.get("Id"));
result.setIsafId((String) jsonRoot.get("IsafId"));
result.setName((String) jsonRoot.get("Name"));
result.setXrrUrl(parseURL(jsonRoot, "XrrUrl"));
JSONObject jsonTracking = (JSONObject) jsonRoot.get("Tracking");
if (jsonTracking != null) {
result.setTrackingDataHost((String) jsonTracking.get("Host"));
result.setTrackingDataPort(parseInteger(jsonTracking, "Port"));
}
JSONArray jsonRegattas = (JSONArray) jsonRoot.get("Regattas");
for (Object regattaObject: jsonRegattas) {
RegattaResultDescriptor regattaResult = new RegattaResultDescriptor();
JSONObject jsonRegatta = (JSONObject) regattaObject;
regattaResult.setId((String) jsonRegatta.get("Id"));
regattaResult.setIsafId((String) jsonRegatta.get("IsafId"));
regattaResult.setExternalId((String) jsonRegatta.get("ExternalId"));
regattaResult.setName((String) jsonRegatta.get("Name"));
regattaResult.setCompetitorGenderType(parseCompetitorGenderType(jsonRegatta, "Gender"));
regattaResult.setClassName((String) jsonRegatta.get("ClassName"));
regattaResult.setPdfUrl(parseURL(jsonRegatta, "PdfUrl"));
regattaResult.setXrrPreliminaryUrl(parseURL(jsonRegatta, "XrrPreliminaryUrl"));
regattaResult.setXrrFinalUrl(parseURL(jsonRegatta, "XrrFinalUrl"));
regattaResult.setXrrEntriesUrl(parseURL(jsonRegatta, "XrrEntriesUrl"));
regattaResult.setHtmlUrl(parseURL(jsonRegatta, "HtmlUrl"));
regattaResult.setPublishedAt(parseDate(jsonRegatta, "Published"));
regattaResult.setIsFinal((Boolean) jsonRegatta.get("Final"));
JSONArray jsonRaces = (JSONArray) jsonRegatta.get("Races");
if(jsonRaces != null) {
for (Object raceObject: jsonRaces) {
RaceResultDescriptor raceResult = new RaceResultDescriptor();
JSONObject jsonRace = (JSONObject) raceObject;
raceResult.setId((String) jsonRace.get("Id"));
raceResult.setName((String) jsonRace.get("Name"));
raceResult.setRaceColumnNumber(parseInteger(jsonRace, "RaceIndex"));
raceResult.setStatus((String) jsonRace.get("Status"));
raceResult.setSeriesName((String) jsonRace.get("Series"));
raceResult.setFleetName((String) jsonRace.get("Fleet"));
raceResult.setTracked((Boolean) jsonRace.get("IsTracked"));
raceResult.setStartTime(parseDate(jsonRace, "StartTime"));
regattaResult.getRaceResults().add(raceResult);
}
}
result.getRegattaResults().add(regattaResult);
}
is.close();
} catch(ParseException e) {
e.printStackTrace();
} finally {
is.close();
}
return result;
}
private CompetitorGenderType parseCompetitorGenderType(JSONObject jsonDate, String attributeName) {
CompetitorGenderType result = null;
String genderTypeAsString = (String) jsonDate.get(attributeName);
if(genderTypeAsString != null) {
switch(genderTypeAsString) {
case "M" : result = CompetitorGenderType.Men; break;
case "W" : result = CompetitorGenderType.Women; break;
case "X" : result = CompetitorGenderType.Mixed; break;
case "Open" : result = CompetitorGenderType.Open; break;
}
}
return result;
}
private Integer parseInteger(JSONObject jsonNumber, String attributeName) {
Integer result = null;
Object object = jsonNumber.get(attributeName);
if(object != null) {
if(object instanceof Number) {
result = ((Number) object).intValue();
} else if (object instanceof String) {
String numberAsString = (String) object;
if(!numberAsString.isEmpty()) {
try {
result = Integer.parseInt(numberAsString);
} catch (NumberFormatException e) {
}
}
}
}
return result;
}
private Date parseDate(JSONObject jsonDate, String attributeName) {
Date result = null;
String dateAsString = (String) jsonDate.get(attributeName);
if(dateAsString != null && !dateAsString.isEmpty()) {
try {
result = DateParser.parseUTC(dateAsString);
} catch (InvalidDateException e) {
}
}
return result;
}
private URL parseURL(JSONObject jsonURL, String attributeName) {
URL result = null;
String urlAsString = (String) jsonURL.get(attributeName);
if(urlAsString != null && !urlAsString.isEmpty()) {
try {
result = new URL(urlAsString);
} catch (MalformedURLException e) {
}
}
return result;
}
}
+526 -523
View File
File diff suppressed because it is too large Load Diff