mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-13 22:15:26 +00:00
Merge branch 'permission-vertical' into bug4942
This commit is contained in:
commit
39417838bb
132 files changed
+3364
-1390
No files matched your search
+9
@@ -41,6 +41,15 @@ public interface CompetitorDTO extends Named, WithID, SecuredDTO, Serializable,
|
||||
* of the competitor's {@link #getName() name} unless it's empty in which case an empty string is returned.
|
||||
*/
|
||||
String getShortInfo();
|
||||
|
||||
/**
|
||||
* Returns a derived short information about a competitor depending on the information available.
|
||||
* Depending on the given preferSailId we prefer either {@link #getShortName() short name} or the sail ID from {@link CompetitorWithBoatDTO#getBoat() boat}
|
||||
* if available. If both values aren't available, the boat name is used if a boat is available. If all these
|
||||
* attributes have no value, a three-letter acronym is constructed from the name by using the first two and the last letter
|
||||
* of the competitor's {@link #getName() name} unless it's empty in which case an empty string is returned.
|
||||
*/
|
||||
String getShortInfo(boolean preferSailId);
|
||||
|
||||
Color getColor();
|
||||
|
||||
|
||||
+8
-3
@@ -160,6 +160,11 @@ public class CompetitorDTOImpl extends NamedSecuredObjectDTO implements Competit
|
||||
|
||||
@Override
|
||||
public String getShortInfo() {
|
||||
return getShortInfo(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getShortInfo(boolean preferSailId) {
|
||||
final String result;
|
||||
if (getShortName() != null && !getShortName().trim().isEmpty()) {
|
||||
result = getShortName();
|
||||
@@ -169,9 +174,9 @@ public class CompetitorDTOImpl extends NamedSecuredObjectDTO implements Competit
|
||||
result = null;
|
||||
} else {
|
||||
result = (trimmedName.length()>0?""+trimmedName.charAt(0):"")
|
||||
+ (trimmedName.length()>1?trimmedName.charAt(1):"")
|
||||
+ (trimmedName.length()>0?trimmedName.charAt(trimmedName.length()-1):"");
|
||||
|
||||
+ (trimmedName.length()>1?trimmedName.charAt(1):"")
|
||||
+ (trimmedName.length()>0?trimmedName.charAt(trimmedName.length()-1):"");
|
||||
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
+5
-3
@@ -59,11 +59,13 @@ public class CompetitorWithBoatDTOImpl extends CompetitorDTOImpl implements Comp
|
||||
public CompetitorWithBoatDTO getCompetitorFromPrevious(LeaderboardDTO previousVersion) {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getShortInfo() {
|
||||
public String getShortInfo(boolean preferSailId) {
|
||||
final String result;
|
||||
if (getShortName() != null && !getShortName().trim().isEmpty()) {
|
||||
if (preferSailId && getBoat() != null && getBoat().getSailId() != null) {
|
||||
result = getBoat().getSailId();
|
||||
} else if (getShortName() != null && !getShortName().trim().isEmpty()) {
|
||||
result = getShortName();
|
||||
} else if (getBoat() != null) {
|
||||
result = getBoat().getSailId() != null ? getBoat().getSailId() : getBoat().getName();
|
||||
|
||||
+6
@@ -59,6 +59,12 @@ public class PreviousCompetitorDTOImpl extends NamedSecuredObjectDTO implements
|
||||
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
|
||||
" need to be replaced by an object of "+CompetitorWithBoatDTOImpl.class.getName()+" after deserialization");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getShortInfo(boolean preferSailId) {
|
||||
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
|
||||
" need to be replaced by an object of "+CompetitorWithBoatDTOImpl.class.getName()+" after deserialization");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTwoLetterIsoCountryCode() {
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
<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>
|
||||
@@ -20,7 +20,12 @@ Require-Bundle: org.json.simple;bundle-version="1.1.0",
|
||||
com.sap.sse.security,
|
||||
com.sun.xml.bind.jaxb-impl;bundle-version="2.3.0",
|
||||
com.sap.sse.security.common,
|
||||
com.sap.sailing.domain.igtimiadapter
|
||||
com.sap.sailing.domain.igtimiadapter,
|
||||
com.sap.sse.security,
|
||||
com.sap.sse.security.common,
|
||||
com.sap.sse.security.interface,
|
||||
org.apache.shiro.core,
|
||||
org.apache.shiro.web
|
||||
Import-Package: com.sap.sse.security.shared,
|
||||
javax.ws.rs;version="1.1.1",
|
||||
javax.ws.rs.core;version="1.1.1",
|
||||
|
||||
@@ -15,6 +15,32 @@
|
||||
<param-value>false</param-value>
|
||||
</init-param>
|
||||
</servlet>
|
||||
|
||||
<context-param>
|
||||
<param-name>shiroEnvironmentClass</param-name>
|
||||
<param-value>org.apache.shiro.web.env.IniWebEnvironment</param-value>
|
||||
</context-param>
|
||||
|
||||
<!-- Apache Shiro -->
|
||||
|
||||
<listener>
|
||||
<listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
|
||||
</listener>
|
||||
<filter>
|
||||
<filter-name>ShiroFilter</filter-name>
|
||||
<filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
|
||||
</filter>
|
||||
<!-- Make sure any request you want accessible to Shiro is filtered. "/*"
|
||||
catches all requests. Usually this filter mapping is defined first (before all
|
||||
others) to ensure that Shiro works in subsequent filters in the filter chain: -->
|
||||
<filter-mapping>
|
||||
<filter-name>ShiroFilter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
<dispatcher>REQUEST</dispatcher>
|
||||
<dispatcher>FORWARD</dispatcher>
|
||||
<dispatcher>INCLUDE</dispatcher>
|
||||
<dispatcher>ERROR</dispatcher>
|
||||
</filter-mapping>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>Igtimi Oauth Callback REST API</servlet-name>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
source.. = src/
|
||||
source.. = src/,\
|
||||
resources/
|
||||
output.. = bin/
|
||||
bin.includes = META-INF/,\
|
||||
.,\
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
|
||||
[main]
|
||||
credentialsMatcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher
|
||||
credentialsMatcher.storedCredentialsHexEncoded = false
|
||||
credentialsMatcher.hashIterations = 1024
|
||||
|
||||
# Realm configuration:
|
||||
# --------------------
|
||||
|
||||
upRealm = com.sap.sse.security.UsernamePasswordRealm
|
||||
upRealm.credentialsMatcher = $credentialsMatcher
|
||||
oauthRealm = com.sap.sse.security.OAuthRealm
|
||||
bearerTokenRealm = com.sap.sse.security.BearerTokenRealm
|
||||
|
||||
# Putting it all together:
|
||||
sessionManager = com.sap.sse.security.SecurityWebSessionManager
|
||||
securityManager.sessionManager = $sessionManager
|
||||
sessionDAO = org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO
|
||||
securityManager.sessionManager.sessionDAO = $sessionDAO
|
||||
subjectDAO = com.sap.sse.security.NoSessionStorageSessionDAO
|
||||
securityManager.subjectDAO = $subjectDAO
|
||||
# 1y timeout
|
||||
securityManager.sessionManager.globalSessionTimeout = 31536000000
|
||||
cacheManager = com.sap.sse.security.SessionCacheManager
|
||||
securityManager.cacheManager = $cacheManager
|
||||
|
||||
# Support for anonymous user permissions
|
||||
webSubjectFactoryWithAnonymousPrincipalSupport=com.sap.sse.security.WebSubjectFactoryWithAnonymousPrincipalSupport
|
||||
securityManager.subjectFactory=$webSubjectFactoryWithAnonymousPrincipalSupport
|
||||
|
||||
# Authentication Filter Configurations
|
||||
# ------------------------------------
|
||||
|
||||
# This authentication filter accepts a bearer access token in the HTTP
|
||||
# Authorization header field, as in
|
||||
# Authorization: Bearer 1029741026501365024376093245
|
||||
# If no such bearer token is provided, the filter falls back to basic HTTP
|
||||
# authentication ("Authentication: Basic ...") and then regular form-based
|
||||
# authentication with POST parameters "username" and "password".
|
||||
bearerToken = com.sap.sse.security.BearerTokenOrBasicOrFormAuthenticationFilter
|
||||
|
||||
# Specifying filter chains for URL patterns
|
||||
|
||||
[urls]
|
||||
/authorizationcallback = bearerToken
|
||||
+10
@@ -10,6 +10,7 @@ import org.osgi.util.tracker.ServiceTracker;
|
||||
|
||||
import com.sap.sailing.domain.igtimiadapter.Client;
|
||||
import com.sap.sailing.domain.igtimiadapter.IgtimiConnectionFactory;
|
||||
import com.sap.sse.security.SecurityService;
|
||||
import com.sap.sse.util.ServiceTrackerFactory;
|
||||
|
||||
/**
|
||||
@@ -25,6 +26,7 @@ import com.sap.sse.util.ServiceTrackerFactory;
|
||||
public class Activator implements BundleActivator {
|
||||
private static Activator INSTANCE;
|
||||
private ServiceTracker<IgtimiConnectionFactory, IgtimiConnectionFactory> igtimiConnectionFactoryTracker;
|
||||
private ServiceTracker<SecurityService, SecurityService> securityServiceTracker;
|
||||
|
||||
public Activator() throws ClientProtocolException, IllegalStateException, IOException, ParseException {
|
||||
}
|
||||
@@ -35,6 +37,8 @@ public class Activator implements BundleActivator {
|
||||
|
||||
igtimiConnectionFactoryTracker = ServiceTrackerFactory
|
||||
.createAndOpen(context, IgtimiConnectionFactory.class);
|
||||
|
||||
securityServiceTracker = ServiceTrackerFactory.createAndOpen(context, SecurityService.class);
|
||||
}
|
||||
|
||||
public static Activator getInstance() throws ClientProtocolException, IllegalStateException, IOException, ParseException {
|
||||
@@ -48,9 +52,15 @@ public class Activator implements BundleActivator {
|
||||
return igtimiConnectionFactoryTracker.getService();
|
||||
}
|
||||
|
||||
public SecurityService getSecurityService() {
|
||||
return securityServiceTracker.getService();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop(BundleContext context) throws Exception {
|
||||
igtimiConnectionFactoryTracker.close();
|
||||
igtimiConnectionFactoryTracker = null;
|
||||
securityServiceTracker.close();
|
||||
securityServiceTracker = null;
|
||||
}
|
||||
}
|
||||
+14
-2
@@ -21,6 +21,8 @@ import org.json.simple.parser.ParseException;
|
||||
|
||||
import com.sap.sailing.domain.igtimiadapter.gateway.impl.Activator;
|
||||
import com.sap.sailing.domain.igtimiadapter.impl.IgtimiConnectionFactoryImpl;
|
||||
import com.sap.sse.security.SecurityService;
|
||||
import com.sap.sse.security.shared.impl.User;
|
||||
|
||||
@Path(AuthorizationCallback.V1)
|
||||
public class AuthorizationCallback {
|
||||
@@ -57,8 +59,18 @@ public class AuthorizationCallback {
|
||||
} else {
|
||||
if (code != null) {
|
||||
try {
|
||||
connectionFactory.obtainAccessTokenFromAuthorizationCode(code);
|
||||
result = Response.ok().entity("SAP Sailing Analytics authorized successfully to access user's tracks").build();
|
||||
final SecurityService securityService = Activator.getInstance().getSecurityService();
|
||||
final User currentUser = securityService.getCurrentUser();
|
||||
if (currentUser != null) {
|
||||
connectionFactory.obtainAccessTokenFromAuthorizationCode(currentUser.getName(), code);
|
||||
result = Response.ok()
|
||||
.entity("SAP Sailing Analytics authorized successfully to access user's tracks")
|
||||
.build();
|
||||
} else {
|
||||
result = Response.status(Status.UNAUTHORIZED).entity(
|
||||
"SAP Sailing Analytics could not authorize access user's tracks: Current user not found.")
|
||||
.build();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
result = Response.status(Status.UNAUTHORIZED).entity(e.getMessage()).build();
|
||||
logger.log(Level.SEVERE, "Error trying to obtain access token from authentication code " + code, e);
|
||||
|
||||
+1
-1
@@ -2,6 +2,6 @@ package com.sap.sailing.domain.igtimiadapter.persistence;
|
||||
|
||||
public interface DomainObjectFactory {
|
||||
|
||||
Iterable<String> getAccessTokens();
|
||||
Iterable<TokenAndCreator> getAccessTokens();
|
||||
|
||||
}
|
||||
+4
-2
@@ -2,8 +2,10 @@ package com.sap.sailing.domain.igtimiadapter.persistence;
|
||||
|
||||
public interface MongoObjectFactory {
|
||||
|
||||
void storeAccessToken(String accessToken);
|
||||
void storeAccessToken(String creatorName, String accessToken);
|
||||
|
||||
void removeAccessToken(String accessToken);
|
||||
void removeAccessToken(String creatorName, String accessToken);
|
||||
|
||||
void clear();
|
||||
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package com.sap.sailing.domain.igtimiadapter.persistence;
|
||||
|
||||
public class TokenAndCreator {
|
||||
|
||||
private final String creatorName;
|
||||
private final String accessToken;
|
||||
|
||||
public TokenAndCreator(String creatorName, String accessToken) {
|
||||
this.creatorName = creatorName;
|
||||
this.accessToken = accessToken;
|
||||
}
|
||||
|
||||
public String getCreatorName() {
|
||||
return creatorName;
|
||||
}
|
||||
|
||||
public String getAccessToken() {
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
}
|
||||
+18
-3
@@ -8,6 +8,7 @@ import org.bson.Document;
|
||||
import com.mongodb.client.MongoCollection;
|
||||
import com.mongodb.client.MongoDatabase;
|
||||
import com.sap.sailing.domain.igtimiadapter.persistence.DomainObjectFactory;
|
||||
import com.sap.sailing.domain.igtimiadapter.persistence.TokenAndCreator;
|
||||
|
||||
public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
private final MongoDatabase db;
|
||||
@@ -17,12 +18,26 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<String> getAccessTokens() {
|
||||
List<String> result = new ArrayList<>();
|
||||
public Iterable<TokenAndCreator> getAccessTokens() {
|
||||
List<TokenAndCreator> result = new ArrayList<>();
|
||||
final MongoCollection<org.bson.Document> accessTokenCollection = db.getCollection(CollectionNames.IGTIMI_ACCESS_TOKENS.name());
|
||||
accessTokenCollection.createIndex(new Document(FieldNames.IGTIMI_ACCESS_TOKENS_ACCESS_TOKEN.name(), 1));
|
||||
for (Object o : accessTokenCollection.find()) {
|
||||
result.add((String) ((Document) o).get(FieldNames.IGTIMI_ACCESS_TOKENS_ACCESS_TOKEN.name()));
|
||||
final String accessToken = (String) ((Document) o).get(FieldNames.IGTIMI_ACCESS_TOKENS_ACCESS_TOKEN.name());
|
||||
String creatorName= (String) ((Document) o).get(FieldNames.CREATOR_NAME.name());
|
||||
|
||||
final boolean needsUpdate = (creatorName == null);
|
||||
if (needsUpdate) {
|
||||
// No creator is set yet -> existing token are assumed to belong to the admin
|
||||
creatorName = "admin";
|
||||
|
||||
// recreating the token on the DB because the composite key changed
|
||||
MongoObjectFactoryImpl mongoObjectFactory = new MongoObjectFactoryImpl(db);
|
||||
mongoObjectFactory.removeAccessToken(null, accessToken);
|
||||
mongoObjectFactory.storeAccessToken(creatorName, accessToken);
|
||||
}
|
||||
|
||||
result.add(new TokenAndCreator(creatorName, accessToken));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
+2
-1
@@ -1,5 +1,6 @@
|
||||
package com.sap.sailing.domain.igtimiadapter.persistence.impl;
|
||||
|
||||
public enum FieldNames {
|
||||
IGTIMI_ACCESS_TOKENS_ACCESS_TOKEN;
|
||||
IGTIMI_ACCESS_TOKENS_ACCESS_TOKEN,
|
||||
CREATOR_NAME;
|
||||
}
|
||||
+12
-5
@@ -13,21 +13,28 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
|
||||
public MongoObjectFactoryImpl(MongoDatabase db) {
|
||||
this.db = db;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
db.getCollection(CollectionNames.IGTIMI_ACCESS_TOKENS.name()).withWriteConcern(WriteConcern.ACKNOWLEDGED)
|
||||
.drop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeAccessToken(String accessToken) {
|
||||
final Document basicDBObject = getAccessTokenDBQuery(accessToken);
|
||||
public void storeAccessToken(String creatorName, String accessToken) {
|
||||
final Document basicDBObject = getAccessTokenDBQuery(creatorName, accessToken);
|
||||
db.getCollection(CollectionNames.IGTIMI_ACCESS_TOKENS.name()).withWriteConcern(WriteConcern.ACKNOWLEDGED).replaceOne(basicDBObject, basicDBObject, new UpdateOptions().upsert(true));
|
||||
}
|
||||
|
||||
private Document getAccessTokenDBQuery(String accessToken) {
|
||||
private Document getAccessTokenDBQuery(String creatorName, String accessToken) {
|
||||
final Document basicDBObject = new Document(FieldNames.IGTIMI_ACCESS_TOKENS_ACCESS_TOKEN.name(), accessToken);
|
||||
basicDBObject.put(FieldNames.CREATOR_NAME.name(), creatorName);
|
||||
return basicDBObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAccessToken(String accessToken) {
|
||||
final Document basicDBObject = getAccessTokenDBQuery(accessToken);
|
||||
public void removeAccessToken(String creatorName, String accessToken) {
|
||||
final Document basicDBObject = getAccessTokenDBQuery(creatorName, accessToken);
|
||||
db.getCollection(CollectionNames.IGTIMI_ACCESS_TOKENS.name()).withWriteConcern(WriteConcern.ACKNOWLEDGED).deleteOne(basicDBObject);
|
||||
}
|
||||
}
|
||||
@@ -10,4 +10,7 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||
Require-Bundle: org.junit;bundle-version="4.8.2",
|
||||
com.sap.sailing.domain.common,
|
||||
com.sap.sse.mongodb,
|
||||
com.sap.sse.common
|
||||
com.sap.sse.common,
|
||||
com.sap.sse.security.testsupport,
|
||||
org.mockito.mockito-core;bundle-version="1.10.14",
|
||||
org.hamcrest;bundle-version="1.1.0"
|
||||
+16
-3
@@ -11,6 +11,8 @@ import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import org.apache.http.client.ClientProtocolException;
|
||||
import org.json.simple.parser.ParseException;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.Timeout;
|
||||
@@ -25,11 +27,22 @@ import com.sap.sailing.domain.igtimiadapter.impl.IgtimiConnectionFactoryImpl;
|
||||
import com.sap.sailing.domain.igtimiadapter.persistence.PersistenceFactory;
|
||||
import com.sap.sse.mongodb.MongoDBConfiguration;
|
||||
import com.sap.sse.mongodb.MongoDBService;
|
||||
import com.sap.sse.security.testsupport.SecurityServiceMockFactory;
|
||||
|
||||
public class SignInTest {
|
||||
private static final Logger logger = Logger.getLogger(SignInTest.class.getName());
|
||||
|
||||
@Rule public Timeout AbstractTracTracLiveTestTimeout = Timeout.millis(2 * 60 * 1000);
|
||||
|
||||
@Before
|
||||
public void setUp() throws ClientProtocolException, IOException, org.json.simple.parser.ParseException {
|
||||
Activator.getInstance().setSecurityService(SecurityServiceMockFactory.mockSecurityService());
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
Activator.getInstance().setSecurityService(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleSignIn() throws ClientProtocolException, IOException, IllegalStateException,
|
||||
@@ -45,7 +58,7 @@ public class SignInTest {
|
||||
final String code = igtimiConnectionFactory.authorizeAndReturnAuthorizedCode("axel.uhl@gmx.de", "123456");
|
||||
logger.info("Igtimi OAuth code is "+code);
|
||||
assertNotNull(code);
|
||||
Account account = igtimiConnectionFactory.obtainAccessTokenFromAuthorizationCode(code);
|
||||
Account account = igtimiConnectionFactory.obtainAccessTokenFromAuthorizationCode("admin", code);
|
||||
assertEquals("axel.uhl@gmx.de", account.getUser().getEmail());
|
||||
}
|
||||
|
||||
@@ -76,7 +89,7 @@ public class SignInTest {
|
||||
MongoDBService mongoTestService = mongoTestConfig.getService();
|
||||
final IgtimiConnectionFactory igtimiConnectionFactory = new IgtimiConnectionFactoryImpl(testAppClient, PersistenceFactory.INSTANCE.getDomainObjectFactory(mongoTestService),
|
||||
PersistenceFactory.INSTANCE.getMongoObjectFactory(mongoTestService));
|
||||
final Account account = igtimiConnectionFactory.createAccountToAccessUserData("axel.uhl@gmx.de", "123456");
|
||||
final Account account = igtimiConnectionFactory.createAccountToAccessUserData("admin", "axel.uhl@gmx.de", "123456");
|
||||
assertNotNull(account);
|
||||
logger.info("Igtimi account is "+account);
|
||||
}
|
||||
@@ -84,7 +97,7 @@ public class SignInTest {
|
||||
@Test
|
||||
public void testAddToken() throws ClientProtocolException, IllegalStateException, IOException, ParseException {
|
||||
final IgtimiConnectionFactory connectionFactory = Activator.getInstance().getConnectionFactory();
|
||||
Account account = connectionFactory.registerAccountForWhichClientIsAuthorized("de2d6531236200f7c9fb69a0463ffe8d6b13f62bd7aad8de98c22862e4928e8a");
|
||||
Account account = connectionFactory.registerAccountForWhichClientIsAuthorized("admin", "de2d6531236200f7c9fb69a0463ffe8d6b13f62bd7aad8de98c22862e4928e8a");
|
||||
assertEquals("axel.uhl@gmx.de", account.getUser().getEmail());
|
||||
assertSame(account, connectionFactory.getExistingAccountByEmail("axel.uhl@gmx.de"));
|
||||
}
|
||||
|
||||
+18
-7
@@ -6,10 +6,10 @@ import static org.junit.Assert.assertTrue;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.mongodb.MongoDBConfiguration;
|
||||
|
||||
public class IgtimiPersistenceTest {
|
||||
private static final String CREATOR = "admin";
|
||||
private MongoObjectFactory mongoObjectFactory;
|
||||
private DomainObjectFactory domainObjectFactory;
|
||||
|
||||
@@ -22,11 +22,22 @@ public class IgtimiPersistenceTest {
|
||||
@Test
|
||||
public void testStoringAndLoadingAccessTokens() {
|
||||
String accessToken = "Test Access Token";
|
||||
mongoObjectFactory.removeAccessToken(accessToken);
|
||||
assertFalse(Util.contains(domainObjectFactory.getAccessTokens(), accessToken));
|
||||
mongoObjectFactory.storeAccessToken(accessToken);
|
||||
assertTrue(Util.contains(domainObjectFactory.getAccessTokens(), accessToken));
|
||||
mongoObjectFactory.removeAccessToken(accessToken);
|
||||
assertFalse(Util.contains(domainObjectFactory.getAccessTokens(), accessToken));
|
||||
mongoObjectFactory.removeAccessToken(CREATOR, accessToken);
|
||||
assertFalse(isAccessTokenContained(domainObjectFactory.getAccessTokens(), accessToken));
|
||||
mongoObjectFactory.storeAccessToken(CREATOR, accessToken);
|
||||
assertTrue(isAccessTokenContained(domainObjectFactory.getAccessTokens(), accessToken));
|
||||
mongoObjectFactory.removeAccessToken(CREATOR, accessToken);
|
||||
assertFalse(isAccessTokenContained(domainObjectFactory.getAccessTokens(), accessToken));
|
||||
}
|
||||
|
||||
private boolean isAccessTokenContained(Iterable<TokenAndCreator> availableToken, String accessToken) {
|
||||
boolean result = false;
|
||||
for (TokenAndCreator token : availableToken) {
|
||||
if (accessToken.equals(token.getAccessToken())) {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+11
-5
@@ -1,8 +1,6 @@
|
||||
package com.sap.sailing.domain.igtimiadapter.test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.http.client.ClientProtocolException;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.rules.Timeout;
|
||||
@@ -11,6 +9,7 @@ import com.sap.sailing.domain.igtimiadapter.Account;
|
||||
import com.sap.sailing.domain.igtimiadapter.IgtimiConnection;
|
||||
import com.sap.sailing.domain.igtimiadapter.IgtimiConnectionFactory;
|
||||
import com.sap.sailing.domain.igtimiadapter.impl.Activator;
|
||||
import com.sap.sse.security.testsupport.SecurityServiceMockFactory;
|
||||
|
||||
public class AbstractTestWithIgtimiConnection {
|
||||
protected IgtimiConnection connection;
|
||||
@@ -19,11 +18,18 @@ public class AbstractTestWithIgtimiConnection {
|
||||
|
||||
@Rule public Timeout AbstractTracTracLiveTestTimeout = Timeout.millis(2 * 60 * 1000);
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws ClientProtocolException, IOException, org.json.simple.parser.ParseException {
|
||||
public void setUp() throws Exception {
|
||||
Activator.getInstance().setSecurityService(SecurityServiceMockFactory.mockSecurityService());
|
||||
final IgtimiConnectionFactory connectionFactory = Activator.getInstance().getConnectionFactory();
|
||||
Account account = connectionFactory.registerAccountForWhichClientIsAuthorized("9fded995cf21c8ed91ddaec13b220e8d5e44c65808d22ec2b1b7c32261121f26");
|
||||
Account account = connectionFactory.registerAccountForWhichClientIsAuthorized("admin", "9fded995cf21c8ed91ddaec13b220e8d5e44c65808d22ec2b1b7c32261121f26");
|
||||
connection = connectionFactory.connect(account);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
Activator.getInstance().setSecurityService(null);
|
||||
}
|
||||
|
||||
}
|
||||
+1
-5
@@ -4,8 +4,6 @@ import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
@@ -13,7 +11,6 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.apache.http.client.ClientProtocolException;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sailing.domain.common.Wind;
|
||||
@@ -41,8 +38,7 @@ public class IgtimiFixTrackTest extends AbstractTestWithIgtimiConnection {
|
||||
private static final Logger logger = Logger.getLogger(IgtimiFixTrackTest.class.getName());
|
||||
|
||||
@Test
|
||||
public void testFetchFixesIntoTracks() throws ParseException, ClientProtocolException, IllegalStateException, IOException, org.json.simple.parser.ParseException {
|
||||
setUp();
|
||||
public void testFetchFixesIntoTracks() throws Exception {
|
||||
final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX", Locale.GERMAN);
|
||||
TimePoint start = new MillisecondsTimePoint(dateFormat.parse("2013-11-09T07:00:00Z"));
|
||||
TimePoint end = new MillisecondsTimePoint(dateFormat.parse("2013-11-09T07:10:00Z"));
|
||||
|
||||
+16
-1
@@ -19,6 +19,7 @@ import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.apache.http.client.ClientProtocolException;
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.api.StatusCode;
|
||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
|
||||
@@ -28,6 +29,8 @@ import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
|
||||
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
|
||||
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.Timeout;
|
||||
@@ -39,12 +42,14 @@ import com.sap.sailing.domain.igtimiadapter.IgtimiConnection;
|
||||
import com.sap.sailing.domain.igtimiadapter.IgtimiConnectionFactory;
|
||||
import com.sap.sailing.domain.igtimiadapter.LiveDataConnection;
|
||||
import com.sap.sailing.domain.igtimiadapter.datatypes.Fix;
|
||||
import com.sap.sailing.domain.igtimiadapter.impl.Activator;
|
||||
import com.sap.sailing.domain.igtimiadapter.impl.ClientImpl;
|
||||
import com.sap.sailing.domain.igtimiadapter.impl.IgtimiConnectionFactoryImpl;
|
||||
import com.sap.sailing.domain.igtimiadapter.persistence.PersistenceFactory;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.mongodb.MongoDBConfiguration;
|
||||
import com.sap.sse.mongodb.MongoDBService;
|
||||
import com.sap.sse.security.testsupport.SecurityServiceMockFactory;
|
||||
|
||||
public class WebSocketTest {
|
||||
private static final Logger logger = Logger.getLogger(WebSocketTest.class.getName());
|
||||
@@ -116,6 +121,16 @@ public class WebSocketTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws ClientProtocolException, IOException, org.json.simple.parser.ParseException {
|
||||
Activator.getInstance().setSecurityService(SecurityServiceMockFactory.mockSecurityService());
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
Activator.getInstance().setSecurityService(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleWebSocketEchoTest() throws Exception {
|
||||
String destUri = "ws://echo.websocket.org"; // wss currently doesn't seem to work with Jetty 9.0.4 WebSocket implementation
|
||||
@@ -162,7 +177,7 @@ public class WebSocketTest {
|
||||
PersistenceFactory.INSTANCE.getMongoObjectFactory(mongoTestService));
|
||||
// the following is an access token for an account allowing axel.uhl@gmx.de to access
|
||||
// the data from baur@stg-academy.org, particularly containing the Berlin test data
|
||||
Account account = igtimiConnectionFactory.registerAccountForWhichClientIsAuthorized("9fded995cf21c8ed91ddaec13b220e8d5e44c65808d22ec2b1b7c32261121f26");
|
||||
Account account = igtimiConnectionFactory.registerAccountForWhichClientIsAuthorized("admin", "9fded995cf21c8ed91ddaec13b220e8d5e44c65808d22ec2b1b7c32261121f26");
|
||||
IgtimiConnection conn = igtimiConnectionFactory.connect(account);
|
||||
LiveDataConnection liveDataConnection = conn.getOrCreateLiveConnection(Collections.singleton("GA-EN-AAEJ"));
|
||||
LiveDataConnection redundantSecondSharedConnection = conn.getOrCreateLiveConnection(Collections.singleton("GA-EN-AAEJ"));
|
||||
|
||||
+9
-3
@@ -11,6 +11,8 @@ import com.sap.sse.security.shared.WithQualifiedObjectIdentifier;
|
||||
*/
|
||||
public interface Account extends WithQualifiedObjectIdentifier {
|
||||
User getUser();
|
||||
|
||||
String getCreatorName();
|
||||
|
||||
@Override
|
||||
default HasPermissions getType() {
|
||||
@@ -22,16 +24,20 @@ public interface Account extends WithQualifiedObjectIdentifier {
|
||||
return getUser().getFirstName() + " " + getUser().getSurname();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
default QualifiedObjectIdentifier getIdentifier() {
|
||||
return getType().getQualifiedObjectIdentifier(getTypeRelativeObjectIdentifier());
|
||||
}
|
||||
|
||||
|
||||
default TypeRelativeObjectIdentifier getTypeRelativeObjectIdentifier() {
|
||||
return getTypeRelativeObjectIdentifier(getUser().getEmail());
|
||||
return getCreatorName() == null ? new TypeRelativeObjectIdentifier(getUser().getEmail())
|
||||
: new TypeRelativeObjectIdentifier(getUser().getEmail(), getCreatorName());
|
||||
}
|
||||
|
||||
static TypeRelativeObjectIdentifier getTypeRelativeObjectIdentifier(String email) {
|
||||
return new TypeRelativeObjectIdentifier(email);
|
||||
static TypeRelativeObjectIdentifier getTypeRelativeObjectIdentifier(String email, String creatorName) {
|
||||
return new TypeRelativeObjectIdentifier(email, creatorName);
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -43,7 +43,7 @@ public interface IgtimiConnectionFactory {
|
||||
* which this factory belongs.
|
||||
* @return
|
||||
*/
|
||||
Account registerAccountForWhichClientIsAuthorized(String accessToken) throws ClientProtocolException,
|
||||
Account registerAccountForWhichClientIsAuthorized(String creatorName, String accessToken) throws ClientProtocolException,
|
||||
IllegalStateException, IOException, ParseException;
|
||||
|
||||
/**
|
||||
@@ -59,7 +59,7 @@ public interface IgtimiConnectionFactory {
|
||||
* @return the account with which a caller can then {@link #connect obtain a connection} for the data that the user
|
||||
* identified by <code>userEmail</code> and <code>userPassword</code> shares with our client.
|
||||
*/
|
||||
Account createAccountToAccessUserData(String userEmail, String userPassword) throws ClientProtocolException,
|
||||
Account createAccountToAccessUserData(String creatorName, String userEmail, String userPassword) throws ClientProtocolException,
|
||||
IOException, IllegalStateException, ParserConfigurationException, SAXException, ClassNotFoundException,
|
||||
InstantiationException, IllegalAccessException, ClassCastException, ParseException;
|
||||
|
||||
|
||||
+8
-1
@@ -6,9 +6,11 @@ import com.sap.sailing.domain.igtimiadapter.User;
|
||||
public class AccountImpl implements Account {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final User user;
|
||||
private final String creatorName;
|
||||
|
||||
public AccountImpl(User user) {
|
||||
public AccountImpl(String creatorName, User user) {
|
||||
super();
|
||||
this.creatorName = creatorName;
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
@@ -16,6 +18,11 @@ public class AccountImpl implements Account {
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreatorName() {
|
||||
return creatorName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
+21
-2
@@ -24,6 +24,7 @@ import com.sap.sailing.domain.igtimiadapter.persistence.MongoObjectFactory;
|
||||
import com.sap.sailing.domain.igtimiadapter.persistence.PersistenceFactory;
|
||||
import com.sap.sailing.domain.tracking.WindTrackerFactory;
|
||||
import com.sap.sse.security.SecurityService;
|
||||
import com.sap.sse.util.ClearStateTestSupport;
|
||||
import com.sap.sse.util.ServiceTrackerFactory;
|
||||
import com.sap.sse.util.impl.ThreadFactoryWithPriority;
|
||||
|
||||
@@ -54,7 +55,9 @@ public class Activator implements BundleActivator {
|
||||
private static final String CLIENT_REDIRECT_PORT_PROPERTY_NAME = "igtimi.client.redirect.port";
|
||||
private final Future<IgtimiConnectionFactoryImpl> connectionFactory;
|
||||
private final Future<IgtimiWindTrackerFactory> windTrackerFactory;
|
||||
private ServiceTracker<SecurityService, SecurityService> securityServiceServiceTracker;
|
||||
private final ExecutorService executor = Executors.newSingleThreadExecutor(new ThreadFactoryWithPriority(Thread.NORM_PRIORITY, /* daemon */ true));
|
||||
private SecurityService securityServiceTest;
|
||||
|
||||
public Activator() throws ClientProtocolException, IllegalStateException, IOException, ParseException {
|
||||
logger.info(getClass().getName()+" constructor");
|
||||
@@ -82,6 +85,11 @@ public class Activator implements BundleActivator {
|
||||
});
|
||||
}
|
||||
|
||||
/** Only used by tests. */
|
||||
public void setSecurityService(SecurityService securityService) {
|
||||
securityServiceTest = securityService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(final BundleContext context) throws Exception {
|
||||
INSTANCE = this;
|
||||
@@ -99,9 +107,8 @@ public class Activator implements BundleActivator {
|
||||
}
|
||||
});
|
||||
|
||||
securityServiceServiceTracker = ServiceTrackerFactory.createAndOpen(context, SecurityService.class);
|
||||
new Thread(() -> {
|
||||
final ServiceTracker<SecurityService, SecurityService> securityServiceServiceTracker = ServiceTrackerFactory
|
||||
.createAndOpen(context, SecurityService.class);
|
||||
try {
|
||||
final SecurityService securityService = securityServiceServiceTracker.waitForService(0);
|
||||
IgtimiConnectionFactoryImpl igtimiConnectionFactory = connectionFactory.get();
|
||||
@@ -114,6 +121,12 @@ public class Activator implements BundleActivator {
|
||||
}
|
||||
}, getClass().getName() + " registering connectivity handler").start();
|
||||
|
||||
context.registerService(ClearStateTestSupport.class.getName(), new ClearStateTestSupport() {
|
||||
@Override
|
||||
public void clearState() throws Exception {
|
||||
connectionFactory.get().clear();
|
||||
}
|
||||
}, null);
|
||||
}
|
||||
|
||||
public static Activator getInstance() throws ClientProtocolException, IllegalStateException, IOException, ParseException {
|
||||
@@ -132,6 +145,10 @@ public class Activator implements BundleActivator {
|
||||
}
|
||||
}
|
||||
|
||||
public SecurityService getSecurityService() {
|
||||
return securityServiceTest == null ? securityServiceServiceTracker.getService() : securityServiceTest;
|
||||
}
|
||||
|
||||
public IgtimiWindTrackerFactory getWindTrackerFactory() {
|
||||
try {
|
||||
return windTrackerFactory.get();
|
||||
@@ -143,5 +160,7 @@ public class Activator implements BundleActivator {
|
||||
|
||||
@Override
|
||||
public void stop(BundleContext context) throws Exception {
|
||||
securityServiceServiceTracker.close();
|
||||
securityServiceServiceTracker = null;
|
||||
}
|
||||
}
|
||||
+40
-14
@@ -43,6 +43,7 @@ import org.xml.sax.SAXException;
|
||||
import org.xml.sax.SAXParseException;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
||||
import com.sap.sailing.domain.common.security.SecuredDomainType;
|
||||
import com.sap.sailing.domain.igtimiadapter.Account;
|
||||
import com.sap.sailing.domain.igtimiadapter.Client;
|
||||
import com.sap.sailing.domain.igtimiadapter.IgtimiConnection;
|
||||
@@ -51,7 +52,9 @@ import com.sap.sailing.domain.igtimiadapter.Permission;
|
||||
import com.sap.sailing.domain.igtimiadapter.datatypes.Type;
|
||||
import com.sap.sailing.domain.igtimiadapter.persistence.DomainObjectFactory;
|
||||
import com.sap.sailing.domain.igtimiadapter.persistence.MongoObjectFactory;
|
||||
import com.sap.sailing.domain.igtimiadapter.persistence.TokenAndCreator;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.security.SecurityService;
|
||||
import com.sap.sse.util.LaxRedirectStrategyForAllRedirectResponseCodes;
|
||||
|
||||
public class IgtimiConnectionFactoryImpl implements IgtimiConnectionFactory {
|
||||
@@ -69,32 +72,55 @@ public class IgtimiConnectionFactoryImpl implements IgtimiConnectionFactory {
|
||||
connectionsByAccount = new HashMap<>();
|
||||
this.client = client;
|
||||
this.mongoObjectFactory = mongoObjectFactory;
|
||||
for (String accessToken : domainObjectFactory.getAccessTokens()) {
|
||||
for (TokenAndCreator accessTokenWithCreator : domainObjectFactory.getAccessTokens()) {
|
||||
try {
|
||||
registerAccountForWhichClientIsAuthorized(accessToken);
|
||||
storeIgtimiAccount(accessTokenWithCreator.getCreatorName(), accessTokenWithCreator.getAccessToken(),
|
||||
getAccount(accessTokenWithCreator.getCreatorName(), accessTokenWithCreator.getAccessToken()));
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Error registering Igtimi access token "+accessToken+"; probably the access token was revoked or expired.", e);
|
||||
mongoObjectFactory.removeAccessToken(accessToken);
|
||||
logger.log(Level.SEVERE, "Error registering Igtimi access token " + accessTokenWithCreator
|
||||
+ "; probably the access token was revoked or expired.", e);
|
||||
mongoObjectFactory.removeAccessToken(accessTokenWithCreator.getCreatorName(),
|
||||
accessTokenWithCreator.getAccessToken());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
accessTokensByAccount.clear();
|
||||
accountsByEmail.clear();
|
||||
connectionsByAccount.clear();
|
||||
mongoObjectFactory.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Account registerAccountForWhichClientIsAuthorized(String accessToken) throws ClientProtocolException, IllegalStateException, IOException, ParseException {
|
||||
Account account = getAccount(accessToken);
|
||||
public Account registerAccountForWhichClientIsAuthorized(String creatorName, String accessToken)
|
||||
throws ClientProtocolException, IllegalStateException, IOException, ParseException {
|
||||
Account account = getAccount(creatorName, accessToken);
|
||||
return getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
|
||||
SecuredDomainType.IGTIMI_ACCOUNT, account.getIdentifier().getTypeRelativeObjectIdentifier(),
|
||||
account.getUser().getEmail(), () -> {
|
||||
return storeIgtimiAccount(creatorName, accessToken, account);
|
||||
});
|
||||
}
|
||||
|
||||
private Account storeIgtimiAccount(String creatorName, String accessToken, Account account) {
|
||||
accountsByEmail.put(account.getUser().getEmail(), account);
|
||||
accessTokensByAccount.put(account, accessToken);
|
||||
mongoObjectFactory.storeAccessToken(accessToken);
|
||||
mongoObjectFactory.storeAccessToken(creatorName, accessToken);
|
||||
return account;
|
||||
}
|
||||
|
||||
private Account getAccount(String accessToken) throws ClientProtocolException, IOException, IllegalStateException, ParseException {
|
||||
protected SecurityService getSecurityService() throws ClientProtocolException, IOException, ParseException {
|
||||
return Activator.getInstance().getSecurityService();
|
||||
}
|
||||
|
||||
private Account getAccount(String creatorName, String accessToken) throws ClientProtocolException, IOException, IllegalStateException, ParseException {
|
||||
HttpClient client = new SystemDefaultHttpClient();
|
||||
HttpGet getAccount = new HttpGet(getApiV1BaseUrl()+"account?access_token="+accessToken);
|
||||
HttpResponse accountResponse = client.execute(getAccount);
|
||||
JSONObject accountJson = ConnectivityUtils.getJsonFromResponse(accountResponse);
|
||||
JSONObject userJson = (JSONObject) accountJson.get("user");
|
||||
Account account = new AccountImpl(new UserDeserializer().createUserFromJson(userJson));
|
||||
Account account = new AccountImpl(creatorName, new UserDeserializer().createUserFromJson(userJson));
|
||||
return account;
|
||||
}
|
||||
|
||||
@@ -348,7 +374,7 @@ public class IgtimiConnectionFactoryImpl implements IgtimiConnectionFactory {
|
||||
* @return the account encoding the application that is authorized for a user's account
|
||||
* @throws RuntimeException in case there was an error while retrieving the token
|
||||
*/
|
||||
public Account obtainAccessTokenFromAuthorizationCode(String code) throws ClientProtocolException, IOException, IllegalStateException, ParseException {
|
||||
public Account obtainAccessTokenFromAuthorizationCode(String creatorName, String code) throws ClientProtocolException, IOException, IllegalStateException, ParseException {
|
||||
HttpClient client = new SystemDefaultHttpClient();
|
||||
HttpPost post = new HttpPost(getOauthTokenUrl());
|
||||
List<NameValuePair> urlParameters = new ArrayList<NameValuePair>();
|
||||
@@ -365,7 +391,7 @@ public class IgtimiConnectionFactoryImpl implements IgtimiConnectionFactory {
|
||||
throw new RuntimeException(accessTokenJson.toString());
|
||||
} else {
|
||||
String accessToken = (String) accessTokenJson.get("access_token");
|
||||
result = registerAccountForWhichClientIsAuthorized(accessToken);
|
||||
result = registerAccountForWhichClientIsAuthorized(creatorName, accessToken);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -390,13 +416,13 @@ public class IgtimiConnectionFactoryImpl implements IgtimiConnectionFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Account createAccountToAccessUserData(String userEmail, String userPassword) throws ClientProtocolException,
|
||||
public Account createAccountToAccessUserData(String creatorName, String userEmail, String userPassword) throws ClientProtocolException,
|
||||
IOException, IllegalStateException, ParserConfigurationException, SAXException, ClassNotFoundException,
|
||||
InstantiationException, IllegalAccessException, ClassCastException, ParseException {
|
||||
final Account result;
|
||||
String code = authorizeAndReturnAuthorizedCode(userEmail, userPassword);
|
||||
if (code != null) {
|
||||
result = obtainAccessTokenFromAuthorizationCode(code);
|
||||
result = obtainAccessTokenFromAuthorizationCode(creatorName, code);
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
@@ -526,7 +552,7 @@ public class IgtimiConnectionFactoryImpl implements IgtimiConnectionFactory {
|
||||
if (account != null) {
|
||||
String accessToken = accessTokensByAccount.remove(account);
|
||||
accountsByEmail.remove(account.getUser().getEmail());
|
||||
mongoObjectFactory.removeAccessToken(accessToken);
|
||||
mongoObjectFactory.removeAccessToken(account.getCreatorName(), accessToken);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-7
@@ -1895,11 +1895,9 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
Document dbObject = (Document) object;
|
||||
final Serializable competitorId = (Serializable) dbObject.get(FieldNames.COMPETITOR_ID.name());
|
||||
String competitorDisplayName = (String) dbObject.get(FieldNames.COMPETITOR_DISPLAY_NAME.name());
|
||||
// The Competitor name is a new field in the list. Therefore the name might be null for existing events. In
|
||||
// this case a standard name is set.
|
||||
if (competitorDisplayName == null) {
|
||||
competitorDisplayName = "loaded competitor";
|
||||
}
|
||||
String competitorShortName = (String) dbObject.get(FieldNames.COMPETITOR_SHORT_NAME.name());
|
||||
String competitorBoatName = (String) dbObject.get(FieldNames.COMPETITOR_BOAT_NAME.name());
|
||||
String competitorBoatSailId = (String) dbObject.get(FieldNames.COMPETITOR_BOAT_SAIL_ID.name());
|
||||
// At this point we do not retrieve the competitor object since at any point in time, especially after a
|
||||
// server restart, the DomainFactory and its competitor
|
||||
// cache might be empty. But at this time the race log is loaded from database, so the competitor would be
|
||||
@@ -1925,8 +1923,9 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
} else {
|
||||
mergeState = MergeState.valueOf(mergeStateAsString);
|
||||
}
|
||||
CompetitorResultImpl positionedCompetitor = new CompetitorResultImpl(
|
||||
competitorId, competitorDisplayName, rank == null ? rankCounter : rank, maxPointsReason, score, finishingTime, comment, mergeState);
|
||||
CompetitorResultImpl positionedCompetitor = new CompetitorResultImpl(competitorId, competitorDisplayName,
|
||||
competitorShortName, competitorBoatName, competitorBoatSailId, rank == null ? rankCounter : rank,
|
||||
maxPointsReason, score, finishingTime, comment, mergeState);
|
||||
positionedCompetitors.add(positionedCompetitor);
|
||||
rankCounter++;
|
||||
}
|
||||
|
||||
+1
-1
@@ -76,7 +76,7 @@ public enum FieldNames {
|
||||
// SwissTiming configuration parameters:
|
||||
ST_CONFIG_NAME, ST_CONFIG_HOSTNAME, ST_CONFIG_PORT,
|
||||
|
||||
COMPETITOR_ID, COMPETITOR_DISPLAY_NAME,
|
||||
COMPETITOR_ID, COMPETITOR_DISPLAY_NAME, COMPETITOR_SHORT_NAME, COMPETITOR_BOAT_NAME, COMPETITOR_BOAT_SAIL_ID,
|
||||
|
||||
// leaderboard:
|
||||
LEADERBOARD_NAME, LEADERBOARD_DISPLAY_NAME, LEADERBOARD_SUPPRESSED_COMPETITORS, LEADERBOARD_SUPPRESSED_COMPETITOR_IDS,
|
||||
|
||||
+4
-1
@@ -1255,7 +1255,10 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
|
||||
private Document storePositionedCompetitor(CompetitorResult competitorResult) {
|
||||
Document result = new Document();
|
||||
result.put(FieldNames.COMPETITOR_ID.name(), competitorResult.getCompetitorId());
|
||||
result.put(FieldNames.COMPETITOR_DISPLAY_NAME.name(), competitorResult.getCompetitorDisplayName());
|
||||
result.put(FieldNames.COMPETITOR_DISPLAY_NAME.name(), competitorResult.getName());
|
||||
result.put(FieldNames.COMPETITOR_SHORT_NAME.name(), competitorResult.getShortName());
|
||||
result.put(FieldNames.COMPETITOR_BOAT_NAME.name(), competitorResult.getBoatName());
|
||||
result.put(FieldNames.COMPETITOR_BOAT_SAIL_ID.name(), competitorResult.getBoatSailId());
|
||||
result.put(FieldNames.LEADERBOARD_SCORE_CORRECTION_MAX_POINTS_REASON.name(), competitorResult.getMaxPointsReason() == null ? null : competitorResult.getMaxPointsReason().name());
|
||||
result.put(FieldNames.LEADERBOARD_CORRECTED_SCORE.name(), competitorResult.getScore());
|
||||
result.put(FieldNames.RACE_LOG_FINISHING_TIME_AS_MILLIS.name(), competitorResult.getFinishingTime() == null ? null : competitorResult.getFinishingTime().asMillis());
|
||||
|
||||
+10
-10
@@ -57,10 +57,10 @@ public class ConfirmedFinishPositioningListFinderTest extends
|
||||
public void testMostRecent() {
|
||||
RaceLogFinishPositioningConfirmedEvent event1 = createEvent(RaceLogFinishPositioningConfirmedEvent.class, 1);
|
||||
RaceLogFinishPositioningConfirmedEvent event2 = createEvent(RaceLogFinishPositioningConfirmedEvent.class, 2);
|
||||
final CompetitorResultImpl oldResultC1 = new CompetitorResultImpl("Comp1", "Comp 1", 1, MaxPointsReason.NONE, 1.0, /* finishing time */ null, /* comment */ null, MergeState.OK);
|
||||
final CompetitorResultImpl oldResultC2 = new CompetitorResultImpl("Comp2", "Comp 2", 2, MaxPointsReason.NONE, 2.0, /* finishing time */ null, /* comment */ null, MergeState.OK);
|
||||
final CompetitorResultImpl oldResultC1 = new CompetitorResultImpl("Comp1", "Comp 1", "Comp 1 Short", "Comp 1 Boat", "Comp 1 Boat Id", 1, MaxPointsReason.NONE, 1.0, /* finishing time */ null, /* comment */ null, MergeState.OK);
|
||||
final CompetitorResultImpl oldResultC2 = new CompetitorResultImpl("Comp2", "Comp 2", "Comp 2 Short", "Comp 2 Boat", "Comp 2 Boat Id", 2, MaxPointsReason.NONE, 2.0, /* finishing time */ null, /* comment */ null, MergeState.OK);
|
||||
final CompetitorResults olderResults = mockCompetitorResults(oldResultC1, oldResultC2);
|
||||
final CompetitorResultImpl newResultC2 = new CompetitorResultImpl("Comp2", "Comp 2", 2, MaxPointsReason.DNF, 3.0, /* finishing time */ null, /* comment */ null, MergeState.OK);
|
||||
final CompetitorResultImpl newResultC2 = new CompetitorResultImpl("Comp2", "Comp 2", "Comp 3 Short", "Comp 3 Boat", "Comp 3 Boat Id", 2, MaxPointsReason.DNF, 3.0, /* finishing time */ null, /* comment */ null, MergeState.OK);
|
||||
final CompetitorResults newerResults = mockCompetitorResults(newResultC2);
|
||||
when(event1.getPositionedCompetitorsIDsNamesMaxPointsReasons()).thenReturn(olderResults);
|
||||
when(event2.getPositionedCompetitorsIDsNamesMaxPointsReasons()).thenReturn(newerResults);
|
||||
@@ -75,16 +75,16 @@ public class ConfirmedFinishPositioningListFinderTest extends
|
||||
RaceLogFinishPositioningConfirmedEvent event2 = createEvent(/* priority */ 1, RaceLogFinishPositioningConfirmedEvent.class, 2);
|
||||
RaceLogFinishPositioningConfirmedEvent event3 = createEvent(/* priority */ 2, RaceLogFinishPositioningConfirmedEvent.class, 3);
|
||||
RaceLogFinishPositioningConfirmedEvent event4 = createEvent(/* priority */ 1, RaceLogFinishPositioningConfirmedEvent.class, 4);
|
||||
final CompetitorResultImpl e1ResultC1 = new CompetitorResultImpl("Comp1", "Comp 1", 1, MaxPointsReason.DNC, 6.0, /* finishing time */ null, /* comment */ null, MergeState.OK);
|
||||
final CompetitorResultImpl e1ResultC2 = new CompetitorResultImpl("Comp2", "Comp 2", 2, MaxPointsReason.NONE, 2.0, /* finishing time */ null, /* comment */ null, MergeState.OK);
|
||||
final CompetitorResultImpl e1ResultC1 = new CompetitorResultImpl("Comp1", "Comp 1", "Comp 1 Short", "Comp 1 Boat", "Comp 1 Boat Id", 1, MaxPointsReason.DNC, 6.0, /* finishing time */ null, /* comment */ null, MergeState.OK);
|
||||
final CompetitorResultImpl e1ResultC2 = new CompetitorResultImpl("Comp2", "Comp 2", "Comp 2 Short", "Comp 2 Boat", "Comp 2 Boat Id", 2, MaxPointsReason.NONE, 2.0, /* finishing time */ null, /* comment */ null, MergeState.OK);
|
||||
final CompetitorResults e1Results = mockCompetitorResults(e1ResultC1, e1ResultC2);
|
||||
final CompetitorResultImpl e2ResultC2 = new CompetitorResultImpl("Comp2", "Comp 2", 2, MaxPointsReason.DNF, 3.0, /* finishing time */ null, /* comment */ null, MergeState.OK);
|
||||
final CompetitorResultImpl e2ResultC2 = new CompetitorResultImpl("Comp2", "Comp 2", "Comp 2 Short", "Comp 2 Boat", "Comp 2 Boat Id", 2, MaxPointsReason.DNF, 3.0, /* finishing time */ null, /* comment */ null, MergeState.OK);
|
||||
final CompetitorResults e2Results = mockCompetitorResults(e2ResultC2);
|
||||
final CompetitorResultImpl e3ResultC2 = new CompetitorResultImpl("Comp2", "Comp 2", 2, MaxPointsReason.DSQ, 6.0, /* finishing time */ null, /* comment */ null, MergeState.OK);
|
||||
final CompetitorResultImpl e3ResultC3 = new CompetitorResultImpl("Comp3", "Comp 3", 2, MaxPointsReason.DNF, 3.0, /* finishing time */ null, /* comment */ null, MergeState.OK);
|
||||
final CompetitorResultImpl e3ResultC2 = new CompetitorResultImpl("Comp2", "Comp 2", "Comp 2 Short", "Comp 2 Boat", "Comp 2 Boat Id", 2, MaxPointsReason.DSQ, 6.0, /* finishing time */ null, /* comment */ null, MergeState.OK);
|
||||
final CompetitorResultImpl e3ResultC3 = new CompetitorResultImpl("Comp3", "Comp 3", "Comp 3 Short", "Comp 3 Boat", "Comp 3 Boat Id", 2, MaxPointsReason.DNF, 3.0, /* finishing time */ null, /* comment */ null, MergeState.OK);
|
||||
final CompetitorResults e3Results = mockCompetitorResults(e3ResultC2, e3ResultC3);
|
||||
final CompetitorResultImpl e4ResultC1 = new CompetitorResultImpl("Comp1", "Comp 1", 1, /* maxPointsReason */ null, /* score */ null, /* finishing time */ null, /* comment */ null, MergeState.OK);
|
||||
final CompetitorResultImpl e4ResultC4 = new CompetitorResultImpl("Comp4", "Comp 4", 2, MaxPointsReason.DNF, 3.0, /* finishing time */ null, /* comment */ null, MergeState.OK);
|
||||
final CompetitorResultImpl e4ResultC1 = new CompetitorResultImpl("Comp1", "Comp 1", "Comp 1 Short", "Comp 1 Boat", "Comp 1 Boat Id", 1, /* maxPointsReason */ null, /* score */ null, /* finishing time */ null, /* comment */ null, MergeState.OK);
|
||||
final CompetitorResultImpl e4ResultC4 = new CompetitorResultImpl("Comp4", "Comp 4", "Comp 4 Short", "Comp 4 Boat", "Comp 4 Boat Id", 2, MaxPointsReason.DNF, 3.0, /* finishing time */ null, /* comment */ null, MergeState.OK);
|
||||
final CompetitorResults e4Results = mockCompetitorResults(e4ResultC1, e4ResultC4);
|
||||
when(event1.getPositionedCompetitorsIDsNamesMaxPointsReasons()).thenReturn(e1Results);
|
||||
when(event2.getPositionedCompetitorsIDsNamesMaxPointsReasons()).thenReturn(e2Results);
|
||||
|
||||
+7
-1
@@ -40,7 +40,13 @@ public interface CompetitorResult extends Serializable {
|
||||
|
||||
Serializable getCompetitorId();
|
||||
|
||||
String getCompetitorDisplayName();
|
||||
String getName();
|
||||
|
||||
String getShortName();
|
||||
|
||||
String getBoatName();
|
||||
|
||||
String getBoatSailId();
|
||||
|
||||
int getOneBasedRank();
|
||||
|
||||
|
||||
+66
-16
@@ -11,7 +11,9 @@ public class CompetitorResultImpl implements CompetitorResult {
|
||||
|
||||
private final Serializable competitorId;
|
||||
|
||||
private final String competitorDisplayName;
|
||||
private final String competitorName;
|
||||
|
||||
private final String competitorShortName;
|
||||
|
||||
private final int oneBasedRank;
|
||||
|
||||
@@ -24,13 +26,32 @@ public class CompetitorResultImpl implements CompetitorResult {
|
||||
private final String comment;
|
||||
|
||||
private final MergeState mergeState;
|
||||
|
||||
public CompetitorResultImpl(Serializable competitorId, String competitorDisplayName, int oneBasedRank,
|
||||
MaxPointsReason maxPointsReason, Double score, TimePoint finishingTime, String comment,
|
||||
MergeState mergeState) {
|
||||
|
||||
private final String boatName;
|
||||
|
||||
private final String boatSailId;
|
||||
|
||||
public CompetitorResultImpl(CompetitorResult item) {
|
||||
this(item.getCompetitorId(), item.getName(), item.getShortName(), item.getBoatName(), item.getBoatSailId(),
|
||||
item.getOneBasedRank(), item.getMaxPointsReason(), item.getScore(), item.getFinishingTime(),
|
||||
item.getComment(), item.getMergeState());
|
||||
}
|
||||
|
||||
public CompetitorResultImpl(CompetitorResult item, int oneBasedRank) {
|
||||
this(item.getCompetitorId(), item.getName(), item.getShortName(), item.getBoatName(), item.getBoatSailId(),
|
||||
oneBasedRank, item.getMaxPointsReason(), item.getScore(), item.getFinishingTime(),
|
||||
item.getComment(), item.getMergeState());
|
||||
}
|
||||
|
||||
public CompetitorResultImpl(Serializable competitorId, String competitorName, String competitorShortName,
|
||||
String boatName, String boatSailId, int oneBasedRank, MaxPointsReason maxPointsReason, Double score,
|
||||
TimePoint finishingTime, String comment, MergeState mergeState) {
|
||||
super();
|
||||
this.competitorId = competitorId;
|
||||
this.competitorDisplayName = competitorDisplayName;
|
||||
this.competitorName = competitorName;
|
||||
this.competitorShortName = competitorShortName;
|
||||
this.boatName = boatName;
|
||||
this.boatSailId = boatSailId;
|
||||
this.oneBasedRank = oneBasedRank;
|
||||
this.maxPointsReason = maxPointsReason;
|
||||
this.score = score;
|
||||
@@ -45,10 +66,25 @@ public class CompetitorResultImpl implements CompetitorResult {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCompetitorDisplayName() {
|
||||
return competitorDisplayName;
|
||||
public String getName() {
|
||||
return competitorName;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getShortName() {
|
||||
return competitorShortName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBoatName() {
|
||||
return boatName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBoatSailId() {
|
||||
return boatSailId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOneBasedRank() {
|
||||
return oneBasedRank;
|
||||
@@ -84,8 +120,11 @@ public class CompetitorResultImpl implements CompetitorResult {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((comment == null) ? 0 : comment.hashCode());
|
||||
result = prime * result + ((competitorDisplayName == null) ? 0 : competitorDisplayName.hashCode());
|
||||
result = prime * result + ((competitorName == null) ? 0 : competitorName.hashCode());
|
||||
result = prime * result + ((competitorShortName == null) ? 0 : competitorShortName.hashCode());
|
||||
result = prime * result + ((competitorId == null) ? 0 : competitorId.hashCode());
|
||||
result = prime * result + ((boatName == null) ? 0 : boatName.hashCode());
|
||||
result = prime * result + ((boatSailId == null) ? 0 : boatSailId.hashCode());
|
||||
result = prime * result + ((finishingTime == null) ? 0 : finishingTime.hashCode());
|
||||
result = prime * result + ((maxPointsReason == null) ? 0 : maxPointsReason.hashCode());
|
||||
result = prime * result + oneBasedRank;
|
||||
@@ -108,16 +147,26 @@ public class CompetitorResultImpl implements CompetitorResult {
|
||||
return false;
|
||||
} else if (!comment.equals(other.comment))
|
||||
return false;
|
||||
if (competitorDisplayName == null) {
|
||||
if (other.competitorDisplayName != null)
|
||||
if (competitorName == null) {
|
||||
if (other.competitorName != null)
|
||||
return false;
|
||||
} else if (!competitorDisplayName.equals(other.competitorDisplayName))
|
||||
} else if (!competitorName.equals(other.competitorName))
|
||||
return false;
|
||||
if (competitorId == null) {
|
||||
if (other.competitorId != null)
|
||||
return false;
|
||||
} else if (!competitorId.equals(other.competitorId))
|
||||
return false;
|
||||
if (boatName == null) {
|
||||
if (other.boatName != null)
|
||||
return false;
|
||||
} else if (!boatName.equals(other.boatName))
|
||||
return false;
|
||||
if (boatSailId == null) {
|
||||
if (other.boatSailId != null)
|
||||
return false;
|
||||
} else if (!boatSailId.equals(other.boatSailId))
|
||||
return false;
|
||||
if (finishingTime == null) {
|
||||
if (other.finishingTime != null)
|
||||
return false;
|
||||
@@ -142,9 +191,10 @@ public class CompetitorResultImpl implements CompetitorResult {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CompetitorResultImpl [competitorId=" + competitorId + ", competitorName=" + competitorDisplayName + ", rank="
|
||||
+ oneBasedRank + ", maxPointsReason=" + maxPointsReason + ", score=" + score + ", finishingTime="
|
||||
+ finishingTime + ", comment=" + comment + ", mergeState=" + mergeState + "]";
|
||||
return "CompetitorResultImpl [competitorId=" + competitorId + ", competitorName=" + competitorName
|
||||
+ ", competitorShortName=" + competitorShortName + ", boatName=" + boatName+ ", boatSailId="
|
||||
+ boatSailId + ", rank=" + oneBasedRank + ", maxPointsReason=" + maxPointsReason + ", score="+ score
|
||||
+ ", finishingTime=" + finishingTime + ", comment=" + comment + ", mergeState=" + mergeState + "]";
|
||||
}
|
||||
|
||||
}
|
||||
+11
-3
@@ -14,7 +14,15 @@ public interface SwissTimingAdapterPersistence {
|
||||
|
||||
Iterable<SwissTimingArchiveConfiguration> getSwissTimingArchiveConfigurations();
|
||||
|
||||
void storeSwissTimingConfiguration(SwissTimingConfiguration swissTimingConfiguration);
|
||||
|
||||
void storeSwissTimingArchiveConfiguration(SwissTimingArchiveConfiguration createSwissTimingArchiveConfiguration);
|
||||
void createSwissTimingArchiveConfiguration(SwissTimingArchiveConfiguration swissTimingArchiveConfiguration);
|
||||
|
||||
void updateSwissTimingArchiveConfiguration(SwissTimingArchiveConfiguration swissTimingArchiveConfiguration);
|
||||
|
||||
void deleteSwissTimingArchiveConfiguration(SwissTimingArchiveConfiguration swissTimingArchiveConfiguration);
|
||||
|
||||
void deleteSwissTimingConfiguration(String creatorName, String jsonURL);
|
||||
|
||||
void updateSwissTimingConfiguration(SwissTimingConfiguration createSwissTimingConfiguration);
|
||||
|
||||
void createSwissTimingConfiguration(SwissTimingConfiguration createSwissTimingConfiguration);
|
||||
}
|
||||
+1
-1
@@ -3,7 +3,7 @@ package com.sap.sailing.domain.swisstimingadapter.persistence.impl;
|
||||
public enum FieldNames {
|
||||
// SwissTiming configuration parameters:
|
||||
ST_CONFIG_NAME, ST_CONFIG_HOSTNAME, ST_CONFIG_PORT, ST_CONFIG_JSON_URL, ST_CONFIG_UPDATE_URL,
|
||||
ST_CONFIG_UPDATE_USERNAME, ST_CONFIG_UPDATE_PASSWORD, ST_ARCHIVE_JSON_URL,
|
||||
ST_CONFIG_UPDATE_USERNAME, ST_CONFIG_UPDATE_PASSWORD, ST_CONFIG_CREATOR_NAME, ST_ARCHIVE_JSON_URL, ST_ARCHIVE_CREATOR_NAME,
|
||||
|
||||
// last message count field:
|
||||
LAST_MESSAGE_COUNT,
|
||||
|
||||
+96
-11
@@ -60,7 +60,24 @@ public class SwissTimingAdapterPersistenceImpl implements SwissTimingAdapterPers
|
||||
String updateURL = (String) object.get(FieldNames.ST_CONFIG_UPDATE_URL.name());
|
||||
String updateUsername = (String) object.get(FieldNames.ST_CONFIG_UPDATE_USERNAME.name());
|
||||
String updatePassword = (String) object.get(FieldNames.ST_CONFIG_UPDATE_PASSWORD.name());
|
||||
return swissTimingFactory.createSwissTimingConfiguration(name, jsonURL, hostname, port, updateURL, updateUsername, updatePassword);
|
||||
String creatorName = object.getString(FieldNames.ST_CONFIG_CREATOR_NAME.name());
|
||||
|
||||
// migration code
|
||||
final boolean needsUpdate = (creatorName == null);
|
||||
if (needsUpdate) {
|
||||
// No creator is set yet -> existing configurations are assumed to belong to the admin
|
||||
creatorName = "admin";
|
||||
}
|
||||
final SwissTimingConfiguration loadedSwissTimingConfiguration = swissTimingFactory.createSwissTimingConfiguration(name, jsonURL, hostname, port, updateURL,
|
||||
updateUsername, updatePassword, creatorName);
|
||||
|
||||
if (needsUpdate) {
|
||||
// recreating the config on the DB because the composite key changed
|
||||
deleteSwissTimingConfiguration(null, jsonURL);
|
||||
createSwissTimingConfiguration(loadedSwissTimingConfiguration);
|
||||
}
|
||||
|
||||
return loadedSwissTimingConfiguration;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -82,12 +99,36 @@ public class SwissTimingAdapterPersistenceImpl implements SwissTimingAdapterPers
|
||||
}
|
||||
|
||||
private SwissTimingArchiveConfiguration loadSwissTimingArchiveConfiguration(Document object) {
|
||||
return swissTimingFactory.createSwissTimingArchiveConfiguration((String) object.get(FieldNames.ST_ARCHIVE_JSON_URL.name()));
|
||||
final String jsonUrl = object.getString(FieldNames.ST_ARCHIVE_JSON_URL.name());
|
||||
String creatorName = object.getString(FieldNames.ST_ARCHIVE_CREATOR_NAME.name());
|
||||
|
||||
final boolean needsUpdate = (creatorName == null);
|
||||
if (needsUpdate) {
|
||||
// No creator is set yet -> existing configurations are assumed to belong to the admin
|
||||
creatorName = "admin";
|
||||
}
|
||||
|
||||
final SwissTimingArchiveConfiguration loadedSwissTimingArchiveConfiguration = swissTimingFactory.createSwissTimingArchiveConfiguration(
|
||||
jsonUrl,
|
||||
creatorName);
|
||||
|
||||
if (needsUpdate) {
|
||||
// recreating the config on the DB because the composite key changed
|
||||
deleteSwissTimingArchiveConfiguration(
|
||||
swissTimingFactory.createSwissTimingArchiveConfiguration(jsonUrl, null));
|
||||
createSwissTimingArchiveConfiguration(loadedSwissTimingArchiveConfiguration);
|
||||
}
|
||||
return loadedSwissTimingArchiveConfiguration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeSwissTimingConfiguration(SwissTimingConfiguration swissTimingConfiguration) {
|
||||
public void createSwissTimingConfiguration(SwissTimingConfiguration swissTimingConfiguration) {
|
||||
MongoCollection<org.bson.Document> stConfigCollection = database.getCollection(CollectionNames.SWISSTIMING_CONFIGURATIONS.name());
|
||||
Document result = storeSwissTimingConfiguration(swissTimingConfiguration);
|
||||
stConfigCollection.withWriteConcern(WriteConcern.ACKNOWLEDGED).insertOne(result);
|
||||
}
|
||||
|
||||
private Document storeSwissTimingConfiguration(SwissTimingConfiguration swissTimingConfiguration) {
|
||||
Document result = new Document();
|
||||
result.put(FieldNames.ST_CONFIG_NAME.name(), swissTimingConfiguration.getName());
|
||||
result.put(FieldNames.ST_CONFIG_JSON_URL.name(), swissTimingConfiguration.getJsonURL());
|
||||
@@ -96,19 +137,63 @@ public class SwissTimingAdapterPersistenceImpl implements SwissTimingAdapterPers
|
||||
result.put(FieldNames.ST_CONFIG_UPDATE_URL.name(), swissTimingConfiguration.getUpdateURL());
|
||||
result.put(FieldNames.ST_CONFIG_UPDATE_USERNAME.name(), swissTimingConfiguration.getUpdateUsername());
|
||||
result.put(FieldNames.ST_CONFIG_UPDATE_PASSWORD.name(), swissTimingConfiguration.getUpdatePassword());
|
||||
final Document updateQuery = new Document(FieldNames.ST_CONFIG_JSON_URL.name(),
|
||||
swissTimingConfiguration.getJsonURL());
|
||||
stConfigCollection.withWriteConcern(WriteConcern.ACKNOWLEDGED).replaceOne(updateQuery, result,
|
||||
new UpdateOptions().upsert(true));
|
||||
result.put(FieldNames.ST_CONFIG_CREATOR_NAME.name(), swissTimingConfiguration.getCreatorName());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeSwissTimingArchiveConfiguration(
|
||||
SwissTimingArchiveConfiguration createSwissTimingArchiveConfiguration) {
|
||||
public void createSwissTimingArchiveConfiguration(
|
||||
SwissTimingArchiveConfiguration config) {
|
||||
MongoCollection<org.bson.Document> stArchiveConfigCollection = database.getCollection(CollectionNames.SWISSTIMING_ARCHIVE_CONFIGURATIONS.name());
|
||||
Document result = new Document();
|
||||
result.put(FieldNames.ST_ARCHIVE_JSON_URL.name(), createSwissTimingArchiveConfiguration.getJsonURL());
|
||||
Document result = storeSwissTimingArchiveConfiguration(config);
|
||||
stArchiveConfigCollection.withWriteConcern(WriteConcern.ACKNOWLEDGED).insertOne(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSwissTimingArchiveConfiguration(
|
||||
SwissTimingArchiveConfiguration config) {
|
||||
MongoCollection<org.bson.Document> stArchiveConfigCollection = database
|
||||
.getCollection(CollectionNames.SWISSTIMING_ARCHIVE_CONFIGURATIONS.name());
|
||||
Document result = storeSwissTimingArchiveConfiguration(config);
|
||||
stArchiveConfigCollection.withWriteConcern(WriteConcern.ACKNOWLEDGED).replaceOne(result, result,
|
||||
new UpdateOptions().upsert(true));
|
||||
}
|
||||
|
||||
private Document storeSwissTimingArchiveConfiguration(SwissTimingArchiveConfiguration config) {
|
||||
Document result = new Document();
|
||||
result.put(FieldNames.ST_ARCHIVE_JSON_URL.name(), config.getJsonURL());
|
||||
result.put(FieldNames.ST_ARCHIVE_CREATOR_NAME.name(), config.getCreatorName());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteSwissTimingArchiveConfiguration(
|
||||
SwissTimingArchiveConfiguration config) {
|
||||
MongoCollection<org.bson.Document> stArchiveConfigCollection = database
|
||||
.getCollection(CollectionNames.SWISSTIMING_ARCHIVE_CONFIGURATIONS.name());
|
||||
Document result = storeSwissTimingArchiveConfiguration(config);
|
||||
stArchiveConfigCollection.withWriteConcern(WriteConcern.ACKNOWLEDGED).deleteOne(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteSwissTimingConfiguration(String creatorName, String jsonURL) {
|
||||
MongoCollection<org.bson.Document> stConfigCollection = database
|
||||
.getCollection(CollectionNames.SWISSTIMING_CONFIGURATIONS.name());
|
||||
Document deleteQuery = new Document(FieldNames.ST_CONFIG_JSON_URL.name(), jsonURL);
|
||||
deleteQuery.put(FieldNames.ST_CONFIG_CREATOR_NAME.name(), creatorName);
|
||||
stConfigCollection.withWriteConcern(WriteConcern.ACKNOWLEDGED).deleteMany(deleteQuery);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSwissTimingConfiguration(SwissTimingConfiguration config) {
|
||||
MongoCollection<org.bson.Document> stConfigCollection = database
|
||||
.getCollection(CollectionNames.SWISSTIMING_CONFIGURATIONS.name());
|
||||
Document result = storeSwissTimingConfiguration(config);
|
||||
|
||||
Document updateQuery = new Document(FieldNames.ST_CONFIG_JSON_URL.name(), config.getJsonURL());
|
||||
updateQuery.put(FieldNames.ST_CONFIG_CREATOR_NAME.name(), config.getCreatorName());
|
||||
|
||||
stConfigCollection.withWriteConcern(WriteConcern.ACKNOWLEDGED).replaceOne(updateQuery, result,
|
||||
new UpdateOptions().upsert(true));
|
||||
}
|
||||
}
|
||||
+6
-3
@@ -10,6 +10,8 @@ public interface SwissTimingArchiveConfiguration extends WithQualifiedObjectIden
|
||||
|
||||
String getJsonURL();
|
||||
|
||||
String getCreatorName();
|
||||
|
||||
@Override
|
||||
default String getName() {
|
||||
return getJsonURL();
|
||||
@@ -26,10 +28,11 @@ public interface SwissTimingArchiveConfiguration extends WithQualifiedObjectIden
|
||||
}
|
||||
|
||||
default TypeRelativeObjectIdentifier getTypeRelativeObjectIdentifier() {
|
||||
return getTypeRelativeObjectIdentifier(getJsonURL());
|
||||
return getTypeRelativeObjectIdentifier(getJsonURL(), getCreatorName());
|
||||
}
|
||||
|
||||
public static TypeRelativeObjectIdentifier getTypeRelativeObjectIdentifier(String jsonUrl) {
|
||||
return new TypeRelativeObjectIdentifier(jsonUrl);
|
||||
public static TypeRelativeObjectIdentifier getTypeRelativeObjectIdentifier(String jsonUrl, String username) {
|
||||
return username == null ? new TypeRelativeObjectIdentifier(jsonUrl)
|
||||
: new TypeRelativeObjectIdentifier(jsonUrl, username);
|
||||
}
|
||||
}
|
||||
+6
-3
@@ -13,6 +13,8 @@ import com.sap.sse.security.shared.WithQualifiedObjectIdentifier;
|
||||
*
|
||||
*/
|
||||
public interface SwissTimingConfiguration extends WithQualifiedObjectIdentifier {
|
||||
|
||||
String getCreatorName();
|
||||
String getName();
|
||||
|
||||
String getJsonURL();
|
||||
@@ -38,10 +40,11 @@ public interface SwissTimingConfiguration extends WithQualifiedObjectIdentifier
|
||||
}
|
||||
|
||||
default TypeRelativeObjectIdentifier getTypeRelativeObjectIdentifier() {
|
||||
return getTypeRelativeObjectIdentifier(getJsonURL());
|
||||
return getTypeRelativeObjectIdentifier(getJsonURL(), getCreatorName());
|
||||
}
|
||||
|
||||
public static TypeRelativeObjectIdentifier getTypeRelativeObjectIdentifier(String jsonUrl) {
|
||||
return new TypeRelativeObjectIdentifier(jsonUrl);
|
||||
public static TypeRelativeObjectIdentifier getTypeRelativeObjectIdentifier(String jsonUrl, String username) {
|
||||
return username == null ? new TypeRelativeObjectIdentifier(jsonUrl)
|
||||
: new TypeRelativeObjectIdentifier(jsonUrl, username);
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -53,7 +53,8 @@ public interface SwissTimingFactory {
|
||||
|
||||
SailMasterTransceiver createSailMasterTransceiver();
|
||||
|
||||
SwissTimingConfiguration createSwissTimingConfiguration(String name, String jsonURL, String hostname, Integer port, String updateURL, String updateUsername, String updatePassword);
|
||||
SwissTimingConfiguration createSwissTimingConfiguration(String name, String jsonURL, String hostname, Integer port,
|
||||
String updateURL, String updateUsername, String updatePassword, String creatorName);
|
||||
|
||||
SwissTimingRaceTracker createRaceTracker(RaceLogStore raceLogStore, RegattaLogStore regattaLogStore, WindStore windStore,
|
||||
DomainFactory domainFactory, TrackedRegattaRegistry trackedRegattaRegistry, RaceLogResolver raceLogResolver, SwissTimingTrackingConnectivityParameters connectivityParams,
|
||||
@@ -69,6 +70,6 @@ public interface SwissTimingFactory {
|
||||
|
||||
SailMasterMessage createMessage(String message);
|
||||
|
||||
SwissTimingArchiveConfiguration createSwissTimingArchiveConfiguration(String string);
|
||||
SwissTimingArchiveConfiguration createSwissTimingArchiveConfiguration(String jsonUrl, String creatorName);
|
||||
|
||||
}
|
||||
+8
-1
@@ -5,14 +5,21 @@ import com.sap.sailing.domain.swisstimingadapter.SwissTimingArchiveConfiguration
|
||||
public class SwissTimingArchiveConfigurationImpl implements SwissTimingArchiveConfiguration {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final String jsonUrl;
|
||||
private final String creatorName;
|
||||
|
||||
public SwissTimingArchiveConfigurationImpl(String jsonUrl) {
|
||||
public SwissTimingArchiveConfigurationImpl(String jsonUrl, String creatorName) {
|
||||
super();
|
||||
this.jsonUrl = jsonUrl;
|
||||
this.creatorName = creatorName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getJsonURL() {
|
||||
return jsonUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreatorName() {
|
||||
return creatorName;
|
||||
}
|
||||
}
|
||||
+9
-1
@@ -11,8 +11,10 @@ public class SwissTimingConfigurationImpl implements SwissTimingConfiguration {
|
||||
private final String updateURL;
|
||||
private final String updateUsername;
|
||||
private final String updatePassword;
|
||||
private String creatorName;
|
||||
|
||||
public SwissTimingConfigurationImpl(String name, String jsonURL, String hostname, Integer port, String updateURL, String updateUsername, String updatePassword) {
|
||||
public SwissTimingConfigurationImpl(String name, String jsonURL, String hostname, Integer port, String updateURL,
|
||||
String updateUsername, String updatePassword, String creatorName) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.jsonURL = jsonURL;
|
||||
@@ -21,6 +23,12 @@ public class SwissTimingConfigurationImpl implements SwissTimingConfiguration {
|
||||
this.updateURL = updateURL;
|
||||
this.updateUsername = updateUsername;
|
||||
this.updatePassword = updatePassword;
|
||||
this.creatorName = creatorName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCreatorName() {
|
||||
return creatorName;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+5
-4
@@ -85,8 +85,9 @@ public class SwissTimingFactoryImpl implements SwissTimingFactory {
|
||||
|
||||
@Override
|
||||
public SwissTimingConfiguration createSwissTimingConfiguration(String name, String jsonURL, String hostname,
|
||||
Integer port, String updateURL, String updateUsername, String updatePassword) {
|
||||
return new SwissTimingConfigurationImpl(name, jsonURL, hostname, port, updateURL, updateUsername, updatePassword);
|
||||
Integer port, String updateURL, String updateUsername, String updatePassword, String creatorName) {
|
||||
return new SwissTimingConfigurationImpl(name, jsonURL, hostname, port, updateURL, updateUsername,
|
||||
updatePassword, creatorName);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -125,7 +126,7 @@ public class SwissTimingFactoryImpl implements SwissTimingFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SwissTimingArchiveConfiguration createSwissTimingArchiveConfiguration(String jsonUrl) {
|
||||
return new SwissTimingArchiveConfigurationImpl(jsonUrl);
|
||||
public SwissTimingArchiveConfiguration createSwissTimingArchiveConfiguration(String jsonUrl, String creatorName) {
|
||||
return new SwissTimingArchiveConfigurationImpl(jsonUrl, creatorName);
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -153,8 +153,8 @@ public class MarkPassingUpdateFromRaceLogFinishPositioingListTest extends Abstra
|
||||
final CompetitorResults results = new CompetitorResultsImpl();
|
||||
int rank = 1;
|
||||
for (Pair<Competitor, TimePoint> finishingTime : finishingTimes) {
|
||||
results.add(new CompetitorResultImpl(finishingTime.getA().getId(), finishingTime.getA().getName(), rank++, /* maxPointsReason */
|
||||
null, /* score */null, finishingTime.getB(), /* comment */null, MergeState.OK));
|
||||
results.add(new CompetitorResultImpl(finishingTime.getA().getId(), finishingTime.getA().getName(), finishingTime.getA().getShortName(),
|
||||
"BoatName", "BoatSailId", rank++, /* maxPointsReason */ null, /* score */null, finishingTime.getB(), /* comment */null, MergeState.OK));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
+7
-1
@@ -21,6 +21,12 @@ public interface MongoObjectFactory {
|
||||
* {@link DomainObjectFactory#getTracTracConfigurations()} called for the same <code>database</code>
|
||||
* will return an equal <code>tracTracConfiguration</code> in its results.
|
||||
*/
|
||||
void storeTracTracConfiguration(TracTracConfiguration tracTracConfiguration);
|
||||
void createTracTracConfiguration(TracTracConfiguration tracTracConfiguration);
|
||||
|
||||
void updateTracTracConfiguration(TracTracConfiguration tracTracConfiguration);
|
||||
|
||||
void deleteTracTracConfiguration(String creatorName, String jsonurl);
|
||||
|
||||
void clear();
|
||||
|
||||
}
|
||||
+2
@@ -8,4 +8,6 @@ public interface PersistenceFactory {
|
||||
PersistenceFactory INSTANCE = new PersistenceFactoryImpl();
|
||||
|
||||
DomainObjectFactory createDomainObjectFactory(MongoDatabase db, DomainFactory tracTracDomainFactory);
|
||||
|
||||
MongoObjectFactory createMongoObjectFactory(MongoDatabase db);
|
||||
}
|
||||
+9
@@ -24,6 +24,7 @@ import com.sap.sailing.domain.tractracadapter.impl.RaceTrackingConnectivityParam
|
||||
import com.sap.sse.common.TypeBasedServiceFinder;
|
||||
import com.sap.sse.mongodb.MongoDBService;
|
||||
import com.sap.sse.security.SecurityService;
|
||||
import com.sap.sse.util.ClearStateTestSupport;
|
||||
import com.sap.sse.util.ServiceTrackerFactory;
|
||||
|
||||
public class Activator implements BundleActivator {
|
||||
@@ -61,6 +62,8 @@ public class Activator implements BundleActivator {
|
||||
|
||||
com.sap.sailing.domain.tractracadapter.persistence.DomainObjectFactory tractracDomainObjectFactory = com.sap.sailing.domain.tractracadapter.persistence.PersistenceFactory.INSTANCE
|
||||
.createDomainObjectFactory(mongoObjectFactory.getDatabase(), domainFactory);
|
||||
com.sap.sailing.domain.tractracadapter.persistence.MongoObjectFactory tractracMongoObjectFactory = com.sap.sailing.domain.tractracadapter.persistence.PersistenceFactory.INSTANCE
|
||||
.createMongoObjectFactory(mongoObjectFactory.getDatabase());
|
||||
for (TracTracConfiguration trackTrackConfig : tractracDomainObjectFactory.getTracTracConfigurations()) {
|
||||
securityService.migrateOwnership(trackTrackConfig);
|
||||
}
|
||||
@@ -69,6 +72,12 @@ public class Activator implements BundleActivator {
|
||||
|
||||
properties.put(TypeBasedServiceFinder.TYPE, RaceTrackingConnectivityParametersImpl.TYPE);
|
||||
context.registerService(RaceTrackingConnectivityParametersHandler.class, paramsHandler, properties);
|
||||
context.registerService(ClearStateTestSupport.class.getName(), new ClearStateTestSupport() {
|
||||
@Override
|
||||
public void clearState() throws Exception {
|
||||
tractracMongoObjectFactory.clear();
|
||||
}
|
||||
}, null);
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Exception trying to register TracTrac RaceTrackingConnectivityParametersHandler implementation", e);
|
||||
}
|
||||
|
||||
+19
-2
@@ -51,14 +51,31 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
String courseDesignUpdateUri = courseDesignUpdateUriObject == null ? "" : (String) courseDesignUpdateUriObject;
|
||||
String tracTracUsername = tracTracUsernameObject == null ? "" : (String) tracTracUsernameObject;
|
||||
String tracTracPassword = tracTracPasswordObject == null ? "" : (String) tracTracPasswordObject;
|
||||
String creatorName = (String) object.get(FieldNames.TT_CONFIG_CREATOR_NAME.name());
|
||||
String jsonURL = (String) object.get(FieldNames.TT_CONFIG_JSON_URL.name());
|
||||
|
||||
return tracTracDomainFactory.createTracTracConfiguration((String) object.get(FieldNames.TT_CONFIG_NAME.name()),
|
||||
(String) object.get(FieldNames.TT_CONFIG_JSON_URL.name()),
|
||||
final boolean needsUpdate = (creatorName == null);
|
||||
if (needsUpdate) {
|
||||
// No creator is set yet -> existing configurations are assumed to belong to the admin
|
||||
creatorName = "admin";
|
||||
}
|
||||
|
||||
final TracTracConfiguration loadedTracTracConfiguration = tracTracDomainFactory.createTracTracConfiguration(
|
||||
creatorName,
|
||||
(String) object.get(FieldNames.TT_CONFIG_NAME.name()),
|
||||
jsonURL,
|
||||
(String) object.get(FieldNames.TT_CONFIG_LIVE_DATA_URI.name()),
|
||||
(String) object.get(FieldNames.TT_CONFIG_STORED_DATA_URI.name()),
|
||||
courseDesignUpdateUri,
|
||||
tracTracUsername,
|
||||
tracTracPassword);
|
||||
|
||||
if (needsUpdate) {
|
||||
// recreating the config on the DB because the composite key changed
|
||||
new MongoObjectFactoryImpl(database).deleteTracTracConfiguration(null, jsonURL);
|
||||
new MongoObjectFactoryImpl(database).createTracTracConfiguration(loadedTracTracConfiguration);
|
||||
}
|
||||
return loadedTracTracConfiguration;
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -2,6 +2,6 @@ package com.sap.sailing.domain.tractracadapter.persistence.impl;
|
||||
|
||||
public enum FieldNames {
|
||||
// TracTrac configuration parameters:
|
||||
TT_CONFIG_NAME, TT_CONFIG_JSON_URL, TT_CONFIG_LIVE_DATA_URI, TT_CONFIG_STORED_DATA_URI, TT_CONFIG_COURSE_DESIGN_UPDATE_URI, TT_CONFIG_TRACTRAC_USERNAME, TT_CONFIG_TRACTRAC_PASSWORD,
|
||||
TT_CONFIG_CREATOR_NAME, TT_CONFIG_NAME, TT_CONFIG_JSON_URL, TT_CONFIG_LIVE_DATA_URI, TT_CONFIG_STORED_DATA_URI, TT_CONFIG_COURSE_DESIGN_UPDATE_URI, TT_CONFIG_TRACTRAC_USERNAME, TT_CONFIG_TRACTRAC_PASSWORD,
|
||||
|
||||
}
|
||||
+36
-6
@@ -16,11 +16,36 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
|
||||
super();
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
database.getCollection(CollectionNames.TRACTRAC_CONFIGURATIONS.name())
|
||||
.withWriteConcern(WriteConcern.ACKNOWLEDGED).drop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeTracTracConfiguration(TracTracConfiguration tracTracConfiguration) {
|
||||
public void createTracTracConfiguration(TracTracConfiguration tracTracConfiguration) {
|
||||
MongoCollection<Document> ttConfigCollection = database.getCollection(CollectionNames.TRACTRAC_CONFIGURATIONS.name());
|
||||
final Document result = storeTracTracConfiguration(tracTracConfiguration);
|
||||
ttConfigCollection.withWriteConcern(WriteConcern.ACKNOWLEDGED).insertOne(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTracTracConfiguration(TracTracConfiguration tracTracConfiguration) {
|
||||
MongoCollection<Document> ttConfigCollection = database
|
||||
.getCollection(CollectionNames.TRACTRAC_CONFIGURATIONS.name());
|
||||
final Document result = storeTracTracConfiguration(tracTracConfiguration);
|
||||
// Object with given name is updated or created if it does not exist yet
|
||||
final Document updateQuery = new Document(FieldNames.TT_CONFIG_JSON_URL.name(),
|
||||
tracTracConfiguration.getJSONURL());
|
||||
updateQuery.put(FieldNames.TT_CONFIG_CREATOR_NAME.name(), tracTracConfiguration.getCreatorName());
|
||||
ttConfigCollection.withWriteConcern(WriteConcern.ACKNOWLEDGED).replaceOne(updateQuery, result,
|
||||
new UpdateOptions().upsert(true));
|
||||
}
|
||||
|
||||
private Document storeTracTracConfiguration(TracTracConfiguration tracTracConfiguration) {
|
||||
final Document result = new Document();
|
||||
result.put(FieldNames.TT_CONFIG_CREATOR_NAME.name(), tracTracConfiguration.getCreatorName());
|
||||
result.put(FieldNames.TT_CONFIG_NAME.name(), tracTracConfiguration.getName());
|
||||
result.put(FieldNames.TT_CONFIG_JSON_URL.name(), tracTracConfiguration.getJSONURL());
|
||||
result.put(FieldNames.TT_CONFIG_LIVE_DATA_URI.name(), tracTracConfiguration.getLiveDataURI());
|
||||
@@ -28,10 +53,15 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
|
||||
result.put(FieldNames.TT_CONFIG_COURSE_DESIGN_UPDATE_URI.name(), tracTracConfiguration.getCourseDesignUpdateURI());
|
||||
result.put(FieldNames.TT_CONFIG_TRACTRAC_USERNAME.name(), tracTracConfiguration.getTracTracUsername());
|
||||
result.put(FieldNames.TT_CONFIG_TRACTRAC_PASSWORD.name(), tracTracConfiguration.getTracTracPassword());
|
||||
// Object with given name is updated or created if it does not exist yet
|
||||
final Document updateQuery = new Document(FieldNames.TT_CONFIG_JSON_URL.name(),
|
||||
tracTracConfiguration.getJSONURL());
|
||||
ttConfigCollection.withWriteConcern(WriteConcern.ACKNOWLEDGED).replaceOne(updateQuery, result,
|
||||
new UpdateOptions().upsert(true));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteTracTracConfiguration(String creatorName, String jsonUrl) {
|
||||
MongoCollection<Document> ttConfigCollection = database.getCollection(CollectionNames.TRACTRAC_CONFIGURATIONS.name());
|
||||
final Document deleteQuery = new Document(FieldNames.TT_CONFIG_JSON_URL.name(),
|
||||
jsonUrl);
|
||||
deleteQuery.put(FieldNames.TT_CONFIG_CREATOR_NAME.name(), creatorName);
|
||||
ttConfigCollection.withWriteConcern(WriteConcern.ACKNOWLEDGED).deleteOne(deleteQuery);
|
||||
}
|
||||
}
|
||||
+6
@@ -3,6 +3,7 @@ package com.sap.sailing.domain.tractracadapter.persistence.impl;
|
||||
import com.mongodb.client.MongoDatabase;
|
||||
import com.sap.sailing.domain.tractracadapter.DomainFactory;
|
||||
import com.sap.sailing.domain.tractracadapter.persistence.DomainObjectFactory;
|
||||
import com.sap.sailing.domain.tractracadapter.persistence.MongoObjectFactory;
|
||||
import com.sap.sailing.domain.tractracadapter.persistence.PersistenceFactory;
|
||||
|
||||
public class PersistenceFactoryImpl implements PersistenceFactory {
|
||||
@@ -10,4 +11,9 @@ public class PersistenceFactoryImpl implements PersistenceFactory {
|
||||
public DomainObjectFactory createDomainObjectFactory(MongoDatabase db, DomainFactory tracTracDomainFactory) {
|
||||
return new DomainObjectFactoryImpl(db, tracTracDomainFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MongoObjectFactory createMongoObjectFactory(MongoDatabase db) {
|
||||
return new MongoObjectFactoryImpl(db);
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -246,7 +246,9 @@ public interface DomainFactory {
|
||||
*/
|
||||
void updateCourseWaypoints(Course courseToUpdate, Iterable<Util.Pair<TracTracControlPoint, PassingInstruction>> controlPoints) throws PatchFailedException;
|
||||
|
||||
TracTracConfiguration createTracTracConfiguration(String name, String jsonURL, String liveDataURI, String storedDataURI, String courseDesignUpdateURI, String tracTracUsername, String tracTracPassword);
|
||||
TracTracConfiguration createTracTracConfiguration(String creatorName, String name, String jsonURL,
|
||||
String liveDataURI, String storedDataURI, String courseDesignUpdateURI, String tracTracUsername,
|
||||
String tracTracPassword);
|
||||
|
||||
/**
|
||||
* Fetch the race definition for <code>race</code>. If the race definition hasn't been created yet, the call blocks
|
||||
|
||||
+2
-3
@@ -74,8 +74,6 @@ public interface TracTracAdapter {
|
||||
* described above will be created and used.
|
||||
* @param offsetToStartTimeOfSimulatedRace
|
||||
* if non-<code>null</code>, the {@link Simulator} will be used with this duration as start offset
|
||||
* @param trackWind TODO
|
||||
* @param correctWindDirectionByMagneticDeclination TODO
|
||||
*/
|
||||
RaceHandle addTracTracRace(TrackerManager trackerManager, RegattaIdentifier regattaToAddTo, URL paramURL,
|
||||
URI liveURI, URI storedURI, URI courseDesignUpdateURI, TimePoint trackingStartTime,
|
||||
@@ -103,7 +101,8 @@ public interface TracTracAdapter {
|
||||
|
||||
RaceRecord getSingleTracTracRaceRecord(URL jsonURL, String raceId, boolean loadClientParams) throws Exception;
|
||||
|
||||
TracTracConfiguration createTracTracConfiguration(String name, String jsonURL, String liveDataURI,
|
||||
TracTracConfiguration createTracTracConfiguration(String creatorName, String name, String jsonURL,
|
||||
String liveDataURI,
|
||||
String storedDataURI, String courseDesignUpdateURI, String tracTracUsername, String tracTracPassword);
|
||||
|
||||
}
|
||||
+7
-3
@@ -39,6 +39,8 @@ public interface TracTracConfiguration extends WithQualifiedObjectIdentifier {
|
||||
*/
|
||||
String getTracTracPassword();
|
||||
|
||||
String getCreatorName();
|
||||
|
||||
@Override
|
||||
default QualifiedObjectIdentifier getIdentifier() {
|
||||
return getType().getQualifiedObjectIdentifier(getTypeRelativeObjectIdentifier());
|
||||
@@ -50,10 +52,12 @@ public interface TracTracConfiguration extends WithQualifiedObjectIdentifier {
|
||||
}
|
||||
|
||||
default TypeRelativeObjectIdentifier getTypeRelativeObjectIdentifier() {
|
||||
return getTypeRelativeObjectIdentifier(getJSONURL());
|
||||
return getTypeRelativeObjectIdentifier(getJSONURL(), getCreatorName());
|
||||
}
|
||||
|
||||
public static TypeRelativeObjectIdentifier getTypeRelativeObjectIdentifier(String jsonUrl) {
|
||||
return new TypeRelativeObjectIdentifier(jsonUrl);
|
||||
public static TypeRelativeObjectIdentifier getTypeRelativeObjectIdentifier(String jsonUrl, String username) {
|
||||
|
||||
return username == null ? new TypeRelativeObjectIdentifier(jsonUrl)
|
||||
: new TypeRelativeObjectIdentifier(jsonUrl, username);
|
||||
}
|
||||
}
|
||||
+5
-2
@@ -998,8 +998,11 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public TracTracConfiguration createTracTracConfiguration(String name, String jsonURL, String liveDataURI, String storedDataURI, String courseDesignUpdateURI, String tracTracUsername, String tracTracPassword) {
|
||||
return new TracTracConfigurationImpl(name, jsonURL, liveDataURI, storedDataURI, courseDesignUpdateURI, tracTracUsername, tracTracPassword);
|
||||
public TracTracConfiguration createTracTracConfiguration(String creatorName, String name, String jsonURL,
|
||||
String liveDataURI, String storedDataURI, String courseDesignUpdateURI, String tracTracUsername,
|
||||
String tracTracPassword) {
|
||||
return new TracTracConfigurationImpl(creatorName, name, jsonURL, liveDataURI, storedDataURI,
|
||||
courseDesignUpdateURI, tracTracUsername, tracTracPassword);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+4
-2
@@ -99,9 +99,11 @@ public class TracTracAdapterImpl implements TracTracAdapter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public TracTracConfiguration createTracTracConfiguration(String name, String jsonURL, String liveDataURI,
|
||||
public TracTracConfiguration createTracTracConfiguration(String creatorName, String name, String jsonURL,
|
||||
String liveDataURI,
|
||||
String storedDataURI, String courseDesignUpdateURI, String tracTracUsername, String tracTracPassword) {
|
||||
return getTracTracDomainFactory().createTracTracConfiguration(name, jsonURL, liveDataURI, storedDataURI,
|
||||
return getTracTracDomainFactory().createTracTracConfiguration(creatorName, name, jsonURL, liveDataURI,
|
||||
storedDataURI,
|
||||
courseDesignUpdateURI, tracTracUsername, tracTracPassword);
|
||||
}
|
||||
|
||||
|
||||
+8
-1
@@ -11,9 +11,12 @@ public class TracTracConfigurationImpl implements TracTracConfiguration {
|
||||
private final String courseDesignUpdateURI;
|
||||
private final String tracTracUsername;
|
||||
private final String tracTracPassword;
|
||||
private final String creatorName;
|
||||
|
||||
public TracTracConfigurationImpl(String name, String jsonURL, String liveDataURI, String storedDataURI, String courseDesignUpdateURI,
|
||||
public TracTracConfigurationImpl(String creatorName, String name, String jsonURL, String liveDataURI,
|
||||
String storedDataURI, String courseDesignUpdateURI,
|
||||
String tracTracUsername, String tracTracPassword) {
|
||||
this.creatorName = creatorName;
|
||||
this.name = name;
|
||||
this.jsonURL = jsonURL;
|
||||
this.liveDataURI = liveDataURI;
|
||||
@@ -67,4 +70,8 @@ public class TracTracConfigurationImpl implements TracTracConfiguration {
|
||||
return tracTracPassword;
|
||||
}
|
||||
|
||||
public String getCreatorName() {
|
||||
return creatorName;
|
||||
}
|
||||
|
||||
}
|
||||
+6
-4
@@ -465,10 +465,12 @@ public final class HomeServiceUtil {
|
||||
URL baseURL = getBaseURL(serverRef.getURL());
|
||||
if (remoteEvents != null) {
|
||||
for (EventBase remoteEvent : remoteEvents) {
|
||||
if (remoteEvent.isPublic() && securityService.hasCurrentUserReadPermission(remoteEvent)) {
|
||||
for(EventVisitor visitor : visitors) {
|
||||
visitor.visit(remoteEvent, true, baseURL);
|
||||
}
|
||||
// Those events have been publicly advertised and have been received by an unauthenticated
|
||||
// anonymous call to the /events end point to the remote server. No security checks or filtering
|
||||
// seems necessary here because we should be seeing only the public remote events anyway.
|
||||
// See also bug 5000.
|
||||
for (EventVisitor visitor : visitors) {
|
||||
visitor.visit(remoteEvent, true, baseURL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
-4
@@ -291,22 +291,28 @@ public class AdminConsoleEntryPoint extends AbstractSailingEntryPoint
|
||||
/* CONNECTORS */
|
||||
final HorizontalTabLayoutPanel connectorsTabPanel = panel.addVerticalTab(getStringMessages().connectors(), "TrackingProviderPanel");
|
||||
TracTracEventManagementPanel tractracEventManagementPanel = new TracTracEventManagementPanel(
|
||||
getSailingService(), getUserService(), this, this, getStringMessages());
|
||||
getSailingService(), getUserService(), this, this, getStringMessages(), tableResources);
|
||||
tractracEventManagementPanel.ensureDebugId("TracTracEventManagement");
|
||||
panel.addToTabPanel(connectorsTabPanel, new DefaultRefreshableAdminConsolePanel<TracTracEventManagementPanel>(tractracEventManagementPanel),
|
||||
panel.addToTabPanel(connectorsTabPanel,
|
||||
new DefaultRefreshableAdminConsolePanel<TracTracEventManagementPanel>(tractracEventManagementPanel) {
|
||||
@Override
|
||||
public void refreshAfterBecomingVisible() {
|
||||
tractracEventManagementPanel.refreshTracTracConnectors();
|
||||
}
|
||||
},
|
||||
getStringMessages().tracTracEvents(),
|
||||
SecuredDomainType.TRACTRAC_ACCOUNT.getPermission(DefaultActions.values()));
|
||||
regattasDisplayers.add(tractracEventManagementPanel);
|
||||
|
||||
SwissTimingReplayConnectorPanel swissTimingReplayConnectorPanel = new SwissTimingReplayConnectorPanel(
|
||||
getSailingService(), getUserService(), this, this, getStringMessages());
|
||||
getSailingService(), getUserService(), this, this, getStringMessages(), tableResources);
|
||||
panel.addToTabPanel(connectorsTabPanel, new DefaultRefreshableAdminConsolePanel<SwissTimingReplayConnectorPanel>(swissTimingReplayConnectorPanel),
|
||||
getStringMessages().swissTimingArchiveConnector(),
|
||||
SecuredDomainType.SWISS_TIMING_ARCHIVE_ACCOUNT.getPermission(DefaultActions.values()));
|
||||
regattasDisplayers.add(swissTimingReplayConnectorPanel);
|
||||
|
||||
SwissTimingEventManagementPanel swisstimingEventManagementPanel = new SwissTimingEventManagementPanel(
|
||||
getSailingService(), getUserService(), this, this, getStringMessages());
|
||||
getSailingService(), getUserService(), this, this, getStringMessages(), tableResources);
|
||||
panel.addToTabPanel(connectorsTabPanel, new DefaultRefreshableAdminConsolePanel<SwissTimingEventManagementPanel>(swisstimingEventManagementPanel),
|
||||
getStringMessages().swissTimingEvents(),
|
||||
SecuredDomainType.SWISS_TIMING_ACCOUNT.getPermission(DefaultActions.values()));
|
||||
|
||||
+22
-25
@@ -57,6 +57,7 @@ import com.sap.sse.security.shared.HasPermissions;
|
||||
import com.sap.sse.security.shared.HasPermissions.DefaultActions;
|
||||
import com.sap.sse.security.ui.client.UserService;
|
||||
import com.sap.sse.security.ui.client.component.AccessControlledActionsColumn;
|
||||
import com.sap.sse.security.ui.client.component.AccessControlledButtonPanel;
|
||||
import com.sap.sse.security.ui.client.component.DefaultActionsImagesBarCell;
|
||||
import com.sap.sse.security.ui.client.component.EditOwnershipDialog;
|
||||
import com.sap.sse.security.ui.client.component.EditOwnershipDialog.DialogConfig;
|
||||
@@ -122,39 +123,34 @@ public class IgtimiAccountsPanel extends FlowPanel {
|
||||
final RefreshableMultiSelectionModel<AccountWithSecurityDTO> refreshableAccountsSelectionModel = (RefreshableMultiSelectionModel<AccountWithSecurityDTO>) cellTable
|
||||
.getSelectionModel();
|
||||
|
||||
// setup controls
|
||||
final Panel controlsPanel = new HorizontalPanel();
|
||||
final Button removeAccountButton = new Button(stringMessages.remove());
|
||||
removeAccountButton.setEnabled(false);
|
||||
removeAccountButton.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
if (refreshableAccountsSelectionModel.getSelectedSet().size() > 0) {
|
||||
if (Window.confirm(stringMessages.doYouReallyWantToRemoveTheSelectedIgtimiAccounts())) {
|
||||
for (AccountWithSecurityDTO account : refreshableAccountsSelectionModel.getSelectedSet()) {
|
||||
removeAccount(account, filteredAccounts);
|
||||
}
|
||||
controlsPanel.add(filterAccountsPanel);
|
||||
|
||||
final AccessControlledButtonPanel buttonPanel = new AccessControlledButtonPanel(userService,
|
||||
SecuredDomainType.IGTIMI_ACCOUNT);
|
||||
controlsPanel.add(buttonPanel);
|
||||
buttonPanel.addUnsecuredAction(stringMessages.refresh(), () -> refresh());
|
||||
|
||||
// setup controls
|
||||
final Button removeAccountButton = buttonPanel.addRemoveAction(stringMessages.remove(), () -> {
|
||||
if (refreshableAccountsSelectionModel.getSelectedSet().size() > 0) {
|
||||
if (Window.confirm(stringMessages.doYouReallyWantToRemoveTheSelectedIgtimiAccounts())) {
|
||||
for (AccountWithSecurityDTO account : refreshableAccountsSelectionModel.getSelectedSet()) {
|
||||
removeAccount(account, filteredAccounts);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
removeAccountButton.setEnabled(false);
|
||||
refreshableAccountsSelectionModel.addSelectionChangeHandler(
|
||||
e -> removeAccountButton.setEnabled(refreshableAccountsSelectionModel.getSelectedSet().size() > 0));
|
||||
controlsPanel.add(filterAccountsPanel);
|
||||
controlsPanel.add(removeAccountButton);
|
||||
add(controlsPanel);
|
||||
add(cellTable);
|
||||
|
||||
// add button
|
||||
final Button addAccountButton = new Button(stringMessages.addIgtimiAccount());
|
||||
final Button addAccountButton = buttonPanel.addCreateAction(stringMessages.addIgtimiAccount(),
|
||||
() -> addAccount());
|
||||
addAccountButton.ensureDebugId("addIgtimiAccount");
|
||||
addAccountButton.addClickHandler(e -> addAccount());
|
||||
add(addAccountButton);
|
||||
|
||||
// refresh button
|
||||
final Button refreshButton = new Button(stringMessages.refresh());
|
||||
refreshButton.addClickHandler(e -> refresh());
|
||||
add(refreshButton);
|
||||
|
||||
final String protocol = Window.Location.getProtocol().endsWith(":")
|
||||
? Window.Location.getProtocol().substring(0, Window.Location.getProtocol().length() - 1)
|
||||
@@ -171,8 +167,7 @@ public class IgtimiAccountsPanel extends FlowPanel {
|
||||
|
||||
@Override
|
||||
public void onSuccess(String result) {
|
||||
final Button addIgtimiUserButton = new Button(stringMessages.addIgtimiUser() + " (OAuth)");
|
||||
addIgtimiUserButton.addClickHandler(clickEvent -> {
|
||||
buttonPanel.addCreateAction(stringMessages.addIgtimiUser() + " (OAuth)", () -> {
|
||||
Frame frame = new Frame(UriUtils.fromString(result).asString());
|
||||
frame.addLoadHandler(loadEvent -> refresh());
|
||||
frame.setPixelSize(520, 770);
|
||||
@@ -195,8 +190,7 @@ public class IgtimiAccountsPanel extends FlowPanel {
|
||||
refresh();
|
||||
});
|
||||
dialogBox.center();
|
||||
});
|
||||
controlsPanel.add(addIgtimiUserButton);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -228,6 +222,8 @@ public class IgtimiAccountsPanel extends FlowPanel {
|
||||
account -> account.getName(), columnSortHandler);
|
||||
final TextColumn<AccountWithSecurityDTO> accountEmailColumn = new AbstractSortableTextColumn<AccountWithSecurityDTO>(
|
||||
account -> account.getEmail(), columnSortHandler);
|
||||
final TextColumn<AccountWithSecurityDTO> creatorNameColumn = new AbstractSortableTextColumn<AccountWithSecurityDTO>(
|
||||
account -> account.getCreatorName(), columnSortHandler);
|
||||
|
||||
final HasPermissions type = SecuredDomainType.IGTIMI_ACCOUNT;
|
||||
final AccessControlledActionsColumn<AccountWithSecurityDTO, DefaultActionsImagesBarCell> roleActionColumn = create(
|
||||
@@ -248,6 +244,7 @@ public class IgtimiAccountsPanel extends FlowPanel {
|
||||
table.addColumn(accountSelectionCheckboxColumn, accountSelectionCheckboxColumn.getHeader());
|
||||
table.addColumn(accountNameColumn, stringMessages.name());
|
||||
table.addColumn(accountEmailColumn, stringMessages.email());
|
||||
table.addColumn(creatorNameColumn, stringMessages.creatorName());
|
||||
SecuredDTOOwnerColumn.configureOwnerColumns(table, columnSortHandler, stringMessages);
|
||||
table.addColumn(roleActionColumn, stringMessages.actions());
|
||||
table.setSelectionModel(accountSelectionCheckboxColumn.getSelectionModel(),
|
||||
|
||||
+113
-237
@@ -1,16 +1,10 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.dom.client.Style.Unit;
|
||||
import com.google.gwt.event.dom.client.ChangeEvent;
|
||||
import com.google.gwt.event.dom.client.ChangeHandler;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.user.cellview.client.AbstractCellTable;
|
||||
@@ -22,33 +16,35 @@ import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
import com.google.gwt.user.client.ui.CaptionPanel;
|
||||
import com.google.gwt.user.client.ui.CheckBox;
|
||||
import com.google.gwt.user.client.ui.Grid;
|
||||
import com.google.gwt.user.client.ui.HasVerticalAlignment;
|
||||
import com.google.gwt.user.client.ui.HorizontalPanel;
|
||||
import com.google.gwt.user.client.ui.IntegerBox;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.ListBox;
|
||||
import com.google.gwt.user.client.ui.PasswordTextBox;
|
||||
import com.google.gwt.user.client.ui.TextBox;
|
||||
import com.google.gwt.user.client.ui.VerticalPanel;
|
||||
import com.google.gwt.view.client.ListDataProvider;
|
||||
import com.sap.sailing.domain.common.RegattaIdentifier;
|
||||
import com.sap.sailing.domain.common.RegattaName;
|
||||
import com.sap.sailing.domain.common.security.SecuredDomainType;
|
||||
import com.sap.sailing.gwt.ui.adminconsole.swisstiming.EditSwissTimingConnectionDialog;
|
||||
import com.sap.sailing.gwt.ui.adminconsole.swisstiming.SwissTimingConnectionTableWrapper;
|
||||
import com.sap.sailing.gwt.ui.client.RegattaRefresher;
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SwissTimingConfigurationDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SwissTimingConfigurationWithSecurityDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SwissTimingEventRecordDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SwissTimingRaceRecordDTO;
|
||||
import com.sap.sse.common.util.NaturalComparator;
|
||||
import com.sap.sse.gwt.adminconsole.AdminConsoleTableResources;
|
||||
import com.sap.sse.gwt.client.ErrorReporter;
|
||||
import com.sap.sse.gwt.client.async.MarkedAsyncCallback;
|
||||
import com.sap.sse.gwt.client.celltable.CellTableWithCheckboxResources;
|
||||
import com.sap.sse.gwt.client.celltable.EntityIdentityComparator;
|
||||
import com.sap.sse.gwt.client.celltable.FlushableCellTable;
|
||||
import com.sap.sse.gwt.client.celltable.SelectionCheckboxColumn;
|
||||
import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback;
|
||||
import com.sap.sse.gwt.client.panels.LabeledAbstractFilterablePanel;
|
||||
import com.sap.sse.security.ui.client.UserService;
|
||||
import com.sap.sse.security.ui.client.component.AccessControlledButtonPanel;
|
||||
|
||||
/**
|
||||
* Allows the user to start and stop tracking of races using the SwissTiming connector. In particular,
|
||||
@@ -64,24 +60,12 @@ public class SwissTimingEventManagementPanel extends AbstractEventManagementPane
|
||||
private final LabeledAbstractFilterablePanel<SwissTimingRaceRecordDTO> filterablePanelEvents;
|
||||
private final ListDataProvider<SwissTimingRaceRecordDTO> raceList;
|
||||
private final FlushableCellTable<SwissTimingRaceRecordDTO> raceTable;
|
||||
private final Map<String, SwissTimingConfigurationDTO> previousConfigurations;
|
||||
private final ListBox previousConfigurationsComboBox;
|
||||
private final TextBox eventIdBox;
|
||||
private final TextBox jsonUrlBox;
|
||||
private final TextBox updateURLBox;
|
||||
private final TextBox updateUsernameBox;
|
||||
private final PasswordTextBox updatePasswordBox;
|
||||
private final TextBox hostnameTextbox;
|
||||
private final IntegerBox portIntegerbox;
|
||||
private final List<SwissTimingRaceRecordDTO> availableSwissTimingRaces = new ArrayList<SwissTimingRaceRecordDTO>();
|
||||
private final String manage2sailBaseAPIUrl = "http://manage2sail.com/api/public/links/event/";
|
||||
private final String manage2sailAPIaccessToken = "?accesstoken=bDAv8CwsTM94ujZ";
|
||||
private final String manage2sailUrlAppendix = "&mediaType=json&includeRaces=true";
|
||||
private final String eventIdPattern = "[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}";
|
||||
private final SwissTimingConnectionTableWrapper connectionsTable;
|
||||
|
||||
public SwissTimingEventManagementPanel(final SailingServiceAsync sailingService, UserService userService,
|
||||
ErrorReporter errorReporter,
|
||||
RegattaRefresher regattaRefresher, StringMessages stringConstants) {
|
||||
RegattaRefresher regattaRefresher, StringMessages stringConstants, final CellTableWithCheckboxResources tableResources) {
|
||||
super(sailingService, userService, regattaRefresher, errorReporter, true, stringConstants);
|
||||
this.errorReporter = errorReporter;
|
||||
VerticalPanel mainPanel = new VerticalPanel();
|
||||
@@ -92,101 +76,92 @@ public class SwissTimingEventManagementPanel extends AbstractEventManagementPane
|
||||
VerticalPanel verticalPanel = new VerticalPanel();
|
||||
captionPanelConnections.setContentWidget(verticalPanel);
|
||||
captionPanelConnections.setStyleName("bold");
|
||||
Grid connectionsGrid = new Grid(9, 2);
|
||||
verticalPanel.add(connectionsGrid);
|
||||
previousConfigurations = new HashMap<String, SwissTimingConfigurationDTO>();
|
||||
previousConfigurationsComboBox = new ListBox();
|
||||
connectionsGrid.setWidget(0, 1, previousConfigurationsComboBox);
|
||||
previousConfigurationsComboBox.addChangeHandler(new ChangeHandler() {
|
||||
@Override
|
||||
public void onChange(ChangeEvent event) {
|
||||
updatePanelFromSelectedStoredConfiguration();
|
||||
}
|
||||
});
|
||||
previousConfigurationsComboBox.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
updatePanelFromSelectedStoredConfiguration();
|
||||
}
|
||||
});
|
||||
fillConfigurations();
|
||||
connectionsGrid.setWidget(0, 0, new Label(stringMessages.swissTimingEvents() + ":"));
|
||||
connectionsGrid.setWidget(0, 1, previousConfigurationsComboBox);
|
||||
|
||||
eventIdBox = new TextBox();
|
||||
eventIdBox.getElement().getStyle().setWidth(30, Unit.EM);
|
||||
eventIdBox.setTitle(stringMessages.manage2SailEventIdBoxTooltip());
|
||||
connectionsGrid.setWidget(1, 0, new Label(stringMessages.manage2SailEventIdBox() + ":"));
|
||||
connectionsGrid.setWidget(1, 1, eventIdBox);
|
||||
eventIdBox.addChangeHandler(event -> {
|
||||
if (eventIdBox.getValue() != "") {
|
||||
updateUrlFromEventId(eventIdBox.getValue());
|
||||
}
|
||||
|
||||
connectionsTable = new SwissTimingConnectionTableWrapper(userService, sailingService, stringConstants,
|
||||
errorReporter, true, tableResources, () -> {
|
||||
});
|
||||
verticalPanel.add(connectionsTable);
|
||||
connectionsTable.refreshSwissTimingConnectionList();
|
||||
|
||||
// Add button panel
|
||||
final AccessControlledButtonPanel buttonPanel = new AccessControlledButtonPanel(userService,
|
||||
SecuredDomainType.TRACKED_RACE);
|
||||
verticalPanel.add(buttonPanel);
|
||||
buttonPanel.addUnsecuredAction(stringMessages.refresh(),
|
||||
() -> connectionsTable.refreshSwissTimingConnectionList());
|
||||
// Add SwissTiming Connection
|
||||
buttonPanel.addCreateAction(stringMessages.addSwissTimingConnection(),
|
||||
() -> new EditSwissTimingConnectionDialog(new SwissTimingConfigurationWithSecurityDTO(),
|
||||
new DialogCallback<SwissTimingConfigurationWithSecurityDTO>() {
|
||||
@Override
|
||||
public void ok(SwissTimingConfigurationWithSecurityDTO editedConnection) {
|
||||
sailingService.createSwissTimingConfiguration(editedConnection.getName(),
|
||||
editedConnection.getJsonUrl(), editedConnection.getHostname(),
|
||||
editedConnection.getPort(), editedConnection.getUpdateURL(),
|
||||
editedConnection.getUpdateUsername(), editedConnection.getUpdatePassword(),
|
||||
new MarkedAsyncCallback<Void>(new AsyncCallback<Void>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter
|
||||
.reportError("Exception trying to create configuration in DB: "
|
||||
+ caught.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(Void voidResult) {
|
||||
connectionsTable.refreshSwissTimingConnectionList();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
}
|
||||
}, userService, errorReporter).show());
|
||||
|
||||
// Remove SwissTiming Connection
|
||||
final Button removeButton = buttonPanel.addRemoveAction(stringMessages.remove(), () -> {
|
||||
sailingService.deleteSwissTimingConfiguration(connectionsTable.getSelectionModel().getSelectedObject(),
|
||||
new AsyncCallback<Void>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError(
|
||||
"Exception trying to delete configuration in DB: " + caught.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(Void result) {
|
||||
connectionsTable.refreshSwissTimingConnectionList();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
jsonUrlBox = new TextBox();
|
||||
jsonUrlBox.getElement().getStyle().setWidth(50, Unit.EM);
|
||||
connectionsGrid.setWidget(2, 0, new Label(stringMessages.manage2SailEventURLBox() + ":"));
|
||||
connectionsGrid.setWidget(2, 1, jsonUrlBox);
|
||||
jsonUrlBox.addChangeHandler(event -> {
|
||||
if (jsonUrlBox.getValue() != "") {
|
||||
updateEventIdFromUrl(jsonUrlBox.getValue());
|
||||
}
|
||||
// List Races in SwissTiming Connection
|
||||
final Button listRacesButton = buttonPanel.addUnsecuredAction(stringMessages.listRaces(), () -> {
|
||||
fillRaces(sailingService);
|
||||
});
|
||||
|
||||
hostnameTextbox = new TextBox();
|
||||
portIntegerbox = new IntegerBox();
|
||||
|
||||
connectionsGrid.setWidget(3, 0, new Label(stringConstants.hostname() + ":"));
|
||||
connectionsGrid.setWidget(3, 1, hostnameTextbox);
|
||||
|
||||
connectionsGrid.setWidget(4, 0, new Label(stringMessages.manage2SailPort() + ":"));
|
||||
connectionsGrid.setWidget(4, 1, portIntegerbox);
|
||||
|
||||
updateURLBox = new TextBox();
|
||||
updateURLBox.getElement().getStyle().setWidth(50, Unit.EM);
|
||||
connectionsGrid.setWidget(5, 0, new Label(stringMessages.swissTimingUpdateURL() + ":"));
|
||||
connectionsGrid.setWidget(5, 1, updateURLBox);
|
||||
|
||||
updateUsernameBox = new TextBox();
|
||||
updateUsernameBox.getElement().getStyle().setWidth(50, Unit.EM);
|
||||
connectionsGrid.setWidget(6, 0, new Label(stringMessages.swissTimingUpdateUsername() + ":"));
|
||||
connectionsGrid.setWidget(6, 1, updateUsernameBox);
|
||||
|
||||
updatePasswordBox = new PasswordTextBox();
|
||||
updatePasswordBox.getElement().getStyle().setWidth(50, Unit.EM);
|
||||
connectionsGrid.setWidget(7, 0, new Label(stringMessages.swissTimingUpdatePassword() + ":"));
|
||||
connectionsGrid.setWidget(7, 1, updatePasswordBox);
|
||||
|
||||
Button btnListRaces = new Button(stringConstants.listRaces());
|
||||
connectionsGrid.setWidget(8, 1, btnListRaces);
|
||||
btnListRaces.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
fillRaces(sailingService);
|
||||
}
|
||||
listRacesButton.setEnabled(false);
|
||||
removeButton.setEnabled(false);
|
||||
connectionsTable.getSelectionModel().addSelectionChangeHandler(e -> {
|
||||
final boolean objectSelected = connectionsTable.getSelectionModel().getSelectedObject() != null;
|
||||
listRacesButton.setEnabled(objectSelected);
|
||||
removeButton.setEnabled(objectSelected);
|
||||
});
|
||||
|
||||
HorizontalPanel racesSplitPanel = new HorizontalPanel();
|
||||
mainPanel.add(racesSplitPanel);
|
||||
|
||||
CaptionPanel trackableRacesCaptionPanel = new CaptionPanel(stringConstants.trackableRaces());
|
||||
racesSplitPanel.add(trackableRacesCaptionPanel);
|
||||
trackableRacesCaptionPanel.setWidth("50%");
|
||||
|
||||
CaptionPanel trackedRacesCaptionPanel = new CaptionPanel(stringConstants.trackedRaces());
|
||||
racesSplitPanel.add(trackedRacesCaptionPanel);
|
||||
trackedRacesCaptionPanel.setWidth("50%");
|
||||
|
||||
VerticalPanel trackableRacesPanel = new VerticalPanel();
|
||||
trackableRacesCaptionPanel.setContentWidget(trackableRacesPanel);
|
||||
trackableRacesCaptionPanel.setStyleName("bold");
|
||||
|
||||
VerticalPanel trackedRacesPanel = new VerticalPanel();
|
||||
trackedRacesPanel.setWidth("100%");
|
||||
trackedRacesCaptionPanel.setContentWidget(trackedRacesPanel);
|
||||
trackedRacesCaptionPanel.setStyleName("bold");
|
||||
|
||||
// Regatta selection
|
||||
HorizontalPanel regattaPanel = new HorizontalPanel();
|
||||
regattaPanel.setSpacing(5);
|
||||
@@ -195,39 +170,31 @@ public class SwissTimingEventManagementPanel extends AbstractEventManagementPane
|
||||
regattaPanel.add(regattaForTrackingLabel);
|
||||
regattaPanel.add(getAvailableRegattasListBox());
|
||||
trackableRacesPanel.add(regattaPanel);
|
||||
|
||||
Label lblTrackSettings = new Label(stringConstants.trackSettings());
|
||||
trackableRacesPanel.add(lblTrackSettings);
|
||||
|
||||
final CheckBox trackWindCheckbox = new CheckBox(stringConstants.trackWind());
|
||||
trackWindCheckbox.setWordWrap(false);
|
||||
trackWindCheckbox.setValue(true);
|
||||
trackableRacesPanel.add(trackWindCheckbox);
|
||||
|
||||
final CheckBox declinationCheckbox = new CheckBox(stringConstants.declinationCheckbox());
|
||||
declinationCheckbox.setWordWrap(false);
|
||||
declinationCheckbox.setValue(true);
|
||||
trackableRacesPanel.add(declinationCheckbox);
|
||||
|
||||
final CheckBox simulateWithStartTimeNow = new CheckBox(stringMessages.simulateAsLiveRace());
|
||||
simulateWithStartTimeNow.setWordWrap(false);
|
||||
simulateWithStartTimeNow.setValue(false);
|
||||
trackableRacesPanel.add(simulateWithStartTimeNow);
|
||||
|
||||
final CheckBox useInternalMarkPassingAlgorithmCheckbox = new CheckBox(stringMessages.useInternalAlgorithm());
|
||||
useInternalMarkPassingAlgorithmCheckbox.setWordWrap(false);
|
||||
useInternalMarkPassingAlgorithmCheckbox.setValue(Boolean.FALSE);
|
||||
trackableRacesPanel.add(useInternalMarkPassingAlgorithmCheckbox);
|
||||
|
||||
// text box for filtering the cell table
|
||||
HorizontalPanel filterPanel = new HorizontalPanel();
|
||||
filterPanel.setSpacing(5);
|
||||
trackableRacesPanel.add(filterPanel);
|
||||
|
||||
Label lblFilterEvents = new Label(stringConstants.filterRaces() + ":");
|
||||
filterPanel.add(lblFilterEvents);
|
||||
filterPanel.setCellVerticalAlignment(lblFilterEvents, HasVerticalAlignment.ALIGN_MIDDLE);
|
||||
|
||||
raceTable = new FlushableCellTable<SwissTimingRaceRecordDTO>(/* pageSize */10000, tableRes);
|
||||
raceTable.setWidth("300px");
|
||||
raceList = new ListDataProvider<SwissTimingRaceRecordDTO>();
|
||||
@@ -253,7 +220,6 @@ public class SwissTimingEventManagementPanel extends AbstractEventManagementPane
|
||||
return raceTable;
|
||||
}
|
||||
};
|
||||
|
||||
final EntityIdentityComparator<SwissTimingRaceRecordDTO> entityIdentityComparator = new EntityIdentityComparator<SwissTimingRaceRecordDTO>() {
|
||||
@Override
|
||||
public boolean representSameEntity(SwissTimingRaceRecordDTO dto1, SwissTimingRaceRecordDTO dto2) {
|
||||
@@ -264,21 +230,18 @@ public class SwissTimingEventManagementPanel extends AbstractEventManagementPane
|
||||
return t.raceId.hashCode();
|
||||
}
|
||||
};
|
||||
|
||||
TextColumn<SwissTimingRaceRecordDTO> raceNameColumn = new TextColumn<SwissTimingRaceRecordDTO>() {
|
||||
@Override
|
||||
public String getValue(SwissTimingRaceRecordDTO object) {
|
||||
return object.getName();
|
||||
}
|
||||
};
|
||||
|
||||
TextColumn<SwissTimingRaceRecordDTO> regattaNameColumn = new TextColumn<SwissTimingRaceRecordDTO>() {
|
||||
@Override
|
||||
public String getValue(SwissTimingRaceRecordDTO object) {
|
||||
return object.regattaName;
|
||||
}
|
||||
};
|
||||
|
||||
SelectionCheckboxColumn<SwissTimingRaceRecordDTO> selectionColumn = new SelectionCheckboxColumn<SwissTimingRaceRecordDTO>(
|
||||
tableRes.cellTableStyle().cellTableCheckboxSelected(),
|
||||
tableRes.cellTableStyle().cellTableCheckboxDeselected(),
|
||||
@@ -290,42 +253,36 @@ public class SwissTimingEventManagementPanel extends AbstractEventManagementPane
|
||||
return object.seriesName;
|
||||
}
|
||||
};
|
||||
|
||||
TextColumn<SwissTimingRaceRecordDTO> raceIdColumn = new TextColumn<SwissTimingRaceRecordDTO>() {
|
||||
@Override
|
||||
public String getValue(SwissTimingRaceRecordDTO object) {
|
||||
return object.raceId;
|
||||
}
|
||||
};
|
||||
|
||||
TextColumn<SwissTimingRaceRecordDTO> boatClassColumn = new TextColumn<SwissTimingRaceRecordDTO>() {
|
||||
@Override
|
||||
public String getValue(SwissTimingRaceRecordDTO object) {
|
||||
return object.boatClass != null ? object.boatClass : "";
|
||||
}
|
||||
};
|
||||
|
||||
TextColumn<SwissTimingRaceRecordDTO> genderColumn = new TextColumn<SwissTimingRaceRecordDTO>() {
|
||||
@Override
|
||||
public String getValue(SwissTimingRaceRecordDTO object) {
|
||||
return object.gender != null ? object.gender : "";
|
||||
}
|
||||
};
|
||||
|
||||
TextColumn<SwissTimingRaceRecordDTO> raceStatusColumn = new TextColumn<SwissTimingRaceRecordDTO>() {
|
||||
@Override
|
||||
public String getValue(SwissTimingRaceRecordDTO object) {
|
||||
return object.raceStatus != null ? object.raceStatus : "";
|
||||
}
|
||||
};
|
||||
|
||||
TextColumn<SwissTimingRaceRecordDTO> raceStartTimeColumn = new TextColumn<SwissTimingRaceRecordDTO>() {
|
||||
@Override
|
||||
public String getValue(SwissTimingRaceRecordDTO object) {
|
||||
return object.raceStartTime==null?"":dateFormatter.render(object.raceStartTime) + " " + timeFormatter.render(object.raceStartTime);
|
||||
}
|
||||
};
|
||||
|
||||
raceNameColumn.setSortable(true);
|
||||
raceStartTimeColumn.setSortable(true);
|
||||
boatClassColumn.setSortable(true);
|
||||
@@ -334,8 +291,6 @@ public class SwissTimingEventManagementPanel extends AbstractEventManagementPane
|
||||
raceStatusColumn.setSortable(true);
|
||||
regattaNameColumn.setSortable(true);
|
||||
seriesNameColumn.setSortable(true);
|
||||
|
||||
|
||||
raceTable.addColumn(selectionColumn, selectionColumn.getHeader());
|
||||
raceTable.addColumn(regattaNameColumn, stringConstants.regatta());
|
||||
raceTable.addColumn(seriesNameColumn, stringConstants.series());
|
||||
@@ -345,20 +300,16 @@ public class SwissTimingEventManagementPanel extends AbstractEventManagementPane
|
||||
raceTable.addColumn(boatClassColumn, stringConstants.boatClass());
|
||||
raceTable.addColumn(genderColumn, stringConstants.gender());
|
||||
raceTable.addColumn(raceStartTimeColumn, stringConstants.startTime());
|
||||
|
||||
raceTable.setSelectionModel(selectionColumn.getSelectionModel(), selectionColumn.getSelectionManager());
|
||||
|
||||
trackableRacesPanel.add(raceTable);
|
||||
raceList.addDataDisplay(raceTable);
|
||||
Handler columnSortHandler = getRaceTableColumnSortHandler(raceList.getList(), regattaNameColumn, seriesNameColumn,
|
||||
raceNameColumn, raceStartTimeColumn, raceIdColumn, boatClassColumn, genderColumn, raceStatusColumn);
|
||||
raceTable.addColumnSortHandler(columnSortHandler);
|
||||
|
||||
trackedRacesPanel.add(trackedRacesListComposite);
|
||||
filterPanel.add(filterablePanelEvents);
|
||||
HorizontalPanel racesButtonPanel = new HorizontalPanel();
|
||||
trackableRacesPanel.add(racesButtonPanel);
|
||||
|
||||
Button btnTrack = new Button(stringConstants.startTracking());
|
||||
racesButtonPanel.add(btnTrack);
|
||||
racesButtonPanel.setSpacing(10);
|
||||
@@ -371,30 +322,7 @@ public class SwissTimingEventManagementPanel extends AbstractEventManagementPane
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This function tries to infer a valid JsonUrl for any input given that matches the pattern of an event Id from
|
||||
* M2S. If there is an event id detected the Json Url gets updated and the event Id textbox is filled with the
|
||||
* detected event Id. The ID pattern is defined in {@link eventIdPattern}.
|
||||
*/
|
||||
private void updateUrlFromEventId(String eventIdTextbox) {
|
||||
if (eventIdTextbox.matches(".*" + eventIdPattern + ".*")) {
|
||||
final String inferredEventId = eventIdTextbox.replaceFirst(".*(" + eventIdPattern + ").*", "$1");
|
||||
jsonUrlBox.setValue(
|
||||
manage2sailBaseAPIUrl + inferredEventId + manage2sailAPIaccessToken + manage2sailUrlAppendix);
|
||||
eventIdBox.setValue(inferredEventId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to {@link #updateUrlFromEventId} this function tries to extract a M2S event Id by looking at the given
|
||||
* url in the Json Url Textbox. The value of {@link eventIdBox} is then set to the event ID inferred from the Json Url.
|
||||
*/
|
||||
private void updateEventIdFromUrl(String jsonUrlTextBox) {
|
||||
if (jsonUrlTextBox.matches("http://manage2sail.com/.*" + eventIdPattern + ".*")) {
|
||||
final String inferredEventId = jsonUrlTextBox.replaceFirst(".*(" + eventIdPattern + ").*", "$1");
|
||||
eventIdBox.setValue(inferredEventId);
|
||||
}
|
||||
}
|
||||
|
||||
private ListHandler<SwissTimingRaceRecordDTO> getRaceTableColumnSortHandler(List<SwissTimingRaceRecordDTO> raceRecords,
|
||||
Column<SwissTimingRaceRecordDTO, ?> regattaNameColumn, Column<SwissTimingRaceRecordDTO, ?> seriesNameColumn,
|
||||
@@ -456,92 +384,56 @@ public class SwissTimingEventManagementPanel extends AbstractEventManagementPane
|
||||
return result;
|
||||
}
|
||||
|
||||
private void fillConfigurations() {
|
||||
sailingService.getPreviousSwissTimingConfigurations(new AsyncCallback<List<SwissTimingConfigurationDTO>>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError("Remote Procedure Call getPreviousConfigurations() - Failure: "
|
||||
+ caught.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(List<SwissTimingConfigurationDTO> result) {
|
||||
while (previousConfigurationsComboBox.getItemCount() > 0) {
|
||||
previousConfigurationsComboBox.removeItem(0);
|
||||
}
|
||||
Collections.sort(result, (c1, c2) -> c1.getName().compareTo(c2.getName()));
|
||||
for (SwissTimingConfigurationDTO stConfig : result) {
|
||||
previousConfigurations.put(stConfig.getName(), stConfig);
|
||||
previousConfigurationsComboBox.addItem(stConfig.getName());
|
||||
}
|
||||
if (!result.isEmpty()) {
|
||||
updatePanelFromSelectedStoredConfiguration();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void fillRaces(final SailingServiceAsync sailingService) {
|
||||
final String jsonUrl = jsonUrlBox.getValue();
|
||||
final String updateURL = updateURLBox.getValue();
|
||||
final String updateUsername = updateUsernameBox.getValue();
|
||||
final String updatePassword = updatePasswordBox.getValue();
|
||||
sailingService.getRacesOfSwissTimingEvent(jsonUrl, new AsyncCallback<SwissTimingEventRecordDTO>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
SwissTimingEventManagementPanel.this.errorReporter.reportError("Error trying to list races: "
|
||||
+ caught.getMessage());
|
||||
}
|
||||
final SwissTimingConfigurationWithSecurityDTO selectedObject = connectionsTable.getSelectionModel()
|
||||
.getSelectedObject();
|
||||
sailingService.getRacesOfSwissTimingEvent(selectedObject.getJsonUrl(),
|
||||
new AsyncCallback<SwissTimingEventRecordDTO>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
SwissTimingEventManagementPanel.this.errorReporter
|
||||
.reportError("Error trying to list races: " + caught.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(final SwissTimingEventRecordDTO result) {
|
||||
availableSwissTimingRaces.clear();
|
||||
if (result != null) {
|
||||
availableSwissTimingRaces.addAll(result.races);
|
||||
}
|
||||
raceList.getList().clear();
|
||||
raceList.getList().addAll(availableSwissTimingRaces);
|
||||
filterablePanelEvents.getTextBox().setText(null);
|
||||
filterablePanelEvents.updateAll(result.races);
|
||||
// store a successful configuration in the database for later retrieval
|
||||
final String hostname = result.trackingDataHost;
|
||||
final Integer port = result.trackingDataPort;
|
||||
final String configName = result.eventName;
|
||||
sailingService.storeSwissTimingConfiguration(configName, jsonUrl, hostname, port, updateURL, updateUsername, updatePassword,
|
||||
new AsyncCallback<Void>() {
|
||||
@Override
|
||||
public void onSuccess(final SwissTimingEventRecordDTO result) {
|
||||
availableSwissTimingRaces.clear();
|
||||
if (result != null) {
|
||||
availableSwissTimingRaces.addAll(result.races);
|
||||
}
|
||||
raceList.getList().clear();
|
||||
raceList.getList().addAll(availableSwissTimingRaces);
|
||||
filterablePanelEvents.getTextBox().setText(null);
|
||||
filterablePanelEvents.updateAll(result.races);
|
||||
// store a successful configuration in the database for later retrieval
|
||||
final SwissTimingConfigurationWithSecurityDTO updatedDTO = new SwissTimingConfigurationWithSecurityDTO(
|
||||
selectedObject, result.trackingDataHost, result.trackingDataPort, result.eventName);
|
||||
|
||||
sailingService.updateSwissTimingConfiguration(updatedDTO, new AsyncCallback<Void>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError("Exception trying to store configuration in DB: "
|
||||
+ caught.getMessage());
|
||||
errorReporter.reportError(
|
||||
"Exception trying to update configuration in DB: " + caught.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(Void voidResult) {
|
||||
// refresh list of previous configurations
|
||||
SwissTimingConfigurationDTO stConfig = new SwissTimingConfigurationDTO(configName, jsonUrl,
|
||||
hostname, port, updateURL, updateUsername, updatePassword);
|
||||
if (previousConfigurations.put(stConfig.getName(), stConfig) == null) {
|
||||
previousConfigurationsComboBox.addItem(stConfig.getName());
|
||||
}
|
||||
for (int i=0; i<previousConfigurationsComboBox.getItemCount(); i++) {
|
||||
if (previousConfigurationsComboBox.getValue(i).equals(stConfig.getName())) {
|
||||
previousConfigurationsComboBox.setSelectedIndex(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
updatePanelFromSelectedStoredConfiguration();
|
||||
connectionsTable.refreshSwissTimingConnectionList();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void trackSelectedRaces(boolean trackWind, boolean correctWindByDeclination, boolean useInternalMarkPassingAlgorithm) {
|
||||
final String hostname = hostnameTextbox.getValue();
|
||||
final Integer port = portIntegerbox.getValue();
|
||||
final String updateURL = updateURLBox.getValue();
|
||||
final String updateUsername = updateUsernameBox.getValue();
|
||||
final String updatePassword = updatePasswordBox.getValue();
|
||||
final SwissTimingConfigurationWithSecurityDTO selectedObject = connectionsTable.getSelectionModel()
|
||||
.getSelectedObject();
|
||||
final String hostname = selectedObject.getHostname();
|
||||
final Integer port = selectedObject.getPort();
|
||||
final String updateURL = selectedObject.getUpdateURL();
|
||||
final String updateUsername = selectedObject.getUpdateUsername();
|
||||
final String updatePassword = selectedObject.getUpdatePassword();
|
||||
final List<SwissTimingRaceRecordDTO> selectedRaces = new ArrayList<SwissTimingRaceRecordDTO>();
|
||||
for (final SwissTimingRaceRecordDTO race : this.raceList.getList()) {
|
||||
if (raceTable.getSelectionModel().isSelected(race)) {
|
||||
@@ -573,20 +465,4 @@ public class SwissTimingEventManagementPanel extends AbstractEventManagementPane
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void updatePanelFromSelectedStoredConfiguration() {
|
||||
if (previousConfigurationsComboBox.getSelectedIndex() >= 0) {
|
||||
SwissTimingConfigurationDTO stConfig = previousConfigurations.get(previousConfigurationsComboBox
|
||||
.getItemText(previousConfigurationsComboBox.getSelectedIndex()));
|
||||
if (stConfig != null) {
|
||||
hostnameTextbox.setValue(stConfig.getHostname());
|
||||
portIntegerbox.setValue(stConfig.getPort());
|
||||
jsonUrlBox.setValue(stConfig.getJsonURL());
|
||||
updateURLBox.setValue(stConfig.getUpdateURL());
|
||||
updateUsernameBox.setValue(stConfig.getUpdateUsername());
|
||||
updatePasswordBox.setValue(stConfig.getUpdatePassword());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+96
-101
@@ -2,16 +2,10 @@ package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.dom.client.Style.Unit;
|
||||
import com.google.gwt.event.dom.client.ChangeEvent;
|
||||
import com.google.gwt.event.dom.client.ChangeHandler;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.user.cellview.client.AbstractCellTable;
|
||||
@@ -24,30 +18,34 @@ import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
import com.google.gwt.user.client.ui.CaptionPanel;
|
||||
import com.google.gwt.user.client.ui.CheckBox;
|
||||
import com.google.gwt.user.client.ui.Grid;
|
||||
import com.google.gwt.user.client.ui.HasVerticalAlignment;
|
||||
import com.google.gwt.user.client.ui.HorizontalPanel;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.ListBox;
|
||||
import com.google.gwt.user.client.ui.TextBox;
|
||||
import com.google.gwt.user.client.ui.VerticalPanel;
|
||||
import com.google.gwt.view.client.ListDataProvider;
|
||||
import com.sap.sailing.domain.common.RegattaIdentifier;
|
||||
import com.sap.sailing.domain.common.RegattaName;
|
||||
import com.sap.sailing.domain.common.security.SecuredDomainType;
|
||||
import com.sap.sailing.gwt.ui.adminconsole.swisstiming.EditSwissTimingArchivedConnectionDialog;
|
||||
import com.sap.sailing.gwt.ui.adminconsole.swisstiming.SwissTimingArchivedConnectionTableWrapper;
|
||||
import com.sap.sailing.gwt.ui.client.RegattaRefresher;
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SwissTimingArchiveConfigurationDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SwissTimingArchiveConfigurationWithSecurityDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SwissTimingReplayRaceDTO;
|
||||
import com.sap.sse.common.util.NaturalComparator;
|
||||
import com.sap.sse.gwt.adminconsole.AdminConsoleTableResources;
|
||||
import com.sap.sse.gwt.client.ErrorReporter;
|
||||
import com.sap.sse.gwt.client.async.MarkedAsyncCallback;
|
||||
import com.sap.sse.gwt.client.celltable.BaseCelltable;
|
||||
import com.sap.sse.gwt.client.celltable.CellTableWithCheckboxResources;
|
||||
import com.sap.sse.gwt.client.celltable.EntityIdentityComparator;
|
||||
import com.sap.sse.gwt.client.celltable.RefreshableMultiSelectionModel;
|
||||
import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback;
|
||||
import com.sap.sse.gwt.client.panels.LabeledAbstractFilterablePanel;
|
||||
import com.sap.sse.security.ui.client.UserService;
|
||||
import com.sap.sse.security.ui.client.component.AccessControlledButtonPanel;
|
||||
|
||||
/**
|
||||
* Allows the user to start and stop tracking of events, regattas and races using the SwissTiming connector.
|
||||
@@ -61,59 +59,42 @@ public class SwissTimingReplayConnectorPanel extends AbstractEventManagementPane
|
||||
private final LabeledAbstractFilterablePanel<SwissTimingReplayRaceDTO> filterablePanelEvents;
|
||||
private final ListDataProvider<SwissTimingReplayRaceDTO> raceList;
|
||||
private final CellTable<SwissTimingReplayRaceDTO> raceTable;
|
||||
private final Map<String, SwissTimingArchiveConfigurationDTO> previousConfigurations;
|
||||
private final ListBox previousConfigurationsComboBox;
|
||||
private final TextBox jsonUrlBox;
|
||||
private final Grid grid;
|
||||
private final List<SwissTimingReplayRaceDTO> availableSwissTimingRaces;
|
||||
|
||||
private final SwissTimingArchivedConnectionTableWrapper connectionsTable;
|
||||
|
||||
public SwissTimingReplayConnectorPanel(final SailingServiceAsync sailingService, UserService userService,
|
||||
ErrorReporter errorReporter, RegattaRefresher regattaRefresher, StringMessages stringMessages) {
|
||||
ErrorReporter errorReporter, RegattaRefresher regattaRefresher, StringMessages stringMessages, CellTableWithCheckboxResources tableResources) {
|
||||
super(sailingService, userService, regattaRefresher, errorReporter, true, stringMessages);
|
||||
this.errorReporter = errorReporter;
|
||||
availableSwissTimingRaces = new ArrayList<SwissTimingReplayRaceDTO>();
|
||||
previousConfigurationsComboBox = new ListBox();
|
||||
previousConfigurationsComboBox.addChangeHandler(new ChangeHandler() {
|
||||
@Override
|
||||
public void onChange(ChangeEvent event) {
|
||||
updateJsonUrlFromSelectedPreviousConfiguration();
|
||||
}
|
||||
});
|
||||
previousConfigurations = new HashMap<String, SwissTimingArchiveConfigurationDTO>();
|
||||
getConnectionHistory();
|
||||
|
||||
jsonUrlBox = new TextBox();
|
||||
jsonUrlBox.getElement().getStyle().setWidth(50, Unit.EM);
|
||||
|
||||
VerticalPanel mainPanel = new VerticalPanel();
|
||||
// setup UI
|
||||
final VerticalPanel mainPanel = new VerticalPanel();
|
||||
this.setWidget(mainPanel);
|
||||
mainPanel.setWidth("100%");
|
||||
|
||||
CaptionPanel captionPanelConnections = new CaptionPanel(stringMessages.connections());
|
||||
final CaptionPanel captionPanelConnections = new CaptionPanel(stringMessages.connections());
|
||||
mainPanel.add(captionPanelConnections);
|
||||
|
||||
VerticalPanel verticalPanel = new VerticalPanel();
|
||||
final VerticalPanel verticalPanel = new VerticalPanel();
|
||||
|
||||
captionPanelConnections.setContentWidget(verticalPanel);
|
||||
captionPanelConnections.setStyleName("bold");
|
||||
|
||||
grid = new Grid(3, 2);
|
||||
verticalPanel.add(grid);
|
||||
|
||||
grid.setWidget(0, 0, new Label(stringMessages.swissTimingEvents() + ":"));
|
||||
grid.setWidget(0, 1, previousConfigurationsComboBox);
|
||||
grid.setWidget(1, 0, new Label(stringMessages.jsonUrl() + ":"));
|
||||
grid.setWidget(1, 1, jsonUrlBox);
|
||||
// add connections table
|
||||
connectionsTable = new SwissTimingArchivedConnectionTableWrapper(userService, sailingService, stringMessages,
|
||||
errorReporter, true, tableResources, () -> {
|
||||
});
|
||||
connectionsTable.refreshConnectionList();
|
||||
verticalPanel.add(connectionsTable);
|
||||
|
||||
Button btnListRaces = new Button(stringMessages.listRaces());
|
||||
grid.setWidget(2, 1, btnListRaces);
|
||||
btnListRaces.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
fillRaces(sailingService);
|
||||
}
|
||||
});
|
||||
|
||||
// create button UI
|
||||
final AccessControlledButtonPanel buttonPanel = createButtonPanel(sailingService, userService, errorReporter,
|
||||
stringMessages);
|
||||
verticalPanel.add(buttonPanel);
|
||||
|
||||
// Table
|
||||
TextColumn<SwissTimingReplayRaceDTO> regattaNameColumn = new TextColumn<SwissTimingReplayRaceDTO>() {
|
||||
@Override
|
||||
public String getValue(SwissTimingReplayRaceDTO object) {
|
||||
@@ -265,6 +246,69 @@ public class SwissTimingReplayConnectorPanel extends AbstractEventManagementPane
|
||||
|
||||
}
|
||||
|
||||
private AccessControlledButtonPanel createButtonPanel(final SailingServiceAsync sailingService,
|
||||
UserService userService, ErrorReporter errorReporter, StringMessages stringMessages) {
|
||||
final AccessControlledButtonPanel buttonPanel = new AccessControlledButtonPanel(userService,
|
||||
SecuredDomainType.SWISS_TIMING_ARCHIVE_ACCOUNT);
|
||||
// Refresh action
|
||||
buttonPanel.addUnsecuredAction(stringMessages.refresh(), () -> connectionsTable.refreshConnectionList());
|
||||
// Create action
|
||||
buttonPanel.addCreateAction(stringMessages.addSwissTimingAchivedConnection(),
|
||||
() -> new EditSwissTimingArchivedConnectionDialog(new SwissTimingArchiveConfigurationWithSecurityDTO(),
|
||||
new DialogCallback<SwissTimingArchiveConfigurationWithSecurityDTO>() {
|
||||
@Override
|
||||
public void ok(SwissTimingArchiveConfigurationWithSecurityDTO editedConnection) {
|
||||
sailingService.createSwissTimingArchiveConfiguration(editedConnection.getJsonUrl(),
|
||||
new MarkedAsyncCallback<Void>(new AsyncCallback<Void>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter
|
||||
.reportError("Exception trying to create configuration in DB: "
|
||||
+ caught.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(Void voidResult) {
|
||||
connectionsTable.refreshConnectionList();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
}
|
||||
}, userService, errorReporter).show());
|
||||
// Remove action
|
||||
final Button removeButton = buttonPanel.addRemoveAction(stringMessages.remove(), () -> {
|
||||
sailingService.deleteSwissTimingArchiveConfiguration(
|
||||
connectionsTable.getSelectionModel().getSelectedObject(), new AsyncCallback<Void>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError(
|
||||
"Exception trying to delete configuration in DB: " + caught.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(Void result) {
|
||||
connectionsTable.refreshConnectionList();
|
||||
}
|
||||
});
|
||||
});
|
||||
// List Race action
|
||||
final Button listRacesButton = buttonPanel.addUnsecuredAction(stringMessages.listRaces(), () -> {
|
||||
fillRaces(sailingService);
|
||||
});
|
||||
listRacesButton.setEnabled(false);
|
||||
removeButton.setEnabled(false);
|
||||
// add change handlers to enable and disable List Races and Remove
|
||||
connectionsTable.getSelectionModel().addSelectionChangeHandler(e -> {
|
||||
final boolean objectSelected = connectionsTable.getSelectionModel().getSelectedObject() != null;
|
||||
listRacesButton.setEnabled(objectSelected);
|
||||
removeButton.setEnabled(objectSelected);
|
||||
});
|
||||
return buttonPanel;
|
||||
}
|
||||
|
||||
private String getBoatClassNamesAsString(SwissTimingReplayRaceDTO object) {
|
||||
return object.boat_class;
|
||||
}
|
||||
@@ -295,32 +339,12 @@ public class SwissTimingReplayConnectorPanel extends AbstractEventManagementPane
|
||||
return result;
|
||||
}
|
||||
|
||||
private void getConnectionHistory() {
|
||||
sailingService.getPreviousSwissTimingArchiveConfigurations(new AsyncCallback<List<SwissTimingArchiveConfigurationDTO>>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError("Remote Procedure Call getPreviousConfigurations() - Failure: "
|
||||
+ caught.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(List<SwissTimingArchiveConfigurationDTO> result) {
|
||||
previousConfigurationsComboBox.clear();
|
||||
previousConfigurations.clear();
|
||||
Collections.sort(result, (c1, c2) -> c1.getJsonUrl().compareTo(c2.getJsonUrl()));
|
||||
for (SwissTimingArchiveConfigurationDTO configEntry : result) {
|
||||
String name = configEntry.getJsonUrl();
|
||||
previousConfigurations.put(name, configEntry);
|
||||
previousConfigurationsComboBox.addItem(name);
|
||||
}
|
||||
updateJsonUrlFromSelectedPreviousConfiguration();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void fillRaces(final SailingServiceAsync sailingService) {
|
||||
final String swissTimingJsonUrl = jsonUrlBox.getValue();
|
||||
sailingService.listSwissTiminigReplayRaces(swissTimingJsonUrl, new AsyncCallback<List<SwissTimingReplayRaceDTO>>() {
|
||||
final SwissTimingArchiveConfigurationWithSecurityDTO selectedObject = connectionsTable.getSelectionModel()
|
||||
.getSelectedObject();
|
||||
if (selectedObject != null) {
|
||||
sailingService.listSwissTiminigReplayRaces(selectedObject.getJsonUrl(),
|
||||
new AsyncCallback<List<SwissTimingReplayRaceDTO>>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
SwissTimingReplayConnectorPanel.this.errorReporter.reportError("Error trying to list SwissTiming races: "
|
||||
@@ -335,26 +359,9 @@ public class SwissTimingReplayConnectorPanel extends AbstractEventManagementPane
|
||||
raceList.getList().addAll(availableSwissTimingRaces);
|
||||
filterablePanelEvents.getTextBox().setText(null);
|
||||
filterablePanelEvents.updateAll(races);
|
||||
// store a successful configuration in the database for later retrieval
|
||||
sailingService.storeSwissTimingArchiveConfiguration(swissTimingJsonUrl,
|
||||
new AsyncCallback<Void>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError("Exception trying to store configuration in DB: "
|
||||
+ caught.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(Void voidResult) {
|
||||
// refresh list of previous configurations
|
||||
SwissTimingArchiveConfigurationDTO stConfig = new SwissTimingArchiveConfigurationDTO(swissTimingJsonUrl);
|
||||
if (previousConfigurations.put(stConfig.getJsonUrl(), stConfig) == null) {
|
||||
previousConfigurationsComboBox.addItem(stConfig.getJsonUrl());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void trackSelectedRaces(boolean trackWind, boolean correctWindByDeclination, boolean useInternalMarkPassingAlgorithm) {
|
||||
@@ -387,16 +394,4 @@ public class SwissTimingReplayConnectorPanel extends AbstractEventManagementPane
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void updateJsonUrlFromSelectedPreviousConfiguration() {
|
||||
int selectedIndex = previousConfigurationsComboBox.getSelectedIndex();
|
||||
String selectedConfiguration;
|
||||
if (selectedIndex >= 0) {
|
||||
selectedConfiguration = previousConfigurationsComboBox.getItemText(selectedIndex);
|
||||
} else {
|
||||
selectedConfiguration = null;
|
||||
}
|
||||
jsonUrlBox.setText(selectedConfiguration);
|
||||
}
|
||||
|
||||
}
|
||||
+113
-188
@@ -1,17 +1,12 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.event.dom.client.ChangeEvent;
|
||||
import com.google.gwt.event.dom.client.ChangeHandler;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.user.cellview.client.AbstractCellTable;
|
||||
@@ -28,31 +23,34 @@ import com.google.gwt.user.client.ui.Grid;
|
||||
import com.google.gwt.user.client.ui.HTMLTable.ColumnFormatter;
|
||||
import com.google.gwt.user.client.ui.HorizontalPanel;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.ListBox;
|
||||
import com.google.gwt.user.client.ui.PasswordTextBox;
|
||||
import com.google.gwt.user.client.ui.TextBox;
|
||||
import com.google.gwt.user.client.ui.VerticalPanel;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.google.gwt.view.client.ListDataProvider;
|
||||
import com.google.gwt.view.client.SelectionModel;
|
||||
import com.sap.sailing.domain.common.RegattaIdentifier;
|
||||
import com.sap.sailing.domain.common.RegattaName;
|
||||
import com.sap.sailing.domain.common.security.SecuredDomainType;
|
||||
import com.sap.sailing.gwt.ui.adminconsole.tractrac.EditTracTracConnectionDialog;
|
||||
import com.sap.sailing.gwt.ui.adminconsole.tractrac.TracTracConnectionTableWrapper;
|
||||
import com.sap.sailing.gwt.ui.client.RegattaRefresher;
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.TracTracConfigurationDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.TracTracConfigurationWithSecurityDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.TracTracRaceRecordDTO;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.util.NaturalComparator;
|
||||
import com.sap.sse.gwt.adminconsole.AdminConsoleTableResources;
|
||||
import com.sap.sse.gwt.client.ErrorReporter;
|
||||
import com.sap.sse.gwt.client.async.MarkedAsyncCallback;
|
||||
import com.sap.sse.gwt.client.celltable.CellTableWithCheckboxResources;
|
||||
import com.sap.sse.gwt.client.celltable.EntityIdentityComparator;
|
||||
import com.sap.sse.gwt.client.celltable.FlushableCellTable;
|
||||
import com.sap.sse.gwt.client.celltable.SelectionCheckboxColumn;
|
||||
import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback;
|
||||
import com.sap.sse.gwt.client.panels.LabeledAbstractFilterablePanel;
|
||||
import com.sap.sse.security.ui.client.UserService;
|
||||
import com.sap.sse.security.ui.client.component.AccessControlledButtonPanel;
|
||||
|
||||
/**
|
||||
* Allows the user to start and stop tracking of events, regattas and races using the TracTrac connector. In particular,
|
||||
@@ -70,30 +68,27 @@ import com.sap.sse.security.ui.client.UserService;
|
||||
public class TracTracEventManagementPanel extends AbstractEventManagementPanel {
|
||||
private final ErrorReporter errorReporter;
|
||||
|
||||
private final Map<String, TracTracConfigurationDTO> previousConfigurations;
|
||||
|
||||
private final List<TracTracRaceRecordDTO> availableTracTracRaces;
|
||||
|
||||
private final ListDataProvider<TracTracRaceRecordDTO> raceList;
|
||||
|
||||
private ListBox connectionsHistoryListBox;
|
||||
|
||||
private TextBox storedURITextBox;
|
||||
private TextBox liveURITextBox;
|
||||
private TextBox jsonURLTextBox;
|
||||
private TextBox tracTracUpdateURITextBox;
|
||||
private TextBox tractracUsernameTextBox;
|
||||
private PasswordTextBox tractracPasswordTextBox;
|
||||
private TracTracConnectionTableWrapper connectionsTable;
|
||||
|
||||
private Label loadingMessageLabel;
|
||||
|
||||
private LabeledAbstractFilterablePanel<TracTracRaceRecordDTO> racesFilterablePanel;
|
||||
private FlushableCellTable<TracTracRaceRecordDTO> racesTable;
|
||||
|
||||
|
||||
private final UserService userService;
|
||||
private final CellTableWithCheckboxResources tableResources;
|
||||
|
||||
public TracTracEventManagementPanel(final SailingServiceAsync sailingService, UserService userService,
|
||||
ErrorReporter errorReporter, RegattaRefresher regattaRefresher, StringMessages stringMessages) {
|
||||
ErrorReporter errorReporter, RegattaRefresher regattaRefresher, StringMessages stringMessages,
|
||||
final CellTableWithCheckboxResources tableResources) {
|
||||
super(sailingService, userService, regattaRefresher, errorReporter, true, stringMessages);
|
||||
this.userService = userService;
|
||||
this.errorReporter = errorReporter;
|
||||
this.previousConfigurations = new HashMap<String, TracTracConfigurationDTO>();
|
||||
this.tableResources = tableResources;
|
||||
this.availableTracTracRaces = new ArrayList<TracTracRaceRecordDTO>();
|
||||
this.raceList = new ListDataProvider<TracTracRaceRecordDTO>();
|
||||
this.setWidget(createContent());
|
||||
@@ -111,8 +106,6 @@ public class TracTracEventManagementPanel extends AbstractEventManagementPanel {
|
||||
|
||||
mainPanel.add(racesPanel);
|
||||
|
||||
fillConfigurations();
|
||||
|
||||
return mainPanel;
|
||||
}
|
||||
|
||||
@@ -120,113 +113,80 @@ public class TracTracEventManagementPanel extends AbstractEventManagementPanel {
|
||||
CaptionPanel connectionsPanel = new CaptionPanel("TracTrac " + stringMessages.connections());
|
||||
connectionsPanel.ensureDebugId("ConnectionsSection");
|
||||
connectionsPanel.setStyleName("bold");
|
||||
|
||||
Grid grid = new Grid(10, 3);
|
||||
connectionsPanel.setContentWidget(grid);
|
||||
|
||||
// Existing TracTrac connections
|
||||
Label connectionsHistoryLabel = new Label("TracTrac " + stringMessages.connections() + ":");
|
||||
|
||||
connectionsHistoryListBox = new ListBox();
|
||||
connectionsHistoryListBox.ensureDebugId("ConnectionHistory");
|
||||
connectionsHistoryListBox.addChangeHandler(new ChangeHandler() {
|
||||
@Override
|
||||
public void onChange(ChangeEvent event) {
|
||||
updatePanelFromSelectedStoredConfiguration();
|
||||
}
|
||||
});
|
||||
connectionsHistoryListBox.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
// TODO: This leads to a strange behavior (values are updated by opening the drop down) but at the
|
||||
// moment there is no other way to "reset" the values to the selected value, if the selection does
|
||||
// not change since there is no close event or something similar.
|
||||
updatePanelFromSelectedStoredConfiguration();
|
||||
}
|
||||
});
|
||||
|
||||
grid.setWidget(0, 0, connectionsHistoryLabel);
|
||||
grid.setWidget(0, 1, connectionsHistoryListBox);
|
||||
|
||||
// URIs (Live and Stored)
|
||||
grid.setWidget(1, 0, new Label(stringMessages.details() + ":"));
|
||||
|
||||
Label liveURILabel = new Label(stringMessages.liveUri() + ":");
|
||||
liveURILabel.setTitle(stringMessages.leaveEmptyForDefault());
|
||||
|
||||
liveURITextBox = new TextBox();
|
||||
liveURITextBox.ensureDebugId("LiveURITextBox");
|
||||
liveURITextBox.setVisibleLength(40);
|
||||
liveURITextBox.setTitle(stringMessages.leaveEmptyForDefault());
|
||||
|
||||
grid.setWidget(2, 0, liveURILabel);
|
||||
grid.setWidget(2, 1, liveURITextBox);
|
||||
|
||||
Label storedURILabel = new Label(stringMessages.storedUri() + ":");
|
||||
storedURILabel.setTitle(stringMessages.leaveEmptyForDefault());
|
||||
|
||||
storedURITextBox = new TextBox();
|
||||
storedURITextBox.ensureDebugId("StoredURITextBox");
|
||||
storedURITextBox.setVisibleLength(40);
|
||||
storedURITextBox.setTitle(stringMessages.leaveEmptyForDefault());
|
||||
|
||||
grid.setWidget(3, 0, storedURILabel);
|
||||
grid.setWidget(3, 1, storedURITextBox);
|
||||
|
||||
// JSON URL
|
||||
Label jsonURLLabel = new Label(stringMessages.jsonUrl() + ":");
|
||||
|
||||
jsonURLTextBox = new TextBox();
|
||||
jsonURLTextBox.ensureDebugId("JsonURLTextBox");
|
||||
jsonURLTextBox.setVisibleLength(100);
|
||||
|
||||
grid.setWidget(4, 0, jsonURLLabel);
|
||||
grid.setWidget(4, 1, jsonURLTextBox);
|
||||
|
||||
// Course design Update URL
|
||||
Label tracTracUpdateURLLabel = new Label(stringMessages.tracTracUpdateUrl() + ":");
|
||||
|
||||
tracTracUpdateURITextBox = new TextBox();
|
||||
tracTracUpdateURITextBox.ensureDebugId("TracTracUpdateURITextBox");
|
||||
tracTracUpdateURITextBox.setVisibleLength(100);
|
||||
|
||||
grid.setWidget(5, 0, tracTracUpdateURLLabel);
|
||||
grid.setWidget(5, 1, tracTracUpdateURITextBox);
|
||||
|
||||
// TracTrac Username
|
||||
tractracUsernameTextBox = new TextBox();
|
||||
tractracUsernameTextBox.ensureDebugId("TracTracUsernameTextBox");
|
||||
tractracUsernameTextBox.setVisibleLength(40);
|
||||
|
||||
grid.setWidget(6, 0, new Label(stringMessages.tractracUsername() + ":"));
|
||||
grid.setWidget(6, 1, tractracUsernameTextBox);
|
||||
|
||||
// TracTrac Password
|
||||
tractracPasswordTextBox = new PasswordTextBox();
|
||||
tractracPasswordTextBox.ensureDebugId("TracTracPasswordTextBox");
|
||||
tractracPasswordTextBox.setVisibleLength(40);
|
||||
|
||||
grid.setWidget(7, 0, new Label(stringMessages.tractracPassword() + ":"));
|
||||
grid.setWidget(7, 1, tractracPasswordTextBox);
|
||||
|
||||
grid.setWidget(8, 0, new Label(stringMessages.racesWithHiddenState() + ":"));
|
||||
VerticalPanel tableAndConfigurationPanel = new VerticalPanel();
|
||||
connectionsTable = new TracTracConnectionTableWrapper(userService, sailingService, stringMessages,
|
||||
errorReporter, true, tableResources, () -> {});
|
||||
connectionsTable.refreshTracTracConnectionList();
|
||||
connectionsPanel.setContentWidget(tableAndConfigurationPanel);
|
||||
final Grid grid = new Grid(1, 2);
|
||||
grid.setWidget(0, 0, new Label(stringMessages.racesWithHiddenState() + ":"));
|
||||
final CheckBox showHiddenRacesCheckbox = new CheckBox(stringMessages.show());
|
||||
showHiddenRacesCheckbox.ensureDebugId("ShowHiddenRacesCheckBox");
|
||||
grid.setWidget(8, 1, showHiddenRacesCheckbox);
|
||||
grid.setWidget(0, 1, showHiddenRacesCheckbox);
|
||||
tableAndConfigurationPanel.add(connectionsTable);
|
||||
tableAndConfigurationPanel.add(grid);
|
||||
// Add TracTrac Connection
|
||||
final AccessControlledButtonPanel buttonPanel = new AccessControlledButtonPanel(userService, SecuredDomainType.TRACKED_RACE);
|
||||
tableAndConfigurationPanel.add(buttonPanel);
|
||||
buttonPanel.addUnsecuredAction(stringMessages.refresh(), () -> connectionsTable.refreshTracTracConnectionList());
|
||||
Button addCreateAction = buttonPanel.addCreateAction(stringMessages.addTracTracConnection(),
|
||||
() -> new EditTracTracConnectionDialog(new TracTracConfigurationWithSecurityDTO(),
|
||||
new DialogCallback<TracTracConfigurationWithSecurityDTO>() {
|
||||
@Override
|
||||
public void ok(TracTracConfigurationWithSecurityDTO editedConnection) {
|
||||
sailingService.createTracTracConfiguration(editedConnection.getName(),
|
||||
editedConnection.getJsonUrl(), editedConnection.getLiveDataURI(),
|
||||
editedConnection.getStoredDataURI(),
|
||||
editedConnection.getCourseDesignUpdateURI(),
|
||||
editedConnection.getTracTracUsername(), editedConnection.getTracTracPassword(),
|
||||
new MarkedAsyncCallback<Void>(new AsyncCallback<Void>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
reportError("Exception trying to create configuration in DB: "
|
||||
+ caught.getMessage());
|
||||
}
|
||||
|
||||
// List Races
|
||||
Button listRacesButton = new Button(stringMessages.listRaces());
|
||||
listRacesButton.ensureDebugId("ListRacesButton");
|
||||
listRacesButton.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
loadingMessageLabel.setText(stringMessages.loading());
|
||||
fillRaces(sailingService, showHiddenRacesCheckbox.getValue());
|
||||
}
|
||||
@Override
|
||||
public void onSuccess(Void voidResult) {
|
||||
connectionsTable.refreshTracTracConnectionList();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
}
|
||||
}, userService, errorReporter).show());
|
||||
addCreateAction.ensureDebugId("AddConnectionButton");
|
||||
final Button removeButton = buttonPanel.addRemoveAction(stringMessages.remove(), () -> {
|
||||
sailingService.deleteTracTracConfiguration(connectionsTable.getSelectionModel().getSelectedObject(),
|
||||
new AsyncCallback<Void>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError(
|
||||
"Exception trying to delete configuration in DB: " + caught.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(Void result) {
|
||||
connectionsTable.refreshTracTracConnectionList();
|
||||
}
|
||||
});
|
||||
});
|
||||
grid.setWidget(9, 1, listRacesButton);
|
||||
loadingMessageLabel = new Label();
|
||||
grid.setWidget(9, 2, loadingMessageLabel);
|
||||
final Button listRacesButton = buttonPanel.addUnsecuredAction(stringMessages.listRaces(), () -> {
|
||||
loadingMessageLabel.setText(stringMessages.loading());
|
||||
fillRaces(sailingService, showHiddenRacesCheckbox.getValue());
|
||||
});
|
||||
listRacesButton.ensureDebugId("ListRacesButton");
|
||||
listRacesButton.setEnabled(false);
|
||||
removeButton.setEnabled(false);
|
||||
buttonPanel.addUnsecuredWidget(loadingMessageLabel);
|
||||
connectionsTable.getSelectionModel().addSelectionChangeHandler(e -> {
|
||||
final boolean objectSelected = connectionsTable.getSelectionModel().getSelectedObject() != null;
|
||||
listRacesButton.setEnabled(objectSelected);
|
||||
removeButton.setEnabled(objectSelected);
|
||||
});
|
||||
return connectionsPanel;
|
||||
}
|
||||
|
||||
@@ -386,7 +346,10 @@ public class TracTracEventManagementPanel extends AbstractEventManagementPanel {
|
||||
raceList.addDataDisplay(racesTable);
|
||||
layoutTable.setWidget(++row, 0, racesTable);
|
||||
cellFormatter.setColSpan(row, 0, 2);
|
||||
Button startTrackingButton = new Button(stringMessages.startTracking());
|
||||
final Button startTrackingButton = new Button(stringMessages.startTracking());
|
||||
startTrackingButton.setEnabled(false);
|
||||
connectionsTable.getSelectionModel().addSelectionChangeHandler(
|
||||
e -> startTrackingButton.setEnabled(connectionsTable.getSelectionModel().getSelectedObject() != null));
|
||||
startTrackingButton.ensureDebugId("StartTrackingButton");
|
||||
startTrackingButton.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
@@ -480,40 +443,13 @@ public class TracTracEventManagementPanel extends AbstractEventManagementPanel {
|
||||
return result;
|
||||
}
|
||||
|
||||
private void fillConfigurations() {
|
||||
this.sailingService.getPreviousTracTracConfigurations(new MarkedAsyncCallback<List<TracTracConfigurationDTO>>(
|
||||
new AsyncCallback<List<TracTracConfigurationDTO>>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
reportError("Remote Procedure Call getPreviousConfigurations() - Failure: " + caught.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(List<TracTracConfigurationDTO> result) {
|
||||
TracTracEventManagementPanel.this.previousConfigurations.clear();
|
||||
TracTracEventManagementPanel.this.connectionsHistoryListBox.clear();
|
||||
Collections.sort(result, (c1, c2) -> c1.name.compareTo(c2.name));
|
||||
for (TracTracConfigurationDTO config : result) {
|
||||
TracTracEventManagementPanel.this.previousConfigurations.put(config.name, config);
|
||||
TracTracEventManagementPanel.this.connectionsHistoryListBox.addItem(config.name, config.name);
|
||||
}
|
||||
|
||||
if (!result.isEmpty()) {
|
||||
updatePanelFromSelectedStoredConfiguration();
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private void fillRaces(final SailingServiceAsync sailingService, boolean listHiddenRaces) {
|
||||
final String jsonURL = jsonURLTextBox.getValue();
|
||||
final String liveDataURI = liveURITextBox.getValue();
|
||||
final String storedDataURI = storedURITextBox.getValue();
|
||||
final String courseDesignUpdateURI = tracTracUpdateURITextBox.getValue();
|
||||
final String tractracUsername = tractracUsernameTextBox.getValue();
|
||||
final String tractracPassword = tractracPasswordTextBox.getValue();
|
||||
final TracTracConfigurationWithSecurityDTO selectedConnection = connectionsTable.getSelectionModel()
|
||||
.getSelectedObject();
|
||||
if (selectedConnection != null) {
|
||||
|
||||
sailingService.listTracTracRacesInEvent(jsonURL, listHiddenRaces, new MarkedAsyncCallback<com.sap.sse.common.Util.Pair<String, List<TracTracRaceRecordDTO>>>(
|
||||
sailingService.listTracTracRacesInEvent(selectedConnection.getJsonUrl(), listHiddenRaces,
|
||||
new MarkedAsyncCallback<com.sap.sse.common.Util.Pair<String, List<TracTracRaceRecordDTO>>>(
|
||||
new AsyncCallback<com.sap.sse.common.Util.Pair<String, List<TracTracRaceRecordDTO>>>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
@@ -525,7 +461,9 @@ public class TracTracEventManagementPanel extends AbstractEventManagementPanel {
|
||||
public void onSuccess(final com.sap.sse.common.Util.Pair<String, List<TracTracRaceRecordDTO>> result) {
|
||||
loadingMessageLabel.setText("Building resultset and saving configuration...");
|
||||
TracTracEventManagementPanel.this.availableTracTracRaces.clear();
|
||||
final String eventName = result.getA();
|
||||
final TracTracConfigurationWithSecurityDTO updatedConnection = new TracTracConfigurationWithSecurityDTO(
|
||||
selectedConnection,
|
||||
result.getA());
|
||||
final List<TracTracRaceRecordDTO> eventRaces = result.getB();
|
||||
if (eventRaces != null) {
|
||||
TracTracEventManagementPanel.this.availableTracTracRaces.addAll(eventRaces);
|
||||
@@ -540,8 +478,8 @@ public class TracTracEventManagementPanel extends AbstractEventManagementPanel {
|
||||
loadingMessageLabel.setText("");
|
||||
|
||||
// store a successful configuration in the database for later retrieval
|
||||
sailingService.storeTracTracConfiguration(eventName, jsonURL, liveDataURI, storedDataURI,
|
||||
courseDesignUpdateURI, tractracUsername, tractracPassword, new MarkedAsyncCallback<Void>(
|
||||
sailingService.updateTracTracConfiguration(updatedConnection,
|
||||
new MarkedAsyncCallback<Void>(
|
||||
new AsyncCallback<Void>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
@@ -550,25 +488,22 @@ public class TracTracEventManagementPanel extends AbstractEventManagementPanel {
|
||||
|
||||
@Override
|
||||
public void onSuccess(Void voidResult) {
|
||||
// refresh list of previous configurations
|
||||
TracTracConfigurationDTO config = new TracTracConfigurationDTO(eventName, jsonURL,
|
||||
liveDataURI, storedDataURI, courseDesignUpdateURI, tractracUsername, tractracPassword);
|
||||
|
||||
if (TracTracEventManagementPanel.this.previousConfigurations.put(config.name, config) == null) {
|
||||
TracTracEventManagementPanel.this.connectionsHistoryListBox.addItem(config.name, config.name);
|
||||
}
|
||||
connectionsTable.refreshTracTracConnectionList();
|
||||
}
|
||||
}));
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
private void trackSelectedRaces(boolean trackWind, boolean correctWind, final Duration offsetToStartTimeOfSimulatedRace, boolean ignoreTracTracMarkPassings) {
|
||||
String liveURI = liveURITextBox.getValue();
|
||||
String storedURI = storedURITextBox.getValue();
|
||||
String courseDesignUpdateURI = tracTracUpdateURITextBox.getValue();
|
||||
String tractracUsername = tractracUsernameTextBox.getValue();
|
||||
String tractracPassword = tractracPasswordTextBox.getValue();
|
||||
final TracTracConfigurationWithSecurityDTO selectedConnection = connectionsTable.getSelectionModel()
|
||||
.getSelectedObject();
|
||||
String liveURI = selectedConnection.getLiveDataURI();
|
||||
String storedURI = selectedConnection.getStoredDataURI();
|
||||
String courseDesignUpdateURI = selectedConnection.getCourseDesignUpdateURI();
|
||||
String tractracUsername = selectedConnection.getTracTracUsername();
|
||||
String tractracPassword = selectedConnection.getTracTracPassword();
|
||||
RegattaDTO selectedRegatta = getSelectedRegatta(); // null meaning "Default Regatta" selection
|
||||
RegattaIdentifier regattaIdentifier = null;
|
||||
if (selectedRegatta != null) {
|
||||
@@ -603,19 +538,9 @@ public class TracTracEventManagementPanel extends AbstractEventManagementPanel {
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
private void updatePanelFromSelectedStoredConfiguration() {
|
||||
int index = connectionsHistoryListBox.getSelectedIndex();
|
||||
if (index != -1) {
|
||||
String configurationKey = connectionsHistoryListBox.getValue(index);
|
||||
TracTracConfigurationDTO config = previousConfigurations.get(configurationKey);
|
||||
jsonURLTextBox.setValue(config.jsonURL);
|
||||
liveURITextBox.setValue(config.liveDataURI);
|
||||
storedURITextBox.setValue(config.storedDataURI);
|
||||
tracTracUpdateURITextBox.setValue(config.courseDesignUpdateURI);
|
||||
tractracUsernameTextBox.setValue(config.tractracUsername);
|
||||
tractracPasswordTextBox.setValue(config.tractracPassword);
|
||||
}
|
||||
}
|
||||
|
||||
public void refreshTracTracConnectors() {
|
||||
connectionsTable.refreshTracTracConnectionList();
|
||||
raceList.getList().clear();
|
||||
}
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole.swisstiming;
|
||||
|
||||
import com.google.gwt.user.client.ui.FocusWidget;
|
||||
import com.google.gwt.user.client.ui.Grid;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.TextBox;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.SwissTimingArchiveConfigurationWithSecurityDTO;
|
||||
import com.sap.sse.gwt.client.ErrorReporter;
|
||||
import com.sap.sse.gwt.client.dialog.DataEntryDialog;
|
||||
import com.sap.sse.security.ui.client.UserService;
|
||||
|
||||
/**
|
||||
* Edits a {@link SwissTimingArchiveConfigurationWithSecurityDTO} object. Can be accessed from
|
||||
* {@link SwissTimingArchivedConnectionTableWrapper}
|
||||
*/
|
||||
public class EditSwissTimingArchivedConnectionDialog
|
||||
extends DataEntryDialog<SwissTimingArchiveConfigurationWithSecurityDTO> {
|
||||
private static final StringMessages stringMessages = StringMessages.INSTANCE;
|
||||
private Grid grid;
|
||||
|
||||
private TextBox jsonURLTextBox;
|
||||
private final SwissTimingArchiveConfigurationWithSecurityDTO dtoToEdit;
|
||||
|
||||
private static class EmptyTextValidator implements Validator<SwissTimingArchiveConfigurationWithSecurityDTO> {
|
||||
@Override
|
||||
public String getErrorMessage(SwissTimingArchiveConfigurationWithSecurityDTO valueToValidate) {
|
||||
final String result;
|
||||
if (valueToValidate.getJsonUrl() == null || valueToValidate.getJsonUrl().trim().isEmpty()) {
|
||||
result = stringMessages.pleaseEnterNonEmptyUrl();
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The class creates the UI-dialog to type in the Data about a the selected swiss timing account.
|
||||
*
|
||||
* @param userToEdit
|
||||
* The 'userToEdit' parameter contains the user which should be changed or initialized.
|
||||
*/
|
||||
public EditSwissTimingArchivedConnectionDialog(final SwissTimingArchiveConfigurationWithSecurityDTO dtoToEdit,
|
||||
final DialogCallback<SwissTimingArchiveConfigurationWithSecurityDTO> callback,
|
||||
final UserService userService,
|
||||
final ErrorReporter errorReporter) {
|
||||
super(stringMessages.editSwissTimingAchivedConnection(), null, stringMessages.ok(), stringMessages.cancel(),
|
||||
/* validator */ new EmptyTextValidator(), /* animationEnabled */true, callback);
|
||||
this.dtoToEdit = dtoToEdit;
|
||||
this.ensureDebugId("EditSwissTimingArchivedConnectionDialog");
|
||||
createUi();
|
||||
setData(dtoToEdit);
|
||||
}
|
||||
|
||||
private void setData(final SwissTimingArchiveConfigurationWithSecurityDTO dtotoEdit) {
|
||||
jsonURLTextBox.setText(dtotoEdit.getJsonUrl());
|
||||
validateAndUpdate();
|
||||
}
|
||||
|
||||
private void createUi() {
|
||||
grid = new Grid(2, 2);
|
||||
grid.setWidget(0, 0, new Label(stringMessages.details() + ":"));
|
||||
// JSON URL
|
||||
Label jsonURLLabel = new Label(stringMessages.jsonUrl() + ":");
|
||||
jsonURLTextBox = createTextBox("");
|
||||
jsonURLTextBox.ensureDebugId("JsonURLTextBox");
|
||||
jsonURLTextBox.setVisibleLength(100);
|
||||
// validation: User should not create empty connections
|
||||
grid.setWidget(1, 0, jsonURLLabel);
|
||||
grid.setWidget(1, 1, jsonURLTextBox);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FocusWidget getInitialFocusWidget() {
|
||||
return jsonURLTextBox;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SwissTimingArchiveConfigurationWithSecurityDTO getResult() {
|
||||
final String jsonURL = jsonURLTextBox.getValue();
|
||||
return new SwissTimingArchiveConfigurationWithSecurityDTO(jsonURL, dtoToEdit.getCreatorName());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Widget getAdditionalWidget() {
|
||||
return grid;
|
||||
}
|
||||
|
||||
}
|
||||
+183
@@ -0,0 +1,183 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole.swisstiming;
|
||||
|
||||
import com.google.gwt.user.client.ui.FocusWidget;
|
||||
import com.google.gwt.user.client.ui.Grid;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.PasswordTextBox;
|
||||
import com.google.gwt.user.client.ui.TextBox;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.SwissTimingConfigurationWithSecurityDTO;
|
||||
import com.sap.sse.gwt.client.ErrorReporter;
|
||||
import com.sap.sse.gwt.client.dialog.DataEntryDialog;
|
||||
import com.sap.sse.security.ui.client.UserService;
|
||||
|
||||
/**
|
||||
* Edits a {@link SwissTimingConfigurationWithSecurityDTO} object. Can be accessed from
|
||||
* {@link SwissTimingConnectionTableWrapper}. The Manage2Sail event ID and the complete URL
|
||||
* field update each other mutually upon manual update.
|
||||
*/
|
||||
public class EditSwissTimingConnectionDialog extends DataEntryDialog<SwissTimingConfigurationWithSecurityDTO> {
|
||||
private static final StringMessages stringMessages = StringMessages.INSTANCE;
|
||||
|
||||
private Grid grid;
|
||||
|
||||
private TextBox manage2SailEventIdTextBox;
|
||||
private TextBox manage2SailEventUrlJsonTextBox;
|
||||
private TextBox hostnameTextBox;
|
||||
private TextBox portTextBox;
|
||||
private TextBox updateUrlTextBox;
|
||||
private TextBox updateUsernameTextBox;
|
||||
private PasswordTextBox updatePasswordTextBox;
|
||||
private final SwissTimingConfigurationWithSecurityDTO dtoToEdit;
|
||||
|
||||
private static class EmptyFieldValidator implements Validator<SwissTimingConfigurationWithSecurityDTO> {
|
||||
@Override
|
||||
public String getErrorMessage(SwissTimingConfigurationWithSecurityDTO valueToValidate) {
|
||||
final String result;
|
||||
if (valueToValidate.getJsonUrl() == null || valueToValidate.getJsonUrl().trim().isEmpty()) {
|
||||
result = stringMessages.pleaseEnterNonEmptyUrl();
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The class creates the UI-dialog to type in the Data about a the selected swiss timing account.
|
||||
*
|
||||
* @param userToEdit
|
||||
* The 'userToEdit' parameter contains the user which should be changed or initialized.
|
||||
*/
|
||||
public EditSwissTimingConnectionDialog(final SwissTimingConfigurationWithSecurityDTO dtotoEdit,
|
||||
final DialogCallback<SwissTimingConfigurationWithSecurityDTO> callback, final UserService userService,
|
||||
final ErrorReporter errorReporter) {
|
||||
super(stringMessages.editSwissTimingConnections(), null, stringMessages.ok(), stringMessages.cancel(),
|
||||
/* validator */ new EmptyFieldValidator(),
|
||||
/* animationEnabled */true, callback);
|
||||
this.dtoToEdit = dtotoEdit;
|
||||
this.ensureDebugId("EditTracTracConnectionDialog");
|
||||
createUi();
|
||||
setData(dtotoEdit);
|
||||
}
|
||||
|
||||
private void setData(final SwissTimingConfigurationWithSecurityDTO dtoToEdit) {
|
||||
manage2SailEventUrlJsonTextBox.setText(dtoToEdit.getJsonUrl());
|
||||
hostnameTextBox.setText(dtoToEdit.getHostname());
|
||||
portTextBox.setText(dtoToEdit.getPort() == null ? "" : ("" + dtoToEdit.getPort()));
|
||||
updateUrlTextBox.setText(dtoToEdit.getUpdateURL());
|
||||
updateUsernameTextBox.setText(dtoToEdit.getUpdateUsername());
|
||||
updatePasswordTextBox.setText(dtoToEdit.getUpdatePassword());
|
||||
validateAndUpdate();
|
||||
}
|
||||
|
||||
private void createUi() {
|
||||
grid = new Grid(8, 2);
|
||||
grid.setWidget(0, 0, new Label(stringMessages.details() + ":"));
|
||||
// Manage2SailEventId
|
||||
final Label manage2SailEventIdLabel = new Label(stringMessages.manage2SailEventIdBox() + ":");
|
||||
manage2SailEventIdLabel.setTitle(stringMessages.leaveEmptyForDefault());
|
||||
manage2SailEventIdTextBox = createTextBox("");
|
||||
manage2SailEventIdTextBox.ensureDebugId("Manage2SailEventIdTextBox");
|
||||
manage2SailEventIdTextBox.setVisibleLength(40);
|
||||
manage2SailEventIdTextBox.setTitle(stringMessages.manage2SailEventIdBox());
|
||||
// update url with changed event id
|
||||
manage2SailEventIdTextBox.addKeyUpHandler(e -> updateUrlFromEventId(manage2SailEventIdTextBox.getText()));
|
||||
grid.setWidget(1, 0, manage2SailEventIdLabel);
|
||||
grid.setWidget(1, 1, manage2SailEventIdTextBox);
|
||||
// Manage2SailEventUrl
|
||||
final Label manage2SailEventUrlJsonLabel = new Label(stringMessages.manage2SailEventURLBox() + ":");
|
||||
manage2SailEventUrlJsonLabel.setTitle(stringMessages.leaveEmptyForDefault());
|
||||
manage2SailEventUrlJsonTextBox = createTextBox("");
|
||||
manage2SailEventUrlJsonTextBox.ensureDebugId("Manage2SailEventUrlJsonTextBox");
|
||||
manage2SailEventUrlJsonTextBox.setVisibleLength(40);
|
||||
manage2SailEventUrlJsonTextBox.setTitle(stringMessages.manage2SailEventURLBox());
|
||||
grid.setWidget(2, 0, manage2SailEventUrlJsonLabel);
|
||||
grid.setWidget(2, 1, manage2SailEventUrlJsonTextBox);
|
||||
// Hostname
|
||||
final Label hostnameLabel = new Label(stringMessages.hostname() + ":");
|
||||
manage2SailEventUrlJsonLabel.setTitle(stringMessages.leaveEmptyForDefault());
|
||||
hostnameTextBox = createTextBox("");
|
||||
hostnameTextBox.ensureDebugId("HostnameTextBox");
|
||||
hostnameTextBox.setVisibleLength(40);
|
||||
hostnameTextBox.setTitle(stringMessages.hostname());
|
||||
grid.setWidget(3, 0, hostnameLabel);
|
||||
grid.setWidget(3, 1, hostnameTextBox);
|
||||
// Port
|
||||
final Label portLabel = new Label(stringMessages.manage2SailPort() + ":");
|
||||
portLabel.setTitle(stringMessages.leaveEmptyForDefault());
|
||||
portTextBox = createTextBox("");
|
||||
portTextBox.ensureDebugId("PortTextBox");
|
||||
portTextBox.setVisibleLength(40);
|
||||
portTextBox.setTitle(stringMessages.manage2SailPort());
|
||||
grid.setWidget(4, 0, portLabel);
|
||||
grid.setWidget(4, 1, portTextBox);
|
||||
// Update URL
|
||||
final Label updateUrlLabel = new Label(stringMessages.swissTimingUpdateURL() + ":");
|
||||
updateUrlLabel.setTitle(stringMessages.leaveEmptyForDefault());
|
||||
updateUrlTextBox = createTextBox("");
|
||||
updateUrlTextBox.ensureDebugId("UpdateUrlTextBox");
|
||||
updateUrlTextBox.setVisibleLength(40);
|
||||
updateUrlTextBox.setTitle(stringMessages.swissTimingUpdateURL());
|
||||
grid.setWidget(5, 0, updateUrlLabel);
|
||||
grid.setWidget(5, 1, updateUrlTextBox);
|
||||
// Update Username
|
||||
final Label updateUsernameLabel = new Label(stringMessages.swissTimingUpdateUsername() + ":");
|
||||
updateUsernameLabel.setTitle(stringMessages.leaveEmptyForDefault());
|
||||
updateUsernameTextBox = createTextBox("");
|
||||
updateUsernameTextBox.ensureDebugId("UpdateUsernameTextBox");
|
||||
updateUsernameTextBox.setVisibleLength(40);
|
||||
updateUsernameTextBox.setTitle(stringMessages.swissTimingUpdateUsername());
|
||||
grid.setWidget(6, 0, updateUsernameLabel);
|
||||
grid.setWidget(6, 1, updateUsernameTextBox);
|
||||
// Update Password
|
||||
final Label updatePasswordLabel = new Label(stringMessages.swissTimingUpdatePassword() + ":");
|
||||
updatePasswordLabel.setTitle(stringMessages.leaveEmptyForDefault());
|
||||
updatePasswordTextBox = createPasswordTextBox("");
|
||||
updatePasswordTextBox.ensureDebugId("UpdatePasswordTextBox");
|
||||
updatePasswordTextBox.setVisibleLength(40);
|
||||
updatePasswordTextBox.setTitle(stringMessages.swissTimingUpdatePassword());
|
||||
grid.setWidget(7, 0, updatePasswordLabel);
|
||||
grid.setWidget(7, 1, updatePasswordTextBox);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function tries to infer a valid JsonUrl for any input given that matches the pattern of an event Id from
|
||||
* M2S. If there is an event id detected the Json Url gets updated and the event Id textbox is filled with the
|
||||
* detected event Id. The ID pattern is defined in {@link eventIdPattern}.
|
||||
*/
|
||||
private void updateUrlFromEventId(String eventIdText) {
|
||||
final String result = SwissTimingEventIdUrlUtil.getUrlFromEventId(eventIdText);
|
||||
if (result != null) {
|
||||
manage2SailEventUrlJsonTextBox.setValue(result, /* fire events */ false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FocusWidget getInitialFocusWidget() {
|
||||
return manage2SailEventUrlJsonTextBox;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SwissTimingConfigurationWithSecurityDTO getResult() {
|
||||
Integer port = null;
|
||||
if (!portTextBox.getText().isEmpty()) {
|
||||
try {
|
||||
port = Integer.parseInt(portTextBox.getText());
|
||||
} catch (NumberFormatException e) {
|
||||
// port will be null.
|
||||
}
|
||||
}
|
||||
|
||||
return new SwissTimingConfigurationWithSecurityDTO(dtoToEdit.getName(),
|
||||
manage2SailEventUrlJsonTextBox.getValue(), hostnameTextBox.getValue(), port,
|
||||
updateUrlTextBox.getValue(), updateUsernameTextBox.getValue(), updatePasswordTextBox.getValue(),
|
||||
dtoToEdit.getCreatorName());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Widget getAdditionalWidget() {
|
||||
return grid;
|
||||
}
|
||||
}
|
||||
+172
@@ -0,0 +1,172 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole.swisstiming;
|
||||
|
||||
import static com.sap.sse.security.ui.client.component.AccessControlledActionsColumn.create;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gwt.user.cellview.client.AbstractCellTable;
|
||||
import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler;
|
||||
import com.google.gwt.user.cellview.client.TextColumn;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.sap.sailing.domain.common.security.SecuredDomainType;
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.shared.SwissTimingArchiveConfigurationWithSecurityDTO;
|
||||
import com.sap.sse.gwt.client.ErrorReporter;
|
||||
import com.sap.sse.gwt.client.async.MarkedAsyncCallback;
|
||||
import com.sap.sse.gwt.client.celltable.AbstractSortableTextColumn;
|
||||
import com.sap.sse.gwt.client.celltable.CellTableWithCheckboxResources;
|
||||
import com.sap.sse.gwt.client.celltable.EntityIdentityComparator;
|
||||
import com.sap.sse.gwt.client.celltable.RefreshableSingleSelectionModel;
|
||||
import com.sap.sse.gwt.client.celltable.TableWrapper;
|
||||
import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback;
|
||||
import com.sap.sse.gwt.client.panels.LabeledAbstractFilterablePanel;
|
||||
import com.sap.sse.security.shared.HasPermissions;
|
||||
import com.sap.sse.security.shared.HasPermissions.DefaultActions;
|
||||
import com.sap.sse.security.ui.client.UserService;
|
||||
import com.sap.sse.security.ui.client.component.AccessControlledActionsColumn;
|
||||
import com.sap.sse.security.ui.client.component.DefaultActionsImagesBarCell;
|
||||
import com.sap.sse.security.ui.client.component.EditOwnershipDialog;
|
||||
import com.sap.sse.security.ui.client.component.SecuredDTOOwnerColumn;
|
||||
import com.sap.sse.security.ui.client.component.editacl.EditACLDialog;
|
||||
import com.sap.sse.security.ui.client.i18n.StringMessages;
|
||||
|
||||
/**
|
||||
* A wrapper for a CellTable displaying an overview over the existing Swiss Timing Archived Connections. It shows the
|
||||
* User-Group name, the group and user each user group is owned by and options to delete the group, change the ownership
|
||||
* or edit the associated ACL.
|
||||
*/
|
||||
public class SwissTimingArchivedConnectionTableWrapper extends
|
||||
TableWrapper<SwissTimingArchiveConfigurationWithSecurityDTO, RefreshableSingleSelectionModel<SwissTimingArchiveConfigurationWithSecurityDTO>, StringMessages, CellTableWithCheckboxResources> {
|
||||
private final LabeledAbstractFilterablePanel<SwissTimingArchiveConfigurationWithSecurityDTO> filterField;
|
||||
private final SailingServiceAsync sailingServiceAsync;
|
||||
private final com.sap.sailing.gwt.ui.client.StringMessages stringMessagesClient;
|
||||
|
||||
public SwissTimingArchivedConnectionTableWrapper(final UserService userService, final SailingServiceAsync sailingServiceAsync,
|
||||
final com.sap.sailing.gwt.ui.client.StringMessages stringMessages, final ErrorReporter errorReporter,
|
||||
final boolean enablePager, final CellTableWithCheckboxResources tableResources, final Runnable refresher) {
|
||||
super(stringMessages, errorReporter, false, enablePager,
|
||||
new EntityIdentityComparator<SwissTimingArchiveConfigurationWithSecurityDTO>() {
|
||||
@Override
|
||||
public boolean representSameEntity(SwissTimingArchiveConfigurationWithSecurityDTO dto1,
|
||||
SwissTimingArchiveConfigurationWithSecurityDTO dto2) {
|
||||
return dto1.getIdentifier().equals(dto2.getIdentifier());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode(SwissTimingArchiveConfigurationWithSecurityDTO t) {
|
||||
return t.getIdentifier().hashCode();
|
||||
}
|
||||
}, tableResources);
|
||||
this.stringMessagesClient = stringMessages;
|
||||
this.sailingServiceAsync = sailingServiceAsync;
|
||||
final ListHandler<SwissTimingArchiveConfigurationWithSecurityDTO> swissTimingAccountColumnListHandler = getColumnSortHandler();
|
||||
|
||||
// table
|
||||
final TextColumn<SwissTimingArchiveConfigurationWithSecurityDTO> swissTimingAccountJsonUrlColumn = new AbstractSortableTextColumn<SwissTimingArchiveConfigurationWithSecurityDTO>(
|
||||
dto -> dto.getJsonUrl(), swissTimingAccountColumnListHandler);
|
||||
final TextColumn<SwissTimingArchiveConfigurationWithSecurityDTO> swissTimingAccountCreatorNameColumn = new AbstractSortableTextColumn<SwissTimingArchiveConfigurationWithSecurityDTO>(
|
||||
dto -> dto.getCreatorName(), swissTimingAccountColumnListHandler);
|
||||
|
||||
final HasPermissions type = SecuredDomainType.SWISS_TIMING_ARCHIVE_ACCOUNT;
|
||||
final AccessControlledActionsColumn<SwissTimingArchiveConfigurationWithSecurityDTO, DefaultActionsImagesBarCell> actionColumn = create(
|
||||
new DefaultActionsImagesBarCell(stringMessages), userService);
|
||||
actionColumn.addAction(DefaultActionsImagesBarCell.ACTION_UPDATE, DefaultActions.UPDATE, dto -> {
|
||||
new EditSwissTimingArchivedConnectionDialog(dto,
|
||||
new DialogCallback<SwissTimingArchiveConfigurationWithSecurityDTO>() {
|
||||
@Override
|
||||
public void ok(final SwissTimingArchiveConfigurationWithSecurityDTO editedObject) {
|
||||
sailingServiceAsync.updateSwissTimingArchiveConfiguration(editedObject,
|
||||
new MarkedAsyncCallback<Void>(new AsyncCallback<Void>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError(
|
||||
"Exception trying to update configuration in DB: " + caught.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(Void voidResult) {
|
||||
refreshConnectionList();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
}
|
||||
}, userService, errorReporter).show();
|
||||
});
|
||||
actionColumn.addAction(DefaultActionsImagesBarCell.ACTION_DELETE, DefaultActions.DELETE, dto -> {
|
||||
sailingServiceAsync.deleteSwissTimingArchiveConfiguration(dto, new AsyncCallback<Void>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError("Exception trying to delete configuration in DB: " + caught.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(Void result) {
|
||||
refreshConnectionList();
|
||||
}
|
||||
});
|
||||
});
|
||||
final EditOwnershipDialog.DialogConfig<SwissTimingArchiveConfigurationWithSecurityDTO> configOwnership = EditOwnershipDialog
|
||||
.create(userService.getUserManagementService(), type, dto -> refreshConnectionList(),
|
||||
stringMessages);
|
||||
final EditACLDialog.DialogConfig<SwissTimingArchiveConfigurationWithSecurityDTO> configACL = EditACLDialog
|
||||
.create(
|
||||
userService.getUserManagementService(), type, dto -> dto.getAccessControlList(), stringMessages);
|
||||
actionColumn.addAction(DefaultActionsImagesBarCell.ACTION_CHANGE_OWNERSHIP, DefaultActions.CHANGE_OWNERSHIP,
|
||||
configOwnership::openDialog);
|
||||
actionColumn.addAction(DefaultActionsImagesBarCell.ACTION_CHANGE_ACL, DefaultActions.CHANGE_ACL,
|
||||
u -> configACL.openDialog(u));
|
||||
filterField = new LabeledAbstractFilterablePanel<SwissTimingArchiveConfigurationWithSecurityDTO>(
|
||||
new Label(stringMessages.filterSwissTimingAchivedConnections()),
|
||||
new ArrayList<SwissTimingArchiveConfigurationWithSecurityDTO>(), dataProvider) {
|
||||
@Override
|
||||
public Iterable<String> getSearchableStrings(SwissTimingArchiveConfigurationWithSecurityDTO t) {
|
||||
List<String> strings = new ArrayList<String>();
|
||||
strings.add(t.getName());
|
||||
strings.add(t.getCreatorName());
|
||||
return strings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractCellTable<SwissTimingArchiveConfigurationWithSecurityDTO> getCellTable() {
|
||||
return table;
|
||||
}
|
||||
};
|
||||
registerSelectionModelOnNewDataProvider(filterField.getAllListDataProvider());
|
||||
|
||||
mainPanel.insert(filterField, 0);
|
||||
table.addColumnSortHandler(swissTimingAccountColumnListHandler);
|
||||
table.addColumn(swissTimingAccountJsonUrlColumn, stringMessagesClient.jsonUrl());
|
||||
table.addColumn(swissTimingAccountCreatorNameColumn, stringMessagesClient.creatorName());
|
||||
SecuredDTOOwnerColumn.configureOwnerColumns(table, swissTimingAccountColumnListHandler, stringMessages);
|
||||
table.addColumn(actionColumn, stringMessages.actions());
|
||||
table.ensureDebugId("SwissTimingConfigurationWithSecurityDTOTable");
|
||||
}
|
||||
|
||||
public LabeledAbstractFilterablePanel<SwissTimingArchiveConfigurationWithSecurityDTO> getFilterField() {
|
||||
return filterField;
|
||||
}
|
||||
|
||||
public void refreshConnectionList() {
|
||||
sailingServiceAsync.getPreviousSwissTimingArchiveConfigurations(
|
||||
new AsyncCallback<List<SwissTimingArchiveConfigurationWithSecurityDTO>>() {
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError(
|
||||
"Remote Procedure Call getPreviousSwissTimingArchiveConfigurations() - Failure: "
|
||||
+ caught.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(List<SwissTimingArchiveConfigurationWithSecurityDTO> result) {
|
||||
filterField.updateAll(result);
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+204
@@ -0,0 +1,204 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole.swisstiming;
|
||||
|
||||
import static com.sap.sse.security.ui.client.component.AccessControlledActionsColumn.create;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gwt.user.cellview.client.AbstractCellTable;
|
||||
import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler;
|
||||
import com.google.gwt.user.cellview.client.TextColumn;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.sap.sailing.domain.common.security.SecuredDomainType;
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.shared.SwissTimingConfigurationWithSecurityDTO;
|
||||
import com.sap.sse.gwt.client.ErrorReporter;
|
||||
import com.sap.sse.gwt.client.async.MarkedAsyncCallback;
|
||||
import com.sap.sse.gwt.client.celltable.AbstractSortableTextColumn;
|
||||
import com.sap.sse.gwt.client.celltable.CellTableWithCheckboxResources;
|
||||
import com.sap.sse.gwt.client.celltable.EntityIdentityComparator;
|
||||
import com.sap.sse.gwt.client.celltable.RefreshableSingleSelectionModel;
|
||||
import com.sap.sse.gwt.client.celltable.TableWrapper;
|
||||
import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback;
|
||||
import com.sap.sse.gwt.client.panels.LabeledAbstractFilterablePanel;
|
||||
import com.sap.sse.security.shared.HasPermissions;
|
||||
import com.sap.sse.security.shared.HasPermissions.DefaultActions;
|
||||
import com.sap.sse.security.ui.client.UserService;
|
||||
import com.sap.sse.security.ui.client.component.AccessControlledActionsColumn;
|
||||
import com.sap.sse.security.ui.client.component.DefaultActionsImagesBarCell;
|
||||
import com.sap.sse.security.ui.client.component.EditOwnershipDialog;
|
||||
import com.sap.sse.security.ui.client.component.SecuredDTOOwnerColumn;
|
||||
import com.sap.sse.security.ui.client.component.editacl.EditACLDialog;
|
||||
import com.sap.sse.security.ui.client.i18n.StringMessages;
|
||||
|
||||
/**
|
||||
* A wrapper for a CellTable displaying an overview over the existing SwissTimingConnections. It shows the name, the
|
||||
* event id, the event json url, the hostname, the port, the update url, the username for sending updates, the password
|
||||
* for sending updates, the name of the creator, the group and user each user group is owned by. There are options edit
|
||||
* or to delete the connection, change the ownership or edit the associated ACL. Editing the connection will open a new
|
||||
* instance of {@link EditSwissTimingConnectionDialog}.
|
||||
*/
|
||||
public class SwissTimingConnectionTableWrapper extends
|
||||
TableWrapper<SwissTimingConfigurationWithSecurityDTO, RefreshableSingleSelectionModel<SwissTimingConfigurationWithSecurityDTO>, StringMessages, CellTableWithCheckboxResources> {
|
||||
private final LabeledAbstractFilterablePanel<SwissTimingConfigurationWithSecurityDTO> filterField;
|
||||
private final SailingServiceAsync sailingServiceAsync;
|
||||
private final com.sap.sailing.gwt.ui.client.StringMessages stringMessagesClient;
|
||||
|
||||
public SwissTimingConnectionTableWrapper(final UserService userService, final SailingServiceAsync sailingServiceAsync,
|
||||
final com.sap.sailing.gwt.ui.client.StringMessages stringMessages, final ErrorReporter errorReporter,
|
||||
final boolean enablePager, final CellTableWithCheckboxResources tableResources, final Runnable refresher) {
|
||||
super(stringMessages, errorReporter, false, enablePager,
|
||||
new EntityIdentityComparator<SwissTimingConfigurationWithSecurityDTO>() {
|
||||
@Override
|
||||
public boolean representSameEntity(SwissTimingConfigurationWithSecurityDTO dto1,
|
||||
SwissTimingConfigurationWithSecurityDTO dto2) {
|
||||
return dto1.getIdentifier().equals(dto2.getIdentifier());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode(SwissTimingConfigurationWithSecurityDTO t) {
|
||||
return t.getIdentifier().hashCode();
|
||||
}
|
||||
}, tableResources);
|
||||
this.stringMessagesClient = stringMessages;
|
||||
this.sailingServiceAsync = sailingServiceAsync;
|
||||
final ListHandler<SwissTimingConfigurationWithSecurityDTO> swissTimingConectionColumnListHandler = getColumnSortHandler();
|
||||
|
||||
// table
|
||||
final TextColumn<SwissTimingConfigurationWithSecurityDTO> swissTimingConnectionNameColumn = new AbstractSortableTextColumn<SwissTimingConfigurationWithSecurityDTO>(
|
||||
dto -> dto.getName(), swissTimingConectionColumnListHandler);
|
||||
final TextColumn<SwissTimingConfigurationWithSecurityDTO> swissTimingConnectionManage2SailEventIdColumn = new AbstractSortableTextColumn<SwissTimingConfigurationWithSecurityDTO>(
|
||||
dto -> SwissTimingEventIdUrlUtil.getEventIdFromUrl(dto.getJsonUrl()),
|
||||
swissTimingConectionColumnListHandler);
|
||||
final TextColumn<SwissTimingConfigurationWithSecurityDTO> swissTimingConnectionJsonUrlColumn = new AbstractSortableTextColumn<SwissTimingConfigurationWithSecurityDTO>(
|
||||
dto -> dto.getJsonUrl(), swissTimingConectionColumnListHandler);
|
||||
final TextColumn<SwissTimingConfigurationWithSecurityDTO> swissTimingConnectionHostnameColumn = new AbstractSortableTextColumn<SwissTimingConfigurationWithSecurityDTO>(
|
||||
dto -> dto.getHostname(), swissTimingConectionColumnListHandler);
|
||||
final TextColumn<SwissTimingConfigurationWithSecurityDTO> swissTimingConnectionPortColumn = new AbstractSortableTextColumn<SwissTimingConfigurationWithSecurityDTO>(
|
||||
dto -> dto.getPort() == null ? "" : ("" + dto.getPort()), swissTimingConectionColumnListHandler);
|
||||
final TextColumn<SwissTimingConfigurationWithSecurityDTO> swissTimingConnectionUpdateUrlColumn = new AbstractSortableTextColumn<SwissTimingConfigurationWithSecurityDTO>(
|
||||
dto -> dto.getUpdateURL(), swissTimingConectionColumnListHandler);
|
||||
final TextColumn<SwissTimingConfigurationWithSecurityDTO> swissTimingConnectionUpdateUsernameColumn = new AbstractSortableTextColumn<SwissTimingConfigurationWithSecurityDTO>(
|
||||
dto -> dto.getUpdateUsername(), swissTimingConectionColumnListHandler);
|
||||
final TextColumn<SwissTimingConfigurationWithSecurityDTO> swissTimingConnectionCreatorNameColumn = new AbstractSortableTextColumn<SwissTimingConfigurationWithSecurityDTO>(
|
||||
dto -> dto.getCreatorName(), swissTimingConectionColumnListHandler);
|
||||
|
||||
final HasPermissions type = SecuredDomainType.SWISS_TIMING_ACCOUNT;
|
||||
final AccessControlledActionsColumn<SwissTimingConfigurationWithSecurityDTO, DefaultActionsImagesBarCell> actionColumn = create(
|
||||
new DefaultActionsImagesBarCell(stringMessages), userService);
|
||||
actionColumn.addAction(DefaultActionsImagesBarCell.ACTION_UPDATE, DefaultActions.UPDATE, dto -> {
|
||||
new EditSwissTimingConnectionDialog(dto, new DialogCallback<SwissTimingConfigurationWithSecurityDTO>() {
|
||||
@Override
|
||||
public void ok(final SwissTimingConfigurationWithSecurityDTO editedObject) {
|
||||
sailingServiceAsync.updateSwissTimingConfiguration(editedObject,
|
||||
new MarkedAsyncCallback<Void>(new AsyncCallback<Void>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError(
|
||||
"Exception trying to update configuration in DB: " + caught.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(Void voidResult) {
|
||||
refreshSwissTimingConnectionList();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
}
|
||||
}, userService, errorReporter).show();
|
||||
});
|
||||
|
||||
actionColumn.addAction(DefaultActionsImagesBarCell.ACTION_DELETE, DefaultActions.DELETE, dto -> {
|
||||
sailingServiceAsync.deleteSwissTimingConfiguration(dto, new AsyncCallback<Void>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError("Exception trying to delete configuration in DB: " + caught.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(Void result) {
|
||||
refreshSwissTimingConnectionList();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
final EditOwnershipDialog.DialogConfig<SwissTimingConfigurationWithSecurityDTO> configOwnership = EditOwnershipDialog
|
||||
.create(userService.getUserManagementService(), type, dto -> refreshSwissTimingConnectionList(),
|
||||
stringMessages);
|
||||
|
||||
final EditACLDialog.DialogConfig<SwissTimingConfigurationWithSecurityDTO> configACL = EditACLDialog.create(
|
||||
userService.getUserManagementService(), type, dto -> dto.getAccessControlList(), stringMessages);
|
||||
|
||||
actionColumn.addAction(DefaultActionsImagesBarCell.ACTION_CHANGE_OWNERSHIP, DefaultActions.CHANGE_OWNERSHIP,
|
||||
configOwnership::openDialog);
|
||||
actionColumn.addAction(DefaultActionsImagesBarCell.ACTION_CHANGE_ACL, DefaultActions.CHANGE_ACL,
|
||||
u -> configACL.openDialog(u));
|
||||
|
||||
filterField = new LabeledAbstractFilterablePanel<SwissTimingConfigurationWithSecurityDTO>(
|
||||
new Label(stringMessagesClient.filterSwissTimingConnections()),
|
||||
new ArrayList<SwissTimingConfigurationWithSecurityDTO>(), dataProvider) {
|
||||
@Override
|
||||
public Iterable<String> getSearchableStrings(SwissTimingConfigurationWithSecurityDTO t) {
|
||||
List<String> strings = new ArrayList<String>();
|
||||
strings.add(t.getName());
|
||||
if (t.getUpdateUsername() != null) {
|
||||
strings.add(t.getUpdateUsername());
|
||||
}
|
||||
strings.add(t.getCreatorName());
|
||||
if (t.getHostname() != null) {
|
||||
strings.add(t.getHostname());
|
||||
}
|
||||
if (t.getPort() != null) {
|
||||
strings.add(t.getPort().toString());
|
||||
}
|
||||
return strings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractCellTable<SwissTimingConfigurationWithSecurityDTO> getCellTable() {
|
||||
return table;
|
||||
}
|
||||
};
|
||||
registerSelectionModelOnNewDataProvider(filterField.getAllListDataProvider());
|
||||
mainPanel.insert(filterField, 0);
|
||||
table.addColumnSortHandler(swissTimingConectionColumnListHandler);
|
||||
table.addColumn(swissTimingConnectionNameColumn, getStringMessages().name());
|
||||
table.addColumn(swissTimingConnectionManage2SailEventIdColumn, stringMessagesClient.manage2SailEventIdBox());
|
||||
table.addColumn(swissTimingConnectionJsonUrlColumn, stringMessagesClient.manage2SailEventURLBox());
|
||||
table.addColumn(swissTimingConnectionHostnameColumn, stringMessagesClient.hostname());
|
||||
table.addColumn(swissTimingConnectionPortColumn, stringMessagesClient.manage2SailPort());
|
||||
table.addColumn(swissTimingConnectionUpdateUrlColumn, stringMessagesClient.updateURL());
|
||||
table.addColumn(swissTimingConnectionUpdateUsernameColumn, stringMessagesClient.username());
|
||||
table.addColumn(swissTimingConnectionCreatorNameColumn, stringMessagesClient.creatorName());
|
||||
SecuredDTOOwnerColumn.configureOwnerColumns(table, swissTimingConectionColumnListHandler, stringMessages);
|
||||
table.addColumn(actionColumn, stringMessages.actions());
|
||||
table.ensureDebugId("SwissTimingConfigurationWithSecurityDTOTable");
|
||||
}
|
||||
|
||||
public LabeledAbstractFilterablePanel<SwissTimingConfigurationWithSecurityDTO> getFilterField() {
|
||||
return filterField;
|
||||
}
|
||||
|
||||
public void refreshSwissTimingConnectionList() {
|
||||
sailingServiceAsync
|
||||
.getPreviousSwissTimingConfigurations(
|
||||
new AsyncCallback<List<SwissTimingConfigurationWithSecurityDTO>>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter
|
||||
.reportError(
|
||||
"Remote Procedure Call getPreviousSwissTimingConfigurations() - Failure: "
|
||||
+ caught.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(List<SwissTimingConfigurationWithSecurityDTO> result) {
|
||||
filterField.updateAll(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole.swisstiming;
|
||||
|
||||
public final class SwissTimingEventIdUrlUtil {
|
||||
private static final String EVENT_ID_PATTERN = "[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}";
|
||||
private static final String MANAGE2SAIL_API_BASE_URL = "http://manage2sail.com/api/public/links/event/";
|
||||
private static final String MANAGE2SAIL_API_ACCESS_TOKEN = "?accesstoken=bDAv8CwsTM94ujZ";
|
||||
private static final String MANAGE2SAIL_API_APPENDIX = "&mediaType=json&includeRaces=true";
|
||||
|
||||
/**
|
||||
* Similar to {@link #updateUrlFromEventId} this function tries to extract a M2S event Id by looking at the given
|
||||
* url.
|
||||
*
|
||||
* @return The event ID inferred from the Json Url.
|
||||
*/
|
||||
public static String getEventIdFromUrl(String eventUrl) {
|
||||
if (eventUrl.matches("http://manage2sail.com/.*" + EVENT_ID_PATTERN + ".*")) {
|
||||
return eventUrl.replaceFirst(".*(" + EVENT_ID_PATTERN + ").*", "$1");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function tries to infer a valid JsonUrl for any input given that matches the pattern of an event Id from
|
||||
* M2S. If there is an event id detected the Json Url gets returned.The ID pattern is defined in
|
||||
* {@link eventIdPattern}.
|
||||
*/
|
||||
public static String getUrlFromEventId(String eventIdText) {
|
||||
if (eventIdText.matches(".*" + EVENT_ID_PATTERN + ".*")) {
|
||||
final String inferredEventId = eventIdText.replaceFirst(".*(" + EVENT_ID_PATTERN + ").*", "$1");
|
||||
return MANAGE2SAIL_API_BASE_URL + inferredEventId + MANAGE2SAIL_API_ACCESS_TOKEN + MANAGE2SAIL_API_APPENDIX;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole.tractrac;
|
||||
|
||||
import com.google.gwt.user.client.ui.FocusWidget;
|
||||
import com.google.gwt.user.client.ui.Grid;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.PasswordTextBox;
|
||||
import com.google.gwt.user.client.ui.TextBox;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.TracTracConfigurationWithSecurityDTO;
|
||||
import com.sap.sse.gwt.client.ErrorReporter;
|
||||
import com.sap.sse.gwt.client.dialog.DataEntryDialog;
|
||||
import com.sap.sse.security.ui.client.UserService;
|
||||
|
||||
/**
|
||||
* Edits a {@link TracTracConfigurationWithSecurityDTO} object. Can be accessed from
|
||||
* {@link TracTracConnectionTableWrapper}
|
||||
*/
|
||||
public class EditTracTracConnectionDialog extends DataEntryDialog<TracTracConfigurationWithSecurityDTO> {
|
||||
private static final StringMessages stringMessages = StringMessages.INSTANCE;
|
||||
private Grid grid;
|
||||
|
||||
private TextBox storedURITextBox;
|
||||
private TextBox liveURITextBox;
|
||||
private TextBox jsonURLTextBox;
|
||||
private TextBox tracTracUpdateURITextBox;
|
||||
private TextBox tractracUsernameTextBox;
|
||||
private PasswordTextBox tractracPasswordTextBox;
|
||||
private final TracTracConfigurationWithSecurityDTO dtoToEdit;
|
||||
|
||||
/**
|
||||
* The class creates the UI-dialog to type in the Data about a the selected trac trac account.
|
||||
*
|
||||
* @param userToEdit
|
||||
* The 'userToEdit' parameter contains the user which should be changed or initialized.
|
||||
*/
|
||||
public EditTracTracConnectionDialog(final TracTracConfigurationWithSecurityDTO dtotoEdit,
|
||||
final DialogCallback<TracTracConfigurationWithSecurityDTO> callback, final UserService userService,
|
||||
final ErrorReporter errorReporter) {
|
||||
super(stringMessages.editTracTracConnection(), null, stringMessages.ok(), stringMessages.cancel(),
|
||||
/* validator */ null, /* animationEnabled */true, callback);
|
||||
this.dtoToEdit = dtotoEdit;
|
||||
this.ensureDebugId("EditTracTracConnectionDialog");
|
||||
createUi();
|
||||
setData(dtotoEdit);
|
||||
}
|
||||
|
||||
private void setData(final TracTracConfigurationWithSecurityDTO dtotoEdit) {
|
||||
storedURITextBox.setText(dtotoEdit.getStoredDataURI());
|
||||
liveURITextBox.setText(dtotoEdit.getLiveDataURI());
|
||||
jsonURLTextBox.setText(dtotoEdit.getJsonUrl());
|
||||
tracTracUpdateURITextBox.setText(dtotoEdit.getCourseDesignUpdateURI());
|
||||
tractracUsernameTextBox.setText(dtotoEdit.getTracTracUsername());
|
||||
tractracPasswordTextBox.setText(dtotoEdit.getTracTracPassword());
|
||||
super.getOkButton().setEnabled(!jsonURLTextBox.getText().isEmpty());
|
||||
}
|
||||
|
||||
private void createUi() {
|
||||
grid = new Grid(7, 2);
|
||||
grid.setWidget(0, 0, new Label(stringMessages.details() + ":"));
|
||||
Label liveURILabel = new Label(stringMessages.liveUri() + ":");
|
||||
liveURILabel.setTitle(stringMessages.leaveEmptyForDefault());
|
||||
liveURITextBox = createTextBox("");
|
||||
liveURITextBox.ensureDebugId("LiveURITextBox");
|
||||
liveURITextBox.setVisibleLength(40);
|
||||
liveURITextBox.setTitle(stringMessages.leaveEmptyForDefault());
|
||||
grid.setWidget(1, 0, liveURILabel);
|
||||
grid.setWidget(1, 1, liveURITextBox);
|
||||
Label storedURILabel = new Label(stringMessages.storedUri() + ":");
|
||||
storedURILabel.setTitle(stringMessages.leaveEmptyForDefault());
|
||||
storedURITextBox = createTextBox("");
|
||||
storedURITextBox.ensureDebugId("StoredURITextBox");
|
||||
storedURITextBox.setVisibleLength(40);
|
||||
storedURITextBox.setTitle(stringMessages.leaveEmptyForDefault());
|
||||
grid.setWidget(2, 0, storedURILabel);
|
||||
grid.setWidget(2, 1, storedURITextBox);
|
||||
// JSON URL
|
||||
Label jsonURLLabel = new Label(stringMessages.jsonUrl() + ":");
|
||||
jsonURLTextBox = createTextBox("");
|
||||
jsonURLTextBox.ensureDebugId("JsonURLTextBox");
|
||||
jsonURLTextBox.setVisibleLength(100);
|
||||
// validation: User should not create empty connections
|
||||
jsonURLTextBox.addKeyUpHandler(e -> super.getOkButton().setEnabled(!jsonURLTextBox.getText().isEmpty()));
|
||||
grid.setWidget(3, 0, jsonURLLabel);
|
||||
grid.setWidget(3, 1, jsonURLTextBox);
|
||||
// Course design Update URL
|
||||
Label tracTracUpdateURLLabel = new Label(stringMessages.tracTracUpdateUrl() + ":");
|
||||
tracTracUpdateURITextBox = createTextBox("");
|
||||
tracTracUpdateURITextBox.ensureDebugId("TracTracUpdateURITextBox");
|
||||
tracTracUpdateURITextBox.setVisibleLength(100);
|
||||
grid.setWidget(4, 0, tracTracUpdateURLLabel);
|
||||
grid.setWidget(4, 1, tracTracUpdateURITextBox);
|
||||
// TracTrac Username
|
||||
tractracUsernameTextBox = createTextBox("");
|
||||
tractracUsernameTextBox.ensureDebugId("TracTracUsernameTextBox");
|
||||
tractracUsernameTextBox.setVisibleLength(40);
|
||||
grid.setWidget(5, 0, new Label(stringMessages.tractracUsername() + ":"));
|
||||
grid.setWidget(5, 1, tractracUsernameTextBox);
|
||||
// TracTrac Password
|
||||
tractracPasswordTextBox = createPasswordTextBox("");
|
||||
tractracPasswordTextBox.ensureDebugId("TracTracPasswordTextBox");
|
||||
tractracPasswordTextBox.setVisibleLength(40);
|
||||
grid.setWidget(6, 0, new Label(stringMessages.tractracPassword() + ":"));
|
||||
grid.setWidget(6, 1, tractracPasswordTextBox);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FocusWidget getInitialFocusWidget() {
|
||||
return jsonURLTextBox;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TracTracConfigurationWithSecurityDTO getResult() {
|
||||
|
||||
final String jsonURL = jsonURLTextBox.getValue();
|
||||
final String liveDataURI = liveURITextBox.getValue();
|
||||
final String storedDataURI = storedURITextBox.getValue();
|
||||
final String courseDesignUpdateURI = tracTracUpdateURITextBox.getValue();
|
||||
final String tractracUsername = tractracUsernameTextBox.getValue();
|
||||
final String tractracPassword = tractracPasswordTextBox.getValue();
|
||||
|
||||
return new TracTracConfigurationWithSecurityDTO(dtoToEdit.getName(), jsonURL, liveDataURI, storedDataURI,
|
||||
courseDesignUpdateURI, tractracUsername, tractracPassword, dtoToEdit.getCreatorName());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Widget getAdditionalWidget() {
|
||||
return grid;
|
||||
}
|
||||
|
||||
}
|
||||
+185
@@ -0,0 +1,185 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole.tractrac;
|
||||
|
||||
import static com.sap.sse.security.ui.client.component.AccessControlledActionsColumn.create;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gwt.user.cellview.client.AbstractCellTable;
|
||||
import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler;
|
||||
import com.google.gwt.user.cellview.client.TextColumn;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.sap.sailing.domain.common.security.SecuredDomainType;
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.shared.TracTracConfigurationWithSecurityDTO;
|
||||
import com.sap.sse.gwt.client.ErrorReporter;
|
||||
import com.sap.sse.gwt.client.async.MarkedAsyncCallback;
|
||||
import com.sap.sse.gwt.client.celltable.AbstractSortableTextColumn;
|
||||
import com.sap.sse.gwt.client.celltable.CellTableWithCheckboxResources;
|
||||
import com.sap.sse.gwt.client.celltable.EntityIdentityComparator;
|
||||
import com.sap.sse.gwt.client.celltable.RefreshableSingleSelectionModel;
|
||||
import com.sap.sse.gwt.client.celltable.TableWrapper;
|
||||
import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback;
|
||||
import com.sap.sse.gwt.client.panels.LabeledAbstractFilterablePanel;
|
||||
import com.sap.sse.security.shared.HasPermissions;
|
||||
import com.sap.sse.security.shared.HasPermissions.DefaultActions;
|
||||
import com.sap.sse.security.ui.client.UserService;
|
||||
import com.sap.sse.security.ui.client.component.AccessControlledActionsColumn;
|
||||
import com.sap.sse.security.ui.client.component.DefaultActionsImagesBarCell;
|
||||
import com.sap.sse.security.ui.client.component.EditOwnershipDialog;
|
||||
import com.sap.sse.security.ui.client.component.SecuredDTOOwnerColumn;
|
||||
import com.sap.sse.security.ui.client.component.editacl.EditACLDialog;
|
||||
import com.sap.sse.security.ui.client.i18n.StringMessages;
|
||||
|
||||
/**
|
||||
* A wrapper for a CellTable displaying an overview over the existing TracTracConnections. It shows the name, the Live
|
||||
* URI, the Stored Uri, the JSON URL, the TracTrac Server Update URI, the TracTrac user name, the TracTrac password, the
|
||||
* name of the creator, the group and user each user group is owned by. There are options edit or to delete the
|
||||
* connection, change the ownership or edit the associated ACL. Editing the connection will open a new instance of
|
||||
* {@link EditTracTracConnectionDialog}.
|
||||
*/
|
||||
public class TracTracConnectionTableWrapper extends
|
||||
TableWrapper<TracTracConfigurationWithSecurityDTO, RefreshableSingleSelectionModel<TracTracConfigurationWithSecurityDTO>, StringMessages, CellTableWithCheckboxResources> {
|
||||
private final LabeledAbstractFilterablePanel<TracTracConfigurationWithSecurityDTO> filterField;
|
||||
private final SailingServiceAsync sailingServiceAsync;
|
||||
private final com.sap.sailing.gwt.ui.client.StringMessages stringMessagesClient;
|
||||
|
||||
public TracTracConnectionTableWrapper(final UserService userService, final SailingServiceAsync sailingServiceAsync,
|
||||
final com.sap.sailing.gwt.ui.client.StringMessages stringMessages, final ErrorReporter errorReporter,
|
||||
final boolean enablePager, final CellTableWithCheckboxResources tableResources, final Runnable refresher) {
|
||||
super(stringMessages, errorReporter, false, enablePager,
|
||||
new EntityIdentityComparator<TracTracConfigurationWithSecurityDTO>() {
|
||||
@Override
|
||||
public boolean representSameEntity(TracTracConfigurationWithSecurityDTO dto1,
|
||||
TracTracConfigurationWithSecurityDTO dto2) {
|
||||
return dto1.getIdentifier().equals(dto2.getIdentifier());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode(TracTracConfigurationWithSecurityDTO t) {
|
||||
return t.getIdentifier().hashCode();
|
||||
}
|
||||
}, tableResources);
|
||||
this.stringMessagesClient = stringMessages;
|
||||
this.sailingServiceAsync = sailingServiceAsync;
|
||||
final ListHandler<TracTracConfigurationWithSecurityDTO> tracTracAccountColumnListHandler = getColumnSortHandler();
|
||||
|
||||
// table
|
||||
final TextColumn<TracTracConfigurationWithSecurityDTO> tracTracAccountNameColumn = new AbstractSortableTextColumn<TracTracConfigurationWithSecurityDTO>(
|
||||
dto -> dto.getName(), tracTracAccountColumnListHandler);
|
||||
final TextColumn<TracTracConfigurationWithSecurityDTO> tracTracAccountLiveUriColumn = new AbstractSortableTextColumn<TracTracConfigurationWithSecurityDTO>(
|
||||
dto -> dto.getLiveDataURI(), tracTracAccountColumnListHandler);
|
||||
final TextColumn<TracTracConfigurationWithSecurityDTO> tracTracAccountStoredUriColumn = new AbstractSortableTextColumn<TracTracConfigurationWithSecurityDTO>(
|
||||
dto -> dto.getStoredDataURI(), tracTracAccountColumnListHandler);
|
||||
final TextColumn<TracTracConfigurationWithSecurityDTO> tracTracAccountJsonUrlColumn = new AbstractSortableTextColumn<TracTracConfigurationWithSecurityDTO>(
|
||||
dto -> dto.getJsonUrl(), tracTracAccountColumnListHandler);
|
||||
final TextColumn<TracTracConfigurationWithSecurityDTO> tracTracAccountTracTracServerUpdateUriColumn = new AbstractSortableTextColumn<TracTracConfigurationWithSecurityDTO>(
|
||||
dto -> dto.getCourseDesignUpdateURI(), tracTracAccountColumnListHandler);
|
||||
final TextColumn<TracTracConfigurationWithSecurityDTO> tracTracAccountUsernameColumn = new AbstractSortableTextColumn<TracTracConfigurationWithSecurityDTO>(
|
||||
dto -> dto.getTracTracUsername(), tracTracAccountColumnListHandler);
|
||||
final TextColumn<TracTracConfigurationWithSecurityDTO> tracTracAccountCreatorNameColumn = new AbstractSortableTextColumn<TracTracConfigurationWithSecurityDTO>(
|
||||
dto -> dto.getCreatorName(), tracTracAccountColumnListHandler);
|
||||
|
||||
final HasPermissions type = SecuredDomainType.TRACTRAC_ACCOUNT;
|
||||
final AccessControlledActionsColumn<TracTracConfigurationWithSecurityDTO, DefaultActionsImagesBarCell> actionColumn = create(
|
||||
new DefaultActionsImagesBarCell(stringMessages), userService);
|
||||
actionColumn.addAction(DefaultActionsImagesBarCell.ACTION_UPDATE, DefaultActions.UPDATE, dto -> {
|
||||
new EditTracTracConnectionDialog(dto, new DialogCallback<TracTracConfigurationWithSecurityDTO>() {
|
||||
@Override
|
||||
public void ok(final TracTracConfigurationWithSecurityDTO editedObject) {
|
||||
sailingServiceAsync.updateTracTracConfiguration(editedObject,
|
||||
new MarkedAsyncCallback<Void>(new AsyncCallback<Void>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError(
|
||||
"Exception trying to update configuration in DB: " + caught.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(Void voidResult) {
|
||||
refreshTracTracConnectionList();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
}
|
||||
}, userService, errorReporter).show();
|
||||
});
|
||||
|
||||
actionColumn.addAction(DefaultActionsImagesBarCell.ACTION_DELETE, DefaultActions.DELETE, dto -> {
|
||||
sailingServiceAsync.deleteTracTracConfiguration(dto, new AsyncCallback<Void>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError("Exception trying to delete configuration in DB: " + caught.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(Void result) {
|
||||
refreshTracTracConnectionList();
|
||||
}
|
||||
});
|
||||
});
|
||||
final EditOwnershipDialog.DialogConfig<TracTracConfigurationWithSecurityDTO> configOwnership = EditOwnershipDialog
|
||||
.create(userService.getUserManagementService(), type, dto -> refreshTracTracConnectionList(),
|
||||
stringMessages);
|
||||
final EditACLDialog.DialogConfig<TracTracConfigurationWithSecurityDTO> configACL = EditACLDialog.create(
|
||||
userService.getUserManagementService(), type, dto -> dto.getAccessControlList(), stringMessages);
|
||||
actionColumn.addAction(DefaultActionsImagesBarCell.ACTION_CHANGE_OWNERSHIP, DefaultActions.CHANGE_OWNERSHIP,
|
||||
configOwnership::openDialog);
|
||||
actionColumn.addAction(DefaultActionsImagesBarCell.ACTION_CHANGE_ACL, DefaultActions.CHANGE_ACL,
|
||||
u -> configACL.openDialog(u));
|
||||
filterField = new LabeledAbstractFilterablePanel<TracTracConfigurationWithSecurityDTO>(
|
||||
new Label(stringMessages.filterTracTracConnections()),
|
||||
new ArrayList<TracTracConfigurationWithSecurityDTO>(), dataProvider) {
|
||||
@Override
|
||||
public Iterable<String> getSearchableStrings(TracTracConfigurationWithSecurityDTO t) {
|
||||
List<String> strings = new ArrayList<String>();
|
||||
strings.add(t.getName());
|
||||
strings.add(t.getCreatorName());
|
||||
return strings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractCellTable<TracTracConfigurationWithSecurityDTO> getCellTable() {
|
||||
return table;
|
||||
}
|
||||
};
|
||||
registerSelectionModelOnNewDataProvider(filterField.getAllListDataProvider());
|
||||
mainPanel.insert(filterField, 0);
|
||||
table.addColumnSortHandler(tracTracAccountColumnListHandler);
|
||||
table.addColumn(tracTracAccountNameColumn, getStringMessages().name());
|
||||
table.addColumn(tracTracAccountLiveUriColumn, stringMessagesClient.liveUri());
|
||||
table.addColumn(tracTracAccountStoredUriColumn, stringMessagesClient.storedUri());
|
||||
table.addColumn(tracTracAccountJsonUrlColumn, stringMessagesClient.jsonUrl());
|
||||
table.addColumn(tracTracAccountTracTracServerUpdateUriColumn, stringMessagesClient.tracTracUpdateUrl());
|
||||
table.addColumn(tracTracAccountUsernameColumn, stringMessagesClient.tractracUsername());
|
||||
table.addColumn(tracTracAccountCreatorNameColumn, stringMessagesClient.creatorName());
|
||||
SecuredDTOOwnerColumn.configureOwnerColumns(table, tracTracAccountColumnListHandler, stringMessages);
|
||||
table.addColumn(actionColumn, stringMessages.actions());
|
||||
table.ensureDebugId("TracTracConfigurationWithSecurityDTOTable");
|
||||
}
|
||||
|
||||
public LabeledAbstractFilterablePanel<TracTracConfigurationWithSecurityDTO> getFilterField() {
|
||||
return filterField;
|
||||
}
|
||||
|
||||
public void refreshTracTracConnectionList() {
|
||||
sailingServiceAsync
|
||||
.getPreviousTracTracConfigurations(new AsyncCallback<List<TracTracConfigurationWithSecurityDTO>>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter
|
||||
.reportError("Remote Procedure Call getPreviousTracTracConfigurations() - Failure: "
|
||||
+ caught.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(List<TracTracConfigurationWithSecurityDTO> result) {
|
||||
filterField.updateAll(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+36
-15
@@ -82,7 +82,6 @@ import com.sap.sailing.gwt.ui.shared.DeviceConfigurationDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.DeviceConfigurationDTO.RegattaConfigurationDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.DeviceConfigurationWithSecurityDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.DeviceMappingDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.EventBaseDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.EventDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.GPSFixDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.GPSFixDTOWithSpeedWindTackAndLegType;
|
||||
@@ -110,12 +109,12 @@ import com.sap.sailing.gwt.ui.shared.SimulatorResultsDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SliceRacePreperationDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTOWithSecurity;
|
||||
import com.sap.sailing.gwt.ui.shared.SwissTimingArchiveConfigurationDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SwissTimingConfigurationDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SwissTimingArchiveConfigurationWithSecurityDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SwissTimingConfigurationWithSecurityDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SwissTimingEventRecordDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SwissTimingRaceRecordDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SwissTimingReplayRaceDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.TracTracConfigurationDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.TracTracConfigurationWithSecurityDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.TracTracRaceRecordDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.TrackFileImportDeviceIdentifierDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.TypedDeviceMappingDTO;
|
||||
@@ -148,7 +147,14 @@ import com.sap.sse.security.ui.shared.SuccessInfo;
|
||||
* service methods, an empty (non-<code>null</code>) result is returned.
|
||||
*/
|
||||
public interface SailingService extends RemoteService, FileStorageManagementGwtService, RemoteReplicationService {
|
||||
List<TracTracConfigurationDTO> getPreviousTracTracConfigurations() throws UnauthorizedException, Exception;
|
||||
List<TracTracConfigurationWithSecurityDTO> getPreviousTracTracConfigurations()
|
||||
throws UnauthorizedException, Exception;
|
||||
|
||||
void updateTracTracConfiguration(TracTracConfigurationWithSecurityDTO tracTracConfiguration)
|
||||
throws UnauthorizedException, Exception;
|
||||
|
||||
void deleteTracTracConfiguration(TracTracConfigurationWithSecurityDTO tracTracConfiguration)
|
||||
throws UnauthorizedException, Exception;
|
||||
|
||||
List<RegattaDTO> getRegattas() throws UnauthorizedException;
|
||||
|
||||
@@ -156,9 +162,7 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS
|
||||
|
||||
RegattaDTO getRegattaByName(String regattaName) throws UnauthorizedException;
|
||||
|
||||
List<EventDTO> getEvents() throws UnauthorizedException, Exception;
|
||||
|
||||
List<EventBaseDTO> getPublicEventsOfAllSailingServers() throws UnauthorizedException, Exception;
|
||||
List<EventDTO> getEvents() throws Exception;
|
||||
|
||||
Util.Pair<String, List<TracTracRaceRecordDTO>> listTracTracRacesInEvent(String eventJsonURL,
|
||||
boolean listHiddenRaces) throws UnauthorizedException, Exception;
|
||||
@@ -176,7 +180,7 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS
|
||||
boolean trackWind, boolean correctWindByDeclination, boolean useInternalMarkPassingAlgorithm)
|
||||
throws UnauthorizedException;
|
||||
|
||||
void storeTracTracConfiguration(String name, String jsonURL, String liveDataURI, String storedDataURI,
|
||||
void createTracTracConfiguration(String name, String jsonURL, String liveDataURI, String storedDataURI,
|
||||
String courseDesignUpdateURI, String tracTracUsername, String tracTracPassword)
|
||||
throws UnauthorizedException, Exception;
|
||||
|
||||
@@ -364,13 +368,19 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS
|
||||
|
||||
void updateIsMedalRace(String leaderboardName, String columnName, boolean isMedalRace) throws UnauthorizedException;
|
||||
|
||||
List<SwissTimingConfigurationDTO> getPreviousSwissTimingConfigurations() throws UnauthorizedException;
|
||||
List<SwissTimingConfigurationWithSecurityDTO> getPreviousSwissTimingConfigurations() throws UnauthorizedException;
|
||||
|
||||
SwissTimingEventRecordDTO getRacesOfSwissTimingEvent(String eventJsonURL) throws UnauthorizedException, Exception;
|
||||
|
||||
void storeSwissTimingConfiguration(String configName, String jsonURL, String hostname, Integer port,
|
||||
void createSwissTimingConfiguration(String configName, String jsonURL, String hostname, Integer port,
|
||||
String updateURL, String updateUsername, String updatePassword) throws UnauthorizedException, Exception;
|
||||
|
||||
void deleteSwissTimingConfiguration(SwissTimingConfigurationWithSecurityDTO configuration)
|
||||
throws UnauthorizedException, Exception;
|
||||
|
||||
void updateSwissTimingConfiguration(SwissTimingConfigurationWithSecurityDTO configuration)
|
||||
throws UnauthorizedException, Exception;
|
||||
|
||||
String[] getCountryCodes() throws UnauthorizedException;
|
||||
|
||||
Map<CompetitorDTO, List<GPSFixDTOWithSpeedWindTackAndLegType>> getDouglasPoints(
|
||||
@@ -505,9 +515,16 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS
|
||||
|
||||
List<String> getOverallLeaderboardNamesContaining(String leaderboardName) throws UnauthorizedException;
|
||||
|
||||
List<SwissTimingArchiveConfigurationDTO> getPreviousSwissTimingArchiveConfigurations() throws UnauthorizedException;
|
||||
List<SwissTimingArchiveConfigurationWithSecurityDTO> getPreviousSwissTimingArchiveConfigurations() throws UnauthorizedException;
|
||||
|
||||
void storeSwissTimingArchiveConfiguration(String swissTimingUrl) throws UnauthorizedException, Exception;
|
||||
void createSwissTimingArchiveConfiguration(String jsonUrl)
|
||||
throws UnauthorizedException, Exception;
|
||||
|
||||
void updateSwissTimingArchiveConfiguration(SwissTimingArchiveConfigurationWithSecurityDTO dto)
|
||||
throws UnauthorizedException, Exception;
|
||||
|
||||
void deleteSwissTimingArchiveConfiguration(SwissTimingArchiveConfigurationWithSecurityDTO dto)
|
||||
throws UnauthorizedException, Exception;
|
||||
|
||||
void createCourseAreas(UUID eventId, String[] courseAreaNames) throws UnauthorizedException;
|
||||
|
||||
@@ -1125,8 +1142,6 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS
|
||||
*/
|
||||
String openRegattaRegistrationQrCode(String url) throws UnauthorizedException;
|
||||
|
||||
void setDefaultTenantForCurrentServer(String tennant) throws UnauthorizedException;
|
||||
|
||||
List<String> getPossibleTennants() throws UnauthorizedException;
|
||||
|
||||
void updateGroupOwnerForEventHierarchy(UUID eventId,
|
||||
@@ -1159,4 +1174,10 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS
|
||||
*/
|
||||
CompetitorDTO getCompetitor(UUID competitorId, String leaderboardName,
|
||||
String regattaRegistrationLinkSecret);
|
||||
|
||||
boolean existsSwissTimingConfigurationForCurrentUser(String jsonUrl) throws Exception, UnauthorizedException;
|
||||
|
||||
boolean existsSwissTimingArchiveConfigurationForCurrentUser(String jsonUrl) throws Exception, UnauthorizedException;
|
||||
|
||||
boolean existsTracTracConfigurationForCurrentUser(String jsonUrl) throws Exception, UnauthorizedException;
|
||||
}
|
||||
+43
-19
@@ -9,6 +9,8 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.shiro.authz.AuthorizationException;
|
||||
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.sap.sailing.domain.base.Fleet;
|
||||
import com.sap.sailing.domain.base.RaceColumn;
|
||||
@@ -66,7 +68,6 @@ import com.sap.sailing.gwt.ui.shared.DeviceConfigurationDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.DeviceConfigurationDTO.RegattaConfigurationDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.DeviceConfigurationWithSecurityDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.DeviceMappingDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.EventBaseDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.EventDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.GPSFixDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.GPSFixDTOWithSpeedWindTackAndLegType;
|
||||
@@ -95,12 +96,12 @@ import com.sap.sailing.gwt.ui.shared.SimulatorResultsDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SliceRacePreperationDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTOWithSecurity;
|
||||
import com.sap.sailing.gwt.ui.shared.SwissTimingArchiveConfigurationDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SwissTimingConfigurationDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SwissTimingArchiveConfigurationWithSecurityDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SwissTimingConfigurationWithSecurityDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SwissTimingEventRecordDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SwissTimingRaceRecordDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SwissTimingReplayRaceDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.TracTracConfigurationDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.TracTracConfigurationWithSecurityDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.TracTracRaceRecordDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.TrackFileImportDeviceIdentifierDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.TypedDeviceMappingDTO;
|
||||
@@ -181,11 +182,17 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn
|
||||
boolean trackWind, boolean correctWindByDeclination, boolean useInternalMarkPassingAlgorithm,
|
||||
AsyncCallback<Void> asyncCallback);
|
||||
|
||||
void getPreviousTracTracConfigurations(AsyncCallback<List<TracTracConfigurationDTO>> callback);
|
||||
void getPreviousTracTracConfigurations(AsyncCallback<List<TracTracConfigurationWithSecurityDTO>> callback);
|
||||
|
||||
void storeTracTracConfiguration(String name, String jsonURL, String liveDataURI, String storedDataURI,
|
||||
void createTracTracConfiguration(String name, String jsonURL, String liveDataURI, String storedDataURI,
|
||||
String courseDesignUpdateURI, String tracTracUsername, String tracTracPassword, AsyncCallback<Void> callback);
|
||||
|
||||
void deleteTracTracConfiguration(TracTracConfigurationWithSecurityDTO tracTracConfiguration,
|
||||
AsyncCallback<Void> callback);
|
||||
|
||||
void updateTracTracConfiguration(TracTracConfigurationWithSecurityDTO tracTracConfiguration,
|
||||
AsyncCallback<Void> callback);
|
||||
|
||||
void stopTrackingRaces(Iterable<RegattaAndRaceIdentifier> racesToStopTracking, AsyncCallback<Void> asyncCallback);
|
||||
|
||||
/**
|
||||
@@ -357,13 +364,19 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn
|
||||
void updateRacesDelayToLive(List<RegattaAndRaceIdentifier> regattaAndRaceIdentifiers, long delayToLiveInMs,
|
||||
AsyncCallback<Void> callback);
|
||||
|
||||
void getPreviousSwissTimingConfigurations(AsyncCallback<List<SwissTimingConfigurationDTO>> asyncCallback);
|
||||
void getPreviousSwissTimingConfigurations(AsyncCallback<List<SwissTimingConfigurationWithSecurityDTO>> asyncCallback);
|
||||
|
||||
void getRacesOfSwissTimingEvent(String eventJsonUrl, AsyncCallback<SwissTimingEventRecordDTO> asyncCallback);
|
||||
|
||||
void storeSwissTimingConfiguration(String configName, String jsonURL, String hostname, Integer port,
|
||||
void createSwissTimingConfiguration(String configName, String jsonURL, String hostname, Integer port,
|
||||
String updateURL, String updateUsername, String updatePassword, AsyncCallback<Void> asyncCallback);
|
||||
|
||||
void updateSwissTimingConfiguration(SwissTimingConfigurationWithSecurityDTO configuration,
|
||||
AsyncCallback<Void> asyncCallback);
|
||||
|
||||
void deleteSwissTimingConfiguration(SwissTimingConfigurationWithSecurityDTO configuration,
|
||||
AsyncCallback<Void> asyncCallback);
|
||||
|
||||
void getCountryCodes(AsyncCallback<String[]> callback);
|
||||
|
||||
void getDouglasPoints(RegattaAndRaceIdentifier raceIdentifier, Map<CompetitorDTO, TimeRange> competitorTimeRanges,
|
||||
@@ -436,8 +449,6 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn
|
||||
|
||||
void getEvents(AsyncCallback<List<EventDTO>> callback);
|
||||
|
||||
void getPublicEventsOfAllSailingServers(AsyncCallback<List<EventBaseDTO>> callback);
|
||||
|
||||
/**
|
||||
* Renames the event with the name <code>oldName</code> to the <code>newName</code>.<br />
|
||||
* If there's no event with the name <code>oldName</code> or there's already a event with the name
|
||||
@@ -572,9 +583,16 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn
|
||||
void getOverallLeaderboardNamesContaining(String leaderboardName, AsyncCallback<List<String>> asyncCallback);
|
||||
|
||||
void getPreviousSwissTimingArchiveConfigurations(
|
||||
AsyncCallback<List<SwissTimingArchiveConfigurationDTO>> asyncCallback);
|
||||
AsyncCallback<List<SwissTimingArchiveConfigurationWithSecurityDTO>> asyncCallback);
|
||||
|
||||
void storeSwissTimingArchiveConfiguration(String swissTimingUrl, AsyncCallback<Void> asyncCallback);
|
||||
void createSwissTimingArchiveConfiguration(String jsonUrl,
|
||||
AsyncCallback<Void> asyncCallback);
|
||||
|
||||
void updateSwissTimingArchiveConfiguration(SwissTimingArchiveConfigurationWithSecurityDTO dto,
|
||||
AsyncCallback<Void> asyncCallback);
|
||||
|
||||
void deleteSwissTimingArchiveConfiguration(SwissTimingArchiveConfigurationWithSecurityDTO dto,
|
||||
AsyncCallback<Void> asyncCallback);
|
||||
|
||||
void updateRegatta(RegattaIdentifier regattaIdentifier, Date startDate, Date endDate, UUID defaultCourseAreaUuid,
|
||||
RegattaConfigurationDTO regattaConfiguration, Double buoyZoneRadiusInHullLengths,
|
||||
@@ -1022,6 +1040,13 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn
|
||||
void getAvailableDetailTypesForLeaderboard(String leaderboardName, RegattaAndRaceIdentifier raceOrNull,
|
||||
AsyncCallback<Iterable<DetailType>> asyncCallback);
|
||||
|
||||
/**
|
||||
* Checks whether the user may cut the race identified by {@code radeIdentifier} into multiple races. For this, it
|
||||
* has to be found and it has to be a "smartphone-tracked" race with a valid start-of-tracking time. If not,
|
||||
* {@code false} will be returned. If the user it not <em>permitted</em> to slice the race, e.g., because no
|
||||
* permission has been granted to modify the leaderboard or regatta, an {@link AuthorizationException} will be
|
||||
* thrown.
|
||||
*/
|
||||
void canSliceRace(RegattaAndRaceIdentifier raceIdentifier, AsyncCallback<Boolean> callback);
|
||||
|
||||
void sliceRace(RegattaAndRaceIdentifier raceIdentifier, String newRaceColumnName, TimePoint sliceFrom, TimePoint sliceTo,
|
||||
@@ -1060,13 +1085,6 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn
|
||||
*/
|
||||
void openRegattaRegistrationQrCode(String url, AsyncCallback<String> asyncCallback);
|
||||
|
||||
/**
|
||||
* Sets the tenant that is used for CREATE operations done on this server
|
||||
*
|
||||
* @param tennant
|
||||
*/
|
||||
void setDefaultTenantForCurrentServer(String tennant, AsyncCallback<Void> asyncCallback);
|
||||
|
||||
/**
|
||||
* gets a (possibly imcomplete) list of available tennants to choose from.
|
||||
*/
|
||||
@@ -1105,4 +1123,10 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn
|
||||
*/
|
||||
void getCompetitor(UUID competitorId, String leaderboardName, String regattaRegistrationLinkSecret,
|
||||
AsyncCallback<CompetitorDTO> asyncCallback);
|
||||
|
||||
void existsSwissTimingConfigurationForCurrentUser(String jsonUrl, AsyncCallback<Boolean> callback);
|
||||
|
||||
void existsSwissTimingArchiveConfigurationForCurrentUser(String jsonUrl, AsyncCallback<Boolean> callback);
|
||||
|
||||
void existsTracTracConfigurationForCurrentUser(String jsonUrl, AsyncCallback<Boolean> callback);
|
||||
}
|
||||
+15
@@ -2243,4 +2243,19 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages,
|
||||
String invalidState();
|
||||
String doYouReallyWantToRemoveDeviceConfiguration(String name);
|
||||
String errorFetchingSimulationData(String message);
|
||||
String addTracTracConnection();
|
||||
String editTracTracConnection();
|
||||
String filterTracTracConnections();
|
||||
String creatorName();
|
||||
String editSwissTimingAchivedConnection();
|
||||
String addSwissTimingAchivedConnection();
|
||||
String filterSwissTimingAchivedConnections();
|
||||
|
||||
String editSwissTimingConnections();
|
||||
|
||||
String filterSwissTimingConnections();
|
||||
|
||||
String updateURL();
|
||||
|
||||
String addSwissTimingConnection();
|
||||
}
|
||||
+12
-1
@@ -2246,4 +2246,15 @@ doYouReallyWantToRemoveDeviceConfiguration=Do you really want to remove device c
|
||||
errorFetchingSimulationData=An Error occured while fetching simulation data: {0}
|
||||
usernameAndPasswordMustBothBeSet=Username and password must both be filled or empty
|
||||
explainUserName=Username to use for authentification on the master
|
||||
explainPassword=Password to use for authentification on the master
|
||||
explainPassword=Password to use for authentification on the master
|
||||
addTracTracConnection=Add TracTrac Connection
|
||||
editTracTracConnection=Edit TracTrac Connection
|
||||
filterTracTracConnections=Filter TracTrac Connections
|
||||
creatorName=Creator Name
|
||||
addSwissTimingAchivedConnection=Add SwissTimingArchived Connection
|
||||
editSwissTimingAchivedConnection=Edit SwissTimingArchived Connection
|
||||
filterSwissTimingAchivedConnections=Filter SwissTimingArchived Connections
|
||||
editSwissTimingConnections = Edit SwissTiming Connection
|
||||
filterSwissTimingConnections=Filter SwissTiming Connections
|
||||
addSwissTimingConnection=Add SwissTiming Connection
|
||||
updateURL=Update URL
|
||||
+12
-1
@@ -2238,4 +2238,15 @@ doYouReallyWantToRemoveDeviceConfiguration=Möchten Sie die Gerätekonfiguration
|
||||
errorFetchingSimulationData=Ein Fehler ist beim Abrufen der Simulationsdaten aufgetreten: {0}
|
||||
usernameAndPasswordMustBothBeSet=Username und Passwort müssen beide entweder gesetzt oder leer sein.
|
||||
explainUserName=Der Benutzername der zur Authentifizierung auf dem Master eingesetzt wird
|
||||
explainPassword=Das Password das zur Authentifizierung auf dem Master eingesetzt wird
|
||||
explainPassword=Das Password das zur Authentifizierung auf dem Master eingesetzt wird
|
||||
addTracTracConnection=TracTrac Verbindung hinzufügen
|
||||
editTracTracConnection=TracTrac Verbindung bearbeiten
|
||||
filterTracTracConnections=TracTrac Verbindungen filtern
|
||||
creatorName=Name des Erstellers
|
||||
addSwissTimingAchivedConnection=SwissTimingArchived Verbindung hinzufügen
|
||||
editSwissTimingAchivedConnection=SwissTimingArchived Verbindung bearbeiten
|
||||
filterSwissTimingAchivedConnections=SwissTimingArchived Verbindungen filtern
|
||||
editSwissTimingConnections = SwissTiming Verbindung bearbeiten
|
||||
filterSwissTimingConnections=SwissTiming Verbindungen filtern
|
||||
addSwissTimingConnection=SwissTiming Verbindung hinzufügen
|
||||
updateURL=Update URL
|
||||
+18
-7
@@ -854,17 +854,28 @@ public abstract class LeaderboardPanel<LS extends LeaderboardSettings> extends A
|
||||
// an overflow to the next column (see https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=3537)
|
||||
setCellStyleNames(style.getTableresources().cellTableStyle().cellTableSailIdColumn());
|
||||
}
|
||||
|
||||
/**
|
||||
* Depending on the {@link LeaderboardDTO LeaderboardDTO's}
|
||||
* {@link AbstractLeaderboardDTO#canBoatsOfCompetitorsChangePerRace canBoatsOfCompetitorsChangePerRace} flag
|
||||
* there is a different precedence of showing either the sail ID (no changing boats) or the competitor short
|
||||
* name (changing boats). This method handles the resolution of the text to show for a competitor in this column.
|
||||
*/
|
||||
private String getRealTextToShow(CompetitorDTO competitor) {
|
||||
boolean preferSailId = !getLeaderboard().canBoatsOfCompetitorsChangePerRace;
|
||||
return competitor.getShortInfo(preferSailId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InvertibleComparator<T> getComparator() {
|
||||
return new InvertibleComparatorAdapter<T>() {
|
||||
@Override
|
||||
public int compare(T o1, T o2) {
|
||||
return competitorFetcher.getCompetitor(o1).getShortInfo() == null
|
||||
? competitorFetcher.getCompetitor(o2).getShortInfo() == null ? 0 : -1
|
||||
: competitorFetcher.getCompetitor(o2).getShortInfo() == null ? 1
|
||||
: Collator.getInstance().compare(competitorFetcher.getCompetitor(o1).getShortInfo(),
|
||||
competitorFetcher.getCompetitor(o2).getShortInfo());
|
||||
final String competitor1ShortInfo = getRealTextToShow(competitorFetcher.getCompetitor(o1));
|
||||
final String competitor2ShortInfo = getRealTextToShow(competitorFetcher.getCompetitor(o2));
|
||||
return competitor1ShortInfo == null ? competitor2ShortInfo == null ? 0 : -1
|
||||
: competitor2ShortInfo == null ? 1
|
||||
: Collator.getInstance().compare(competitor1ShortInfo, competitor2ShortInfo);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -879,12 +890,12 @@ public abstract class LeaderboardPanel<LS extends LeaderboardSettings> extends A
|
||||
public void render(Context context, T object, SafeHtmlBuilder sb) {
|
||||
final CompetitorDTO competitor = competitorFetcher.getCompetitor(object);
|
||||
LeaderboardPanel.this.renderCompetitorText(competitor, isShowCompetitorShortName(),
|
||||
!isShowCompetitorFullName(), sb, builder -> builder.appendEscaped(competitor.getShortInfo()));
|
||||
!isShowCompetitorFullName(), sb, builder -> builder.appendEscaped(getRealTextToShow(competitor)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue(T object) {
|
||||
return competitorFetcher.getCompetitor(object).getShortInfo();
|
||||
return getRealTextToShow(competitorFetcher.getCompetitor(object));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Regular → Executable
+14
-2
@@ -43,6 +43,7 @@ import com.google.gwt.user.datepicker.client.DateBox;
|
||||
import com.google.gwt.view.client.ListDataProvider;
|
||||
import com.sap.sailing.domain.common.DetailType;
|
||||
import com.sap.sailing.domain.common.MaxPointsReason;
|
||||
import com.sap.sailing.domain.common.dto.AbstractLeaderboardDTO;
|
||||
import com.sap.sailing.domain.common.dto.CompetitorDTO;
|
||||
import com.sap.sailing.domain.common.dto.LeaderboardDTO;
|
||||
import com.sap.sailing.domain.common.dto.LeaderboardEntryDTO;
|
||||
@@ -133,12 +134,23 @@ public class EditableLeaderboardPanel extends MultiRaceLeaderboardPanel {
|
||||
super(new TextCell(), SortingOrder.ASCENDING, EditableLeaderboardPanel.this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Depending on the {@link LeaderboardDTO LeaderboardDTO's}
|
||||
* {@link AbstractLeaderboardDTO#canBoatsOfCompetitorsChangePerRace canBoatsOfCompetitorsChangePerRace} flag
|
||||
* there is a different precedence of showing either the sail ID (no changing boats) or the competitor short
|
||||
* name (changing boats). This method handles the resolution of the text to show for a competitor in this column.
|
||||
*/
|
||||
private String getRealTextToShow(CompetitorDTO competitor) {
|
||||
boolean preferSailId = !getLeaderboard().canBoatsOfCompetitorsChangePerRace;
|
||||
return competitor.getShortInfo(preferSailId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InvertibleComparator<CompetitorDTO> getComparator() {
|
||||
return new InvertibleComparatorAdapter<CompetitorDTO>() {
|
||||
@Override
|
||||
public int compare(CompetitorDTO o1, CompetitorDTO o2) {
|
||||
return Collator.getInstance().compare(o1.getShortInfo(), o2.getShortInfo());
|
||||
return Collator.getInstance().compare(getRealTextToShow(o1), getRealTextToShow(o2));
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -161,7 +173,7 @@ public class EditableLeaderboardPanel extends MultiRaceLeaderboardPanel {
|
||||
sb.append(FlagImageRenderer.image(flagImageResource.getSafeUri().asString()));
|
||||
sb.appendHtmlConstant(" ");
|
||||
}
|
||||
sb.appendEscaped(object.getShortInfo());
|
||||
sb.appendEscaped(getRealTextToShow(object));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+175
-80
@@ -454,12 +454,12 @@ import com.sap.sailing.gwt.ui.shared.SliceRacePreperationDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SpeedWithBearingDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTOWithSecurity;
|
||||
import com.sap.sailing.gwt.ui.shared.SwissTimingArchiveConfigurationDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SwissTimingConfigurationDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SwissTimingArchiveConfigurationWithSecurityDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SwissTimingConfigurationWithSecurityDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SwissTimingEventRecordDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SwissTimingRaceRecordDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SwissTimingReplayRaceDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.TracTracConfigurationDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.TracTracConfigurationWithSecurityDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.TracTracRaceRecordDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.TrackFileImportDeviceIdentifierDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.TypedDeviceMappingDTO;
|
||||
@@ -1411,25 +1411,58 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TracTracConfigurationDTO> getPreviousTracTracConfigurations() throws Exception {
|
||||
public List<TracTracConfigurationWithSecurityDTO> getPreviousTracTracConfigurations() throws Exception {
|
||||
final Iterable<TracTracConfiguration> configs = tractracDomainObjectFactory.getTracTracConfigurations();
|
||||
return getSecurityService().mapAndFilterByReadPermissionForCurrentUser(SecuredDomainType.TRACTRAC_ACCOUNT,
|
||||
configs,
|
||||
ttConfig -> new TracTracConfigurationDTO(ttConfig.getName(), ttConfig.getJSONURL().toString(),
|
||||
ttConfig -> {
|
||||
TracTracConfigurationWithSecurityDTO config = new TracTracConfigurationWithSecurityDTO(
|
||||
ttConfig.getName(),
|
||||
ttConfig.getJSONURL().toString(),
|
||||
ttConfig.getLiveDataURI().toString(), ttConfig.getStoredDataURI().toString(),
|
||||
ttConfig.getCourseDesignUpdateURI().toString(), ttConfig.getTracTracUsername().toString(),
|
||||
ttConfig.getTracTracPassword().toString()));
|
||||
ttConfig.getTracTracPassword().toString(), ttConfig.getCreatorName());
|
||||
SecurityDTOUtil.addSecurityInformation(getSecurityService(), config, config.getIdentifier());
|
||||
return config;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createTracTracConfiguration(String name, String jsonURL, String liveDataURI, String storedDataURI,
|
||||
String courseDesignUpdateURI, String tracTracUsername, String tracTracPassword) throws Exception {
|
||||
if (existsTracTracConfigurationForCurrentUser(jsonURL)) {
|
||||
throw new RuntimeException("A configuration for the current user with this json URL already exists.");
|
||||
}
|
||||
final String currentUserName = getSecurityService().getCurrentUser().getName();
|
||||
final TypeRelativeObjectIdentifier identifier = TracTracConfiguration.getTypeRelativeObjectIdentifier(jsonURL, currentUserName);
|
||||
getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
|
||||
SecuredDomainType.TRACTRAC_ACCOUNT,
|
||||
identifier, name,
|
||||
() -> tractracMongoObjectFactory.createTracTracConfiguration(
|
||||
getTracTracAdapter().createTracTracConfiguration(currentUserName, name, jsonURL, liveDataURI,
|
||||
storedDataURI,
|
||||
courseDesignUpdateURI, tracTracUsername, tracTracPassword)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeTracTracConfiguration(String name, String jsonURL, String liveDataURI, String storedDataURI,
|
||||
String courseDesignUpdateURI, String tracTracUsername, String tracTracPassword) throws Exception {
|
||||
public void deleteTracTracConfiguration(TracTracConfigurationWithSecurityDTO tracTracConfiguration) {
|
||||
getSecurityService().checkCurrentUserDeletePermission(tracTracConfiguration);
|
||||
getSecurityService().checkPermissionAndDeleteOwnershipForObjectRemoval(tracTracConfiguration,
|
||||
() ->
|
||||
tractracMongoObjectFactory.deleteTracTracConfiguration(tracTracConfiguration.getCreatorName(),
|
||||
tracTracConfiguration.getJsonUrl()));
|
||||
}
|
||||
|
||||
getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
|
||||
SecuredDomainType.TRACTRAC_ACCOUNT, TracTracConfiguration.getTypeRelativeObjectIdentifier(jsonURL), name,
|
||||
() -> tractracMongoObjectFactory.storeTracTracConfiguration(
|
||||
getTracTracAdapter().createTracTracConfiguration(name, jsonURL, liveDataURI, storedDataURI,
|
||||
courseDesignUpdateURI, tracTracUsername, tracTracPassword)));
|
||||
@Override
|
||||
public void updateTracTracConfiguration(TracTracConfigurationWithSecurityDTO tracTracConfiguration)
|
||||
throws Exception {
|
||||
getSecurityService().checkCurrentUserUpdatePermission(tracTracConfiguration);
|
||||
tractracMongoObjectFactory.updateTracTracConfiguration(
|
||||
getTracTracAdapter().createTracTracConfiguration(tracTracConfiguration.getCreatorName(),
|
||||
tracTracConfiguration.getName(), tracTracConfiguration.getJsonUrl(),
|
||||
tracTracConfiguration.getLiveDataURI(), tracTracConfiguration.getStoredDataURI(),
|
||||
tracTracConfiguration.getCourseDesignUpdateURI(), tracTracConfiguration.getTracTracUsername(),
|
||||
tracTracConfiguration.getTracTracPassword()));
|
||||
}
|
||||
|
||||
private RaceDefinition getRaceByName(Regatta regatta, String raceName) {
|
||||
@@ -3144,12 +3177,96 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SwissTimingConfigurationDTO> getPreviousSwissTimingConfigurations() {
|
||||
public boolean existsSwissTimingConfigurationForCurrentUser(String jsonUrl)
|
||||
throws Exception, UnauthorizedException {
|
||||
boolean found = false;
|
||||
final String currentUserName = getSecurityService().getCurrentUser().getName();
|
||||
for (final SwissTimingConfigurationWithSecurityDTO dto : getPreviousSwissTimingConfigurations()) {
|
||||
if (dto.getJsonUrl().equals(jsonUrl) && currentUserName.equals(dto.getCreatorName())) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean existsSwissTimingArchiveConfigurationForCurrentUser(String jsonUrl)
|
||||
throws Exception, UnauthorizedException {
|
||||
boolean found = false;
|
||||
final String currentUserName = getSecurityService().getCurrentUser().getName();
|
||||
for (final SwissTimingArchiveConfigurationWithSecurityDTO dto : getPreviousSwissTimingArchiveConfigurations()) {
|
||||
if (dto.getJsonUrl().equals(jsonUrl) && currentUserName.equals(dto.getCreatorName())) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean existsTracTracConfigurationForCurrentUser(String jsonUrl) throws Exception, UnauthorizedException {
|
||||
boolean found = false;
|
||||
final String currentUserName = getSecurityService().getCurrentUser().getName();
|
||||
for (final TracTracConfigurationWithSecurityDTO dto : getPreviousTracTracConfigurations()) {
|
||||
if (dto.getJsonUrl().equals(jsonUrl) && currentUserName.equals(dto.getCreatorName())) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SwissTimingConfigurationWithSecurityDTO> getPreviousSwissTimingConfigurations() {
|
||||
Iterable<SwissTimingConfiguration> configs = swissTimingAdapterPersistence.getSwissTimingConfigurations();
|
||||
return getSecurityService().mapAndFilterByReadPermissionForCurrentUser(SecuredDomainType.SWISS_TIMING_ACCOUNT, configs,
|
||||
stConfig -> new SwissTimingConfigurationDTO(stConfig.getName(), stConfig.getJsonURL(),
|
||||
stConfig -> {
|
||||
final SwissTimingConfigurationWithSecurityDTO config = new SwissTimingConfigurationWithSecurityDTO(
|
||||
stConfig.getName(), stConfig.getJsonURL(),
|
||||
stConfig.getHostname(), stConfig.getPort(), stConfig.getUpdateURL(),
|
||||
stConfig.getUpdateUsername(), stConfig.getUpdatePassword()));
|
||||
stConfig.getUpdateUsername(), stConfig.getUpdatePassword(), stConfig.getCreatorName());
|
||||
SecurityDTOUtil.addSecurityInformation(getSecurityService(), config, config.getIdentifier());
|
||||
return config;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createSwissTimingConfiguration(String configName, String jsonURL, String hostname, Integer port,
|
||||
String updateURL, String updateUsername, String updatePassword) throws Exception {
|
||||
if (!jsonURL.equalsIgnoreCase("test")) {
|
||||
if (existsSwissTimingConfigurationForCurrentUser(jsonURL)) {
|
||||
throw new RuntimeException("A Configuration for the current user with this json URL already exists.");
|
||||
}
|
||||
final String currentUserName = getSecurityService().getCurrentUser().getName();
|
||||
final TypeRelativeObjectIdentifier identifier = SwissTimingConfiguration.getTypeRelativeObjectIdentifier(jsonURL, currentUserName);
|
||||
getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
|
||||
SecuredDomainType.SWISS_TIMING_ACCOUNT,
|
||||
identifier, configName,
|
||||
() -> swissTimingAdapterPersistence
|
||||
.createSwissTimingConfiguration(
|
||||
swissTimingFactory.createSwissTimingConfiguration(configName,
|
||||
jsonURL, hostname, port, updateURL, updateUsername, updatePassword,
|
||||
currentUserName)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteSwissTimingConfiguration(SwissTimingConfigurationWithSecurityDTO configuration) {
|
||||
getSecurityService().checkCurrentUserDeletePermission(configuration);
|
||||
getSecurityService().checkPermissionAndDeleteOwnershipForObjectRemoval(configuration,
|
||||
() -> swissTimingAdapterPersistence.deleteSwissTimingConfiguration(configuration.getCreatorName(),
|
||||
configuration.getJsonUrl()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSwissTimingConfiguration(SwissTimingConfigurationWithSecurityDTO configuration)
|
||||
throws Exception {
|
||||
getSecurityService().checkCurrentUserUpdatePermission(configuration);
|
||||
swissTimingAdapterPersistence.updateSwissTimingConfiguration(swissTimingFactory.createSwissTimingConfiguration(
|
||||
configuration.getName(), configuration.getJsonUrl(), configuration.getHostname(),
|
||||
configuration.getPort(), configuration.getUpdateURL(), configuration.getUpdateUsername(),
|
||||
configuration.getUpdatePassword(), configuration.getCreatorName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -3183,19 +3300,6 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeSwissTimingConfiguration(String configName, String jsonURL, String hostname, Integer port,
|
||||
String updateURL, String updateUsername, String updatePassword) throws Exception {
|
||||
if (!jsonURL.equalsIgnoreCase("test")) {
|
||||
getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
|
||||
SecuredDomainType.SWISS_TIMING_ACCOUNT, SwissTimingConfiguration.getTypeRelativeObjectIdentifier(jsonURL),
|
||||
configName,
|
||||
() -> swissTimingAdapterPersistence
|
||||
.storeSwissTimingConfiguration(swissTimingFactory.createSwissTimingConfiguration(configName,
|
||||
jsonURL, hostname, port, updateURL, updateUsername, updatePassword)));
|
||||
}
|
||||
}
|
||||
|
||||
private RaceLogStore getRaceLogStore() {
|
||||
return MongoRaceLogStoreFactory.INSTANCE.getMongoRaceLogStore(mongoObjectFactory,
|
||||
@@ -4237,32 +4341,6 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EventBaseDTO> getPublicEventsOfAllSailingServers() throws MalformedURLException {
|
||||
List<EventBaseDTO> result = new ArrayList<>();
|
||||
for (EventDTO localEvent : getEvents()) {
|
||||
if (localEvent.isPublic) {
|
||||
result.add(localEvent);
|
||||
}
|
||||
}
|
||||
for (Entry<RemoteSailingServerReference, com.sap.sse.common.Util.Pair<Iterable<EventBase>, Exception>> serverRefAndEventsOrException :
|
||||
getService().getPublicEventsOfAllSailingServers().entrySet()) {
|
||||
final com.sap.sse.common.Util.Pair<Iterable<EventBase>, Exception> eventsOrException = serverRefAndEventsOrException.getValue();
|
||||
final RemoteSailingServerReference serverRef = serverRefAndEventsOrException.getKey();
|
||||
final Iterable<EventBase> remoteEvents = eventsOrException.getA();
|
||||
String baseURLFromServerReference = getBaseURL(serverRef.getURL()).toString();
|
||||
if (remoteEvents != null) {
|
||||
for (EventBase remoteEvent : remoteEvents) {
|
||||
EventBaseDTO remoteEventDTO = convertToEventDTO(remoteEvent);
|
||||
remoteEventDTO.setBaseURL(remoteEvent.getBaseURL() == null ? baseURLFromServerReference : remoteEvent.getBaseURL().toString());
|
||||
remoteEventDTO.setIsOnRemoteServer(true);
|
||||
result.add(remoteEventDTO);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the base URL (protocol, host and port parts) used for the currently executing servlet request. Defaults
|
||||
* to <code>http://sapsailing.com</code>.
|
||||
@@ -5183,20 +5261,50 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SwissTimingArchiveConfigurationDTO> getPreviousSwissTimingArchiveConfigurations() {
|
||||
public List<SwissTimingArchiveConfigurationWithSecurityDTO> getPreviousSwissTimingArchiveConfigurations() {
|
||||
Iterable<SwissTimingArchiveConfiguration> configs = swissTimingAdapterPersistence
|
||||
.getSwissTimingArchiveConfigurations();
|
||||
return getSecurityService().mapAndFilterByReadPermissionForCurrentUser(
|
||||
SecuredDomainType.SWISS_TIMING_ARCHIVE_ACCOUNT, configs,
|
||||
stArchiveConfig -> new SwissTimingArchiveConfigurationDTO(stArchiveConfig.getJsonURL()));
|
||||
stArchiveConfig -> {
|
||||
SwissTimingArchiveConfigurationWithSecurityDTO config = new SwissTimingArchiveConfigurationWithSecurityDTO(
|
||||
stArchiveConfig.getJsonURL(), stArchiveConfig.getCreatorName());
|
||||
SecurityDTOUtil.addSecurityInformation(getSecurityService(), config, config.getIdentifier());
|
||||
return config;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeSwissTimingArchiveConfiguration(String swissTimingJsonUrl) throws Exception {
|
||||
public void createSwissTimingArchiveConfiguration(final String jsonURL)
|
||||
throws Exception {
|
||||
if (existsSwissTimingArchiveConfigurationForCurrentUser(jsonURL)) {
|
||||
throw new RuntimeException("A configuration for the current user with this json URL already exists.");
|
||||
}
|
||||
final String currentUserName = getSecurityService().getCurrentUser().getName();
|
||||
final TypeRelativeObjectIdentifier identifier = SwissTimingArchiveConfiguration
|
||||
.getTypeRelativeObjectIdentifier(jsonURL, currentUserName);
|
||||
getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
|
||||
SecuredDomainType.SWISS_TIMING_ACCOUNT, SwissTimingArchiveConfiguration.getTypeRelativeObjectIdentifier(swissTimingJsonUrl),
|
||||
swissTimingJsonUrl, () -> swissTimingAdapterPersistence.storeSwissTimingArchiveConfiguration(
|
||||
swissTimingFactory.createSwissTimingArchiveConfiguration(swissTimingJsonUrl)));
|
||||
SecuredDomainType.SWISS_TIMING_ARCHIVE_ACCOUNT,
|
||||
identifier, identifier.toString(),
|
||||
() -> swissTimingAdapterPersistence.createSwissTimingArchiveConfiguration(
|
||||
swissTimingFactory.createSwissTimingArchiveConfiguration(jsonURL,
|
||||
currentUserName)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSwissTimingArchiveConfiguration(SwissTimingArchiveConfigurationWithSecurityDTO dto)
|
||||
throws Exception {
|
||||
getSecurityService().checkCurrentUserUpdatePermission(dto);
|
||||
swissTimingAdapterPersistence.updateSwissTimingArchiveConfiguration(
|
||||
swissTimingFactory.createSwissTimingArchiveConfiguration(dto.getJsonUrl(), dto.getCreatorName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteSwissTimingArchiveConfiguration(SwissTimingArchiveConfigurationWithSecurityDTO dto)
|
||||
throws Exception {
|
||||
getSecurityService().checkPermissionAndDeleteOwnershipForObjectRemoval(dto.getIdentifier(),
|
||||
() -> swissTimingAdapterPersistence.deleteSwissTimingArchiveConfiguration(swissTimingFactory
|
||||
.createSwissTimingArchiveConfiguration(dto.getJsonUrl(), dto.getCreatorName())));
|
||||
}
|
||||
|
||||
protected com.sap.sailing.domain.base.DomainFactory getBaseDomainFactory() {
|
||||
@@ -6366,7 +6474,8 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet
|
||||
final com.sap.sailing.domain.igtimiadapter.User user = igtimiAccount.getUser();
|
||||
final String email = user.getEmail();
|
||||
final String name = user.getFirstName() + " " + user.getSurname();
|
||||
final AccountWithSecurityDTO securedAccount = new AccountWithSecurityDTO(email, name);
|
||||
final AccountWithSecurityDTO securedAccount = new AccountWithSecurityDTO(email, name,
|
||||
igtimiAccount.getCreatorName());
|
||||
SecurityDTOUtil.addSecurityInformation(getSecurityService(), securedAccount, igtimiAccount.getIdentifier());
|
||||
return securedAccount;
|
||||
}
|
||||
@@ -6393,10 +6502,12 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet
|
||||
final Account existingAccount = getIgtimiConnectionFactory().getExistingAccountByEmail(eMailAddress);
|
||||
final Account account;
|
||||
if (existingAccount == null) {
|
||||
final String creatorName = getSecurityService().getCurrentUser().getName();
|
||||
account = getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(
|
||||
SecuredDomainType.IGTIMI_ACCOUNT, Account.getTypeRelativeObjectIdentifier(eMailAddress),
|
||||
SecuredDomainType.IGTIMI_ACCOUNT,
|
||||
Account.getTypeRelativeObjectIdentifier(eMailAddress, creatorName),
|
||||
eMailAddress,
|
||||
() -> getIgtimiConnectionFactory().createAccountToAccessUserData(eMailAddress, password));
|
||||
() -> getIgtimiConnectionFactory().createAccountToAccessUserData(creatorName, eMailAddress, password));
|
||||
} else {
|
||||
logger.warning("Igtimi account "+eMailAddress+" already exists.");
|
||||
account = null; // account with that e-mail already exists
|
||||
@@ -9015,22 +9126,6 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefaultTenantForCurrentServer(String tennant) {
|
||||
User user = getSecurityService().getCurrentUser();
|
||||
if (user != null) {
|
||||
if (tennant == null) {
|
||||
user.getDefaultTenantMap().remove(ServerInfo.getName());
|
||||
} else {
|
||||
UserGroup userGroupCandidate = getSecurityService().getUserGroupByName(tennant);
|
||||
// FIXME allow admins to pose as any tenant?
|
||||
if (Util.contains(user.getUserGroups(), userGroupCandidate)) {
|
||||
user.getDefaultTenantMap().put(ServerInfo.getName(), userGroupCandidate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getPossibleTennants() {
|
||||
// FIXME this is most likely greatly oversimplified and needs to be improved
|
||||
|
||||
+12
-5
@@ -15,10 +15,12 @@ public class AccountWithSecurityDTO implements SecuredDTO {
|
||||
|
||||
private String email;
|
||||
private String name;
|
||||
private String creatorName;
|
||||
|
||||
public AccountWithSecurityDTO(String email, String name) {
|
||||
public AccountWithSecurityDTO(String email, String name, String creatorName) {
|
||||
this.email = email;
|
||||
this.name = name;
|
||||
this.creatorName = creatorName;
|
||||
}
|
||||
|
||||
public AccountWithSecurityDTO() {
|
||||
@@ -36,6 +38,10 @@ public class AccountWithSecurityDTO implements SecuredDTO {
|
||||
return email;
|
||||
}
|
||||
|
||||
public String getCreatorName() {
|
||||
return creatorName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessControlListDTO getAccessControlList() {
|
||||
return securityInformation.getAccessControlList();
|
||||
@@ -66,13 +72,14 @@ public class AccountWithSecurityDTO implements SecuredDTO {
|
||||
return name;
|
||||
}
|
||||
|
||||
private TypeRelativeObjectIdentifier getTypeRelativeObjectIdentifier() {
|
||||
return creatorName == null ? new TypeRelativeObjectIdentifier(email)
|
||||
: new TypeRelativeObjectIdentifier(email, creatorName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QualifiedObjectIdentifier getIdentifier() {
|
||||
return getType().getQualifiedObjectIdentifier(getTypeRelativeObjectIdentifier());
|
||||
}
|
||||
|
||||
private TypeRelativeObjectIdentifier getTypeRelativeObjectIdentifier() {
|
||||
return new TypeRelativeObjectIdentifier(email);
|
||||
}
|
||||
|
||||
}
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
package com.sap.sailing.gwt.ui.shared;
|
||||
|
||||
import com.google.gwt.user.client.rpc.IsSerializable;
|
||||
|
||||
public class SwissTimingArchiveConfigurationDTO implements IsSerializable {
|
||||
private String jsonUrl;
|
||||
|
||||
SwissTimingArchiveConfigurationDTO() {}
|
||||
|
||||
public SwissTimingArchiveConfigurationDTO(String jsonUrl) {
|
||||
super();
|
||||
this.jsonUrl = jsonUrl;
|
||||
}
|
||||
|
||||
public String getJsonUrl() {
|
||||
return jsonUrl;
|
||||
}
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
package com.sap.sailing.gwt.ui.shared;
|
||||
|
||||
import com.google.gwt.user.client.rpc.IsSerializable;
|
||||
import com.sap.sailing.domain.common.security.SecuredDomainType;
|
||||
import com.sap.sse.security.shared.HasPermissions;
|
||||
import com.sap.sse.security.shared.QualifiedObjectIdentifier;
|
||||
import com.sap.sse.security.shared.TypeRelativeObjectIdentifier;
|
||||
import com.sap.sse.security.shared.dto.AccessControlListDTO;
|
||||
import com.sap.sse.security.shared.dto.OwnershipDTO;
|
||||
import com.sap.sse.security.shared.dto.SecuredDTO;
|
||||
import com.sap.sse.security.shared.dto.SecurityInformationDTO;
|
||||
|
||||
public class SwissTimingArchiveConfigurationWithSecurityDTO implements IsSerializable, SecuredDTO {
|
||||
private static final long serialVersionUID = 108023338445751985L;
|
||||
|
||||
private String jsonUrl;
|
||||
private String creatorName;
|
||||
private SecurityInformationDTO securityInformation = new SecurityInformationDTO();
|
||||
|
||||
public SwissTimingArchiveConfigurationWithSecurityDTO() {
|
||||
}
|
||||
|
||||
public SwissTimingArchiveConfigurationWithSecurityDTO(String jsonUrl, String creatorName) {
|
||||
super();
|
||||
this.jsonUrl = jsonUrl;
|
||||
this.creatorName = creatorName;
|
||||
}
|
||||
|
||||
public String getJsonUrl() {
|
||||
return jsonUrl;
|
||||
}
|
||||
|
||||
public String getCreatorName() {
|
||||
return creatorName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessControlListDTO getAccessControlList() {
|
||||
return securityInformation.getAccessControlList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OwnershipDTO getOwnership() {
|
||||
return securityInformation.getOwnership();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAccessControlList(AccessControlListDTO createAccessControlListDTO) {
|
||||
securityInformation.setAccessControlList(createAccessControlListDTO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOwnership(OwnershipDTO createOwnershipDTO) {
|
||||
securityInformation.setOwnership(createOwnershipDTO);
|
||||
}
|
||||
|
||||
public SecurityInformationDTO getSecurityInformation() {
|
||||
return securityInformation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return jsonUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HasPermissions getType() {
|
||||
return SecuredDomainType.SWISS_TIMING_ARCHIVE_ACCOUNT;
|
||||
}
|
||||
|
||||
private TypeRelativeObjectIdentifier getTypeRelativeObjectIdentifier() {
|
||||
return creatorName == null ? new TypeRelativeObjectIdentifier(jsonUrl)
|
||||
: new TypeRelativeObjectIdentifier(jsonUrl, creatorName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QualifiedObjectIdentifier getIdentifier() {
|
||||
return getType().getQualifiedObjectIdentifier(getTypeRelativeObjectIdentifier());
|
||||
}
|
||||
}
|
||||
-67
@@ -1,67 +0,0 @@
|
||||
package com.sap.sailing.gwt.ui.shared;
|
||||
|
||||
import com.google.gwt.user.client.rpc.IsSerializable;
|
||||
|
||||
public class SwissTimingConfigurationDTO implements IsSerializable {
|
||||
private String name;
|
||||
private String jsonURL;
|
||||
private String hostname;
|
||||
private Integer port;
|
||||
|
||||
/**
|
||||
* The URL to use for updates fed back to the SwissTiming server, such as changes of race timings
|
||||
* or course updates.
|
||||
*/
|
||||
private String updateURL;
|
||||
|
||||
/**
|
||||
* The username to use as part of the credentials for requests to the {@link #updateURL}.
|
||||
*/
|
||||
private String updateUsername;
|
||||
|
||||
/**
|
||||
* The password to use as part of the credentials for requests to the {@link #updateURL}.
|
||||
*/
|
||||
private String updatePassword;
|
||||
|
||||
public SwissTimingConfigurationDTO() {}
|
||||
|
||||
public SwissTimingConfigurationDTO(String name, String jsonURL, String hostname, Integer port, String updateURL, String updateUsername, String updatePassword) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.jsonURL = jsonURL;
|
||||
this.hostname = hostname;
|
||||
this.port = port;
|
||||
this.updateURL = updateURL;
|
||||
this.updateUsername = updateUsername;
|
||||
this.updatePassword = updatePassword;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getJsonURL() {
|
||||
return jsonURL;
|
||||
}
|
||||
|
||||
public String getHostname() {
|
||||
return hostname;
|
||||
}
|
||||
|
||||
public Integer getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public String getUpdateURL() {
|
||||
return updateURL;
|
||||
}
|
||||
|
||||
public String getUpdateUsername() {
|
||||
return updateUsername;
|
||||
}
|
||||
|
||||
public String getUpdatePassword() {
|
||||
return updatePassword;
|
||||
}
|
||||
}
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
package com.sap.sailing.gwt.ui.shared;
|
||||
|
||||
import com.google.gwt.user.client.rpc.IsSerializable;
|
||||
import com.sap.sailing.domain.common.security.SecuredDomainType;
|
||||
import com.sap.sse.security.shared.HasPermissions;
|
||||
import com.sap.sse.security.shared.QualifiedObjectIdentifier;
|
||||
import com.sap.sse.security.shared.TypeRelativeObjectIdentifier;
|
||||
import com.sap.sse.security.shared.dto.AccessControlListDTO;
|
||||
import com.sap.sse.security.shared.dto.OwnershipDTO;
|
||||
import com.sap.sse.security.shared.dto.SecuredDTO;
|
||||
import com.sap.sse.security.shared.dto.SecurityInformationDTO;
|
||||
|
||||
public class SwissTimingConfigurationWithSecurityDTO implements IsSerializable, SecuredDTO {
|
||||
private static final long serialVersionUID = 8896994399042048620L;
|
||||
|
||||
private SecurityInformationDTO securityInformation = new SecurityInformationDTO();
|
||||
|
||||
private String name;
|
||||
private String jsonUrl;
|
||||
private String hostname;
|
||||
private Integer port;
|
||||
private String creatorName;
|
||||
|
||||
/**
|
||||
* The URL to use for updates fed back to the SwissTiming server, such as changes of race timings
|
||||
* or course updates.
|
||||
*/
|
||||
private String updateURL;
|
||||
|
||||
/**
|
||||
* The username to use as part of the credentials for requests to the {@link #updateURL}.
|
||||
*/
|
||||
private String updateUsername;
|
||||
|
||||
/**
|
||||
* The password to use as part of the credentials for requests to the {@link #updateURL}.
|
||||
*/
|
||||
private String updatePassword;
|
||||
|
||||
public SwissTimingConfigurationWithSecurityDTO() {}
|
||||
|
||||
public SwissTimingConfigurationWithSecurityDTO(String name, String jsonUrl, String hostname, Integer port,
|
||||
String updateURL, String updateUsername, String updatePassword, String creatorName) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.jsonUrl = jsonUrl;
|
||||
this.hostname = hostname;
|
||||
this.port = port;
|
||||
this.updateURL = updateURL;
|
||||
this.updateUsername = updateUsername;
|
||||
this.updatePassword = updatePassword;
|
||||
this.creatorName = creatorName;
|
||||
}
|
||||
|
||||
public SwissTimingConfigurationWithSecurityDTO(SwissTimingConfigurationWithSecurityDTO dto, String hostname,
|
||||
Integer port, String eventName) {
|
||||
this.name = eventName;
|
||||
this.jsonUrl = dto.getJsonUrl();
|
||||
this.hostname = hostname;
|
||||
this.port = port;
|
||||
this.updateURL = dto.getUpdateURL();
|
||||
this.updateUsername = dto.getUpdateUsername();
|
||||
this.updatePassword = dto.getUpdatePassword();
|
||||
this.creatorName = dto.getCreatorName();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getJsonUrl() {
|
||||
return jsonUrl;
|
||||
}
|
||||
|
||||
public String getHostname() {
|
||||
return hostname;
|
||||
}
|
||||
|
||||
public Integer getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public String getUpdateURL() {
|
||||
return updateURL;
|
||||
}
|
||||
|
||||
public String getUpdateUsername() {
|
||||
return updateUsername;
|
||||
}
|
||||
|
||||
public String getUpdatePassword() {
|
||||
return updatePassword;
|
||||
}
|
||||
|
||||
public String getCreatorName() {
|
||||
return creatorName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessControlListDTO getAccessControlList() {
|
||||
return securityInformation.getAccessControlList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OwnershipDTO getOwnership() {
|
||||
return securityInformation.getOwnership();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAccessControlList(AccessControlListDTO createAccessControlListDTO) {
|
||||
securityInformation.setAccessControlList(createAccessControlListDTO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOwnership(OwnershipDTO createOwnershipDTO) {
|
||||
securityInformation.setOwnership(createOwnershipDTO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HasPermissions getType() {
|
||||
return SecuredDomainType.SWISS_TIMING_ACCOUNT;
|
||||
}
|
||||
|
||||
private TypeRelativeObjectIdentifier getTypeRelativeObjectIdentifier() {
|
||||
return creatorName == null ? new TypeRelativeObjectIdentifier(jsonUrl)
|
||||
: new TypeRelativeObjectIdentifier(jsonUrl, creatorName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QualifiedObjectIdentifier getIdentifier() {
|
||||
return getType().getQualifiedObjectIdentifier(getTypeRelativeObjectIdentifier());
|
||||
}
|
||||
}
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
package com.sap.sailing.gwt.ui.shared;
|
||||
|
||||
import com.google.gwt.user.client.rpc.IsSerializable;
|
||||
|
||||
public class TracTracConfigurationDTO implements IsSerializable {
|
||||
public String name;
|
||||
public String jsonURL;
|
||||
public String liveDataURI;
|
||||
public String storedDataURI;
|
||||
public String courseDesignUpdateURI;
|
||||
public String tractracUsername;
|
||||
public String tractracPassword;
|
||||
|
||||
public TracTracConfigurationDTO() {}
|
||||
|
||||
public TracTracConfigurationDTO(String name, String jsonURL, String liveDataURI, String storedDataURI, String courseDesignUpdateUrl,
|
||||
String tractracUsername, String tractracPassword) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.jsonURL = jsonURL;
|
||||
this.liveDataURI = liveDataURI;
|
||||
this.storedDataURI = storedDataURI;
|
||||
this.courseDesignUpdateURI = courseDesignUpdateUrl;
|
||||
this.tractracUsername = tractracUsername;
|
||||
this.tractracPassword = tractracPassword;
|
||||
}
|
||||
|
||||
}
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
package com.sap.sailing.gwt.ui.shared;
|
||||
|
||||
import com.google.gwt.user.client.rpc.IsSerializable;
|
||||
import com.sap.sailing.domain.common.security.SecuredDomainType;
|
||||
import com.sap.sse.security.shared.HasPermissions;
|
||||
import com.sap.sse.security.shared.QualifiedObjectIdentifier;
|
||||
import com.sap.sse.security.shared.TypeRelativeObjectIdentifier;
|
||||
import com.sap.sse.security.shared.dto.AccessControlListDTO;
|
||||
import com.sap.sse.security.shared.dto.OwnershipDTO;
|
||||
import com.sap.sse.security.shared.dto.SecuredDTO;
|
||||
import com.sap.sse.security.shared.dto.SecurityInformationDTO;
|
||||
|
||||
public class TracTracConfigurationWithSecurityDTO implements IsSerializable, SecuredDTO {
|
||||
private static final long serialVersionUID = -3567107321280535272L;
|
||||
|
||||
private SecurityInformationDTO securityInformation = new SecurityInformationDTO();
|
||||
|
||||
private String name;
|
||||
private String jsonUrl;
|
||||
private String liveDataURI;
|
||||
private String storedDataURI;
|
||||
private String courseDesignUpdateURI;
|
||||
private String tracTracUsername;
|
||||
private String tracTracPassword;
|
||||
private String creatorName;
|
||||
|
||||
public TracTracConfigurationWithSecurityDTO() {
|
||||
}
|
||||
|
||||
public TracTracConfigurationWithSecurityDTO(String name, String jsonUrl, String liveDataURI, String storedDataURI,
|
||||
String courseDesignUpdateUrl, String tractracUsername, String tractracPassword, String creatorName) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.jsonUrl = jsonUrl;
|
||||
this.liveDataURI = liveDataURI;
|
||||
this.storedDataURI = storedDataURI;
|
||||
this.courseDesignUpdateURI = courseDesignUpdateUrl;
|
||||
this.tracTracUsername = tractracUsername;
|
||||
this.tracTracPassword = tractracPassword;
|
||||
this.creatorName = creatorName;
|
||||
}
|
||||
|
||||
/** Copy constructor with new name */
|
||||
public TracTracConfigurationWithSecurityDTO(TracTracConfigurationWithSecurityDTO config, final String name) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.jsonUrl = config.getJsonUrl();
|
||||
this.liveDataURI = config.getLiveDataURI();
|
||||
this.storedDataURI = config.getStoredDataURI();
|
||||
this.courseDesignUpdateURI = config.getCourseDesignUpdateURI();
|
||||
this.tracTracUsername = config.getTracTracUsername();
|
||||
this.tracTracPassword = config.getTracTracPassword();
|
||||
this.creatorName = config.getCreatorName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessControlListDTO getAccessControlList() {
|
||||
return securityInformation.getAccessControlList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OwnershipDTO getOwnership() {
|
||||
return securityInformation.getOwnership();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAccessControlList(AccessControlListDTO createAccessControlListDTO) {
|
||||
securityInformation.setAccessControlList(createAccessControlListDTO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOwnership(OwnershipDTO createOwnershipDTO) {
|
||||
securityInformation.setOwnership(createOwnershipDTO);
|
||||
}
|
||||
|
||||
public SecurityInformationDTO getSecurityInformation() {
|
||||
return securityInformation;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getJsonUrl() {
|
||||
return jsonUrl;
|
||||
}
|
||||
|
||||
public String getLiveDataURI() {
|
||||
return liveDataURI;
|
||||
}
|
||||
|
||||
public String getStoredDataURI() {
|
||||
return storedDataURI;
|
||||
}
|
||||
|
||||
public String getCourseDesignUpdateURI() {
|
||||
return courseDesignUpdateURI;
|
||||
}
|
||||
|
||||
public String getTracTracUsername() {
|
||||
return tracTracUsername;
|
||||
}
|
||||
|
||||
public String getTracTracPassword() {
|
||||
return tracTracPassword;
|
||||
}
|
||||
|
||||
public String getCreatorName() {
|
||||
return creatorName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HasPermissions getType() {
|
||||
return SecuredDomainType.TRACTRAC_ACCOUNT;
|
||||
}
|
||||
|
||||
private TypeRelativeObjectIdentifier getTypeRelativeObjectIdentifier() {
|
||||
return creatorName == null ? new TypeRelativeObjectIdentifier(jsonUrl)
|
||||
: new TypeRelativeObjectIdentifier(jsonUrl, creatorName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QualifiedObjectIdentifier getIdentifier() {
|
||||
return getType().getQualifiedObjectIdentifier(getTypeRelativeObjectIdentifier());
|
||||
}
|
||||
}
|
||||
+17
-6
@@ -55,11 +55,13 @@ import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartProcedureChanged
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.SimpleRaceLogIdentifierImpl;
|
||||
import com.sap.sailing.domain.base.Boat;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.CourseBase;
|
||||
import com.sap.sailing.domain.base.DomainFactory;
|
||||
import com.sap.sailing.domain.base.Fleet;
|
||||
import com.sap.sailing.domain.base.RaceColumn;
|
||||
import com.sap.sailing.domain.base.impl.BoatClassImpl;
|
||||
import com.sap.sailing.domain.common.CourseDesignerMode;
|
||||
import com.sap.sailing.domain.common.MaxPointsReason;
|
||||
import com.sap.sailing.domain.common.Wind;
|
||||
@@ -307,9 +309,12 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD
|
||||
Competitor storedCompetitor = DomainFactory.INSTANCE.getOrCreateCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", "SAP",
|
||||
Color.RED, "someone@nowhere.de", null, null,
|
||||
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
|
||||
Boat storedBoat = DomainFactory.INSTANCE.getOrCreateBoat(UUID.randomUUID(), "SAP Extreme Sailing Team",
|
||||
new BoatClassImpl("X40", false), "123", Color.RED);
|
||||
CompetitorResults storedPositioningList = new CompetitorResultsImpl();
|
||||
storedPositioningList.add(new CompetitorResultImpl(storedCompetitor.getId(), storedCompetitor.getName(), /* rank */
|
||||
1, MaxPointsReason.NONE, /* score */ null, /* finishingTimePoint */null, /* comment */null, MergeState.OK));
|
||||
storedPositioningList.add(new CompetitorResultImpl(storedCompetitor.getId(), storedCompetitor.getName(), storedCompetitor.getShortName(),
|
||||
storedBoat.getName(), storedBoat.getSailID(), /* rank */ 1, MaxPointsReason.NONE, /* score */ null, /* finishingTimePoint */null,
|
||||
/* comment */null, MergeState.OK));
|
||||
RaceLogFinishPositioningConfirmedEvent event = new RaceLogFinishPositioningConfirmedEventImpl(now, author, 0, storedPositioningList);
|
||||
addAndStoreRaceLogEvent(leaderboard, raceColumnName, event);
|
||||
RaceLog loadedRaceLog = retrieveRaceLog();
|
||||
@@ -331,11 +336,14 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD
|
||||
Competitor storedCompetitor = DomainFactory.INSTANCE.getOrCreateCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", "SAP",
|
||||
Color.RED, "someone@nowhere.de", null, null,
|
||||
/* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
|
||||
Boat storedBoat = DomainFactory.INSTANCE.getOrCreateBoat(UUID.randomUUID(), "SAP Extreme Sailing Team",
|
||||
new BoatClassImpl("X40", false), "123", Color.RED);
|
||||
CompetitorResults storedPositioningList = new CompetitorResultsImpl();
|
||||
final TimePoint finishingTimePoint = MillisecondsTimePoint.now();
|
||||
final String comment = "This is a comment";
|
||||
storedPositioningList.add(new CompetitorResultImpl(storedCompetitor.getId(), storedCompetitor.getName(), /* rank */
|
||||
1, MaxPointsReason.NONE, /* score */ 12.3, finishingTimePoint, comment, MergeState.OK));
|
||||
storedPositioningList.add(new CompetitorResultImpl(storedCompetitor.getId(), storedCompetitor.getName(), storedCompetitor.getShortName(),
|
||||
storedBoat.getName(), storedBoat.getSailID(), /* rank */ 1, MaxPointsReason.NONE, /* score */ 12.3, finishingTimePoint, comment,
|
||||
MergeState.OK));
|
||||
RaceLogFinishPositioningConfirmedEvent event = new RaceLogFinishPositioningConfirmedEventImpl(now, author, 0, storedPositioningList);
|
||||
addAndStoreRaceLogEvent(leaderboard, raceColumnName, event);
|
||||
RaceLog loadedRaceLog = retrieveRaceLog();
|
||||
@@ -399,9 +407,12 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD
|
||||
public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogFinishPositioningListChangeEvent() {
|
||||
Competitor storedCompetitor = DomainFactory.INSTANCE.getOrCreateCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", "SAP", Color.RED,
|
||||
"someone@nowhere.de", null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
|
||||
Boat storedBoat = DomainFactory.INSTANCE.getOrCreateBoat(UUID.randomUUID(), "SAP Extreme Sailing Team",
|
||||
new BoatClassImpl("X40", false), "123", Color.RED);
|
||||
CompetitorResults storedPositioningList = new CompetitorResultsImpl();
|
||||
storedPositioningList.add(new CompetitorResultImpl(storedCompetitor.getId(), storedCompetitor.getName(), /* rank */
|
||||
1, MaxPointsReason.NONE, /* score */ null, /* finishingTimePoint */null, /* comment */null, MergeState.OK));
|
||||
storedPositioningList.add(new CompetitorResultImpl(storedCompetitor.getId(), storedCompetitor.getName(), storedCompetitor.getShortName(),
|
||||
storedBoat.getName(), storedBoat.getSailID(), /* rank */ 1, MaxPointsReason.NONE, /* score */ null, /* finishingTimePoint */null,
|
||||
/* comment */null, MergeState.OK));
|
||||
RaceLogFinishPositioningListChangedEvent event = new RaceLogFinishPositioningListChangedEventImpl(now, author, 0, storedPositioningList);
|
||||
|
||||
addAndStoreRaceLogEvent(leaderboard, raceColumnName, event);
|
||||
|
||||
+12
-2
@@ -43,6 +43,7 @@ import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRaceStatusEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartProcedureChangedEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl;
|
||||
import com.sap.sailing.domain.base.Boat;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.CourseBase;
|
||||
import com.sap.sailing.domain.base.DomainFactory;
|
||||
@@ -50,6 +51,7 @@ import com.sap.sailing.domain.base.Fleet;
|
||||
import com.sap.sailing.domain.base.RaceColumn;
|
||||
import com.sap.sailing.domain.base.Regatta;
|
||||
import com.sap.sailing.domain.base.Series;
|
||||
import com.sap.sailing.domain.base.impl.BoatClassImpl;
|
||||
import com.sap.sailing.domain.base.impl.FleetImpl;
|
||||
import com.sap.sailing.domain.common.CourseDesignerMode;
|
||||
import com.sap.sailing.domain.common.MaxPointsReason;
|
||||
@@ -207,8 +209,12 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends AbstractTestStorin
|
||||
public void testStoreAndRetrieveRegattaWithRaceLogFinishPositioningListChangeEvent() {
|
||||
Competitor storedCompetitor = DomainFactory.INSTANCE.getOrCreateCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", "SAP", Color.RED,
|
||||
"someone@nowhere.de", null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
|
||||
Boat storedBoat = DomainFactory.INSTANCE.getOrCreateBoat(UUID.randomUUID(), "SAP Extreme Sailing Team",
|
||||
new BoatClassImpl("X40", false), "123", Color.RED);
|
||||
CompetitorResults storedPositioningList = new CompetitorResultsImpl();
|
||||
storedPositioningList.add(new CompetitorResultImpl(storedCompetitor.getId(), storedCompetitor.getName(), /* rank */ 1, MaxPointsReason.NONE, /* score */ null, /* finishingTime */ null, /* comment */ null, MergeState.OK));
|
||||
storedPositioningList.add(new CompetitorResultImpl(storedCompetitor.getId(), storedCompetitor.getName(), storedCompetitor.getShortName(),
|
||||
storedBoat.getName(), storedBoat.getSailID(), /* rank */ 1, MaxPointsReason.NONE, /* score */ null, /* finishingTime */ null,
|
||||
/* comment */ null, MergeState.OK));
|
||||
RaceLogFinishPositioningListChangedEvent event = new RaceLogFinishPositioningListChangedEventImpl(now, author, 0, storedPositioningList);
|
||||
addAndStoreRaceLogEvent(regatta, raceColumnName, event);
|
||||
RaceLog loadedRaceLog = retrieveRaceLog();
|
||||
@@ -231,8 +237,12 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends AbstractTestStorin
|
||||
public void testStoreAndRetrieveRegattaWithRaceLogFinishPositioningConfirmedEvent() {
|
||||
Competitor storedCompetitor = DomainFactory.INSTANCE.getOrCreateCompetitor(UUID.randomUUID(), "SAP Extreme Sailing Team", "SAP", Color.RED,
|
||||
"someone@nowhere.de", null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null, null);
|
||||
Boat storedBoat = DomainFactory.INSTANCE.getOrCreateBoat(UUID.randomUUID(), "SAP Extreme Sailing Team",
|
||||
new BoatClassImpl("X40", false), "123", Color.RED);
|
||||
CompetitorResults storedPositioningList = new CompetitorResultsImpl();
|
||||
storedPositioningList.add(new CompetitorResultImpl(storedCompetitor.getId(), storedCompetitor.getName(), /* rank */ 1, MaxPointsReason.NONE, /* score */ null, /* finishingTime */ null, /* comment */ null, MergeState.OK));
|
||||
storedPositioningList.add(new CompetitorResultImpl(storedCompetitor.getId(), storedCompetitor.getName(), storedCompetitor.getShortName(),
|
||||
storedBoat.getName(), storedBoat.getSailID(), /* rank */ 1, MaxPointsReason.NONE, /* score */ null, /* finishingTime */ null,
|
||||
/* comment */ null, MergeState.OK));
|
||||
RaceLogFinishPositioningConfirmedEvent event = new RaceLogFinishPositioningConfirmedEventImpl(now, author, 0, storedPositioningList);
|
||||
addAndStoreRaceLogEvent(regatta, raceColumnName, event);
|
||||
RaceLog loadedRaceLog = retrieveRaceLog();
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package com.sap.sailing.selenium.pages.adminconsole.tractrac;
|
||||
|
||||
import org.openqa.selenium.WebDriver;
|
||||
import org.openqa.selenium.WebElement;
|
||||
|
||||
import com.sap.sailing.selenium.core.BySeleniumId;
|
||||
import com.sap.sailing.selenium.core.FindBy;
|
||||
import com.sap.sailing.selenium.pages.common.DataEntryDialogPO;
|
||||
|
||||
public class AddTracTracConnectionDialogPO extends DataEntryDialogPO {
|
||||
|
||||
// TODO [D049941]: Prefix the Ids with the component (e.g. "Button")
|
||||
@FindBy(how = BySeleniumId.class, using = "LiveURITextBox")
|
||||
private WebElement liveURITextBox;
|
||||
|
||||
@FindBy(how = BySeleniumId.class, using = "StoredURITextBox")
|
||||
private WebElement storedURITextBox;
|
||||
|
||||
@FindBy(how = BySeleniumId.class, using = "JsonURLTextBox")
|
||||
private WebElement jsonURLTextBox;
|
||||
|
||||
protected AddTracTracConnectionDialogPO(WebDriver driver, WebElement element) {
|
||||
super(driver, element);
|
||||
}
|
||||
|
||||
public void setJsonUrl(String jsonUrl) {
|
||||
jsonURLTextBox.clear();
|
||||
jsonURLTextBox.sendKeys(jsonUrl);
|
||||
}
|
||||
}
|
||||
+28
-38
@@ -74,16 +74,6 @@ public class TracTracEventManagementPanelPO extends PageArea {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO [D049941]: Prefix the Ids with the component (e.g. "Button")
|
||||
@FindBy(how = BySeleniumId.class, using = "LiveURITextBox")
|
||||
private WebElement liveURITextBox;
|
||||
|
||||
@FindBy(how = BySeleniumId.class, using = "StoredURITextBox")
|
||||
private WebElement storedURITextBox;
|
||||
|
||||
@FindBy(how = BySeleniumId.class, using = "JsonURLTextBox")
|
||||
private WebElement jsonURLTextBox;
|
||||
|
||||
@FindBy(how = BySeleniumId.class, using = "ListRacesButton")
|
||||
private WebElement listRacesButton;
|
||||
|
||||
@@ -111,6 +101,12 @@ public class TracTracEventManagementPanelPO extends PageArea {
|
||||
@FindBy(how = BySeleniumId.class, using = "TrackedRacesListComposite")
|
||||
private WebElement trackedRacesListComposite;
|
||||
|
||||
@FindBy(how = BySeleniumId.class, using = "AddConnectionButton")
|
||||
private WebElement addConnectionButton;
|
||||
|
||||
@FindBy(how = BySeleniumId.class, using = "TracTracConfigurationWithSecurityDTOTable")
|
||||
private WebElement configurationTable;
|
||||
|
||||
/**
|
||||
* <p></p>
|
||||
*
|
||||
@@ -123,40 +119,34 @@ public class TracTracEventManagementPanelPO extends PageArea {
|
||||
super(driver, element);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Lists all available trackable races for the given URL. The list of the races can be obtained via
|
||||
* {@link #getTrackableRaces()}.</p>
|
||||
*
|
||||
* @param url
|
||||
* The URL for which the races are to list.
|
||||
*/
|
||||
public void listTrackableRaces(String url) {
|
||||
listTrackableRaces("", "", url); //$NON-NLS-1$//$NON-NLS-2$
|
||||
public void addConnectionAndListTrackableRaces(String url) {
|
||||
AddTracTracConnectionDialogPO dialog = addConnection();
|
||||
dialog.setJsonUrl(url);
|
||||
dialog.pressOk();
|
||||
listRacesForExistingConnection(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Lists all available trackable races for the given URL. The list of the races can be obtained via
|
||||
* {@link #getTrackableRaces()}.</p>
|
||||
*
|
||||
* @param url
|
||||
* The URL for which the races are to list.
|
||||
*/
|
||||
public void listTrackableRaces(String liveURI, String storedURI, String jsonURL) {
|
||||
this.liveURITextBox.clear();
|
||||
this.liveURITextBox.sendKeys(liveURI);
|
||||
|
||||
this.storedURITextBox.clear();
|
||||
this.storedURITextBox.sendKeys(storedURI);
|
||||
|
||||
this.jsonURLTextBox.clear();
|
||||
this.jsonURLTextBox.sendKeys(jsonURL);
|
||||
|
||||
public void listRacesForExistingConnection(String url) {
|
||||
CellTablePO<DataEntryPO> tablePO = getConfigurationTable();
|
||||
tablePO.waitForTableToShowData();
|
||||
tablePO.selectEntries(entry -> {
|
||||
return url.equals(entry.getColumnContent("JSON URL"));
|
||||
}, () -> false);
|
||||
|
||||
this.listRacesButton.click();
|
||||
|
||||
waitForAjaxRequests();
|
||||
}
|
||||
|
||||
public AddTracTracConnectionDialogPO addConnection() {
|
||||
addConnectionButton.click();
|
||||
final WebElement dialog = findElementBySeleniumId(this.driver, "EditTracTracConnectionDialog");
|
||||
return new AddTracTracConnectionDialogPO(this.driver, dialog);
|
||||
}
|
||||
|
||||
private CellTablePO<DataEntryPO> getConfigurationTable() {
|
||||
return new GenericCellTablePO<>(this.driver, this.configurationTable, DataEntryPO.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns the list of all available trackable races. This list will be empty if no race is available or if no
|
||||
* race was specified before.</p>
|
||||
|
||||
+13
-4
@@ -5,6 +5,8 @@ import org.junit.Test;
|
||||
import static org.hamcrest.core.Is.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Before;
|
||||
|
||||
import com.sap.sailing.selenium.pages.adminconsole.AdminConsolePage;
|
||||
import com.sap.sailing.selenium.pages.adminconsole.tractrac.TracTracEventManagementPanelPO;
|
||||
import com.sap.sailing.selenium.test.AbstractSeleniumTest;
|
||||
@@ -19,6 +21,13 @@ public class TestRaceFilterForTracTracEvents extends AbstractSeleniumTest {
|
||||
private static final String BMW_CUP_JSON_URL =
|
||||
"http://kml.skitrac.traclive.dk/events/event_20120803_BMWCup/jsonservice.php"; //$NON-NLS-1$
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() {
|
||||
clearState(getContextRoot());
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Test with no filter at all, which means we expect all TracTrac races are displayed for a given event.</p>
|
||||
*/
|
||||
@@ -26,7 +35,7 @@ public class TestRaceFilterForTracTracEvents extends AbstractSeleniumTest {
|
||||
public void testNoFilter() {
|
||||
AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot());
|
||||
TracTracEventManagementPanelPO tracTracEvents = adminConsole.goToTracTracEvents();
|
||||
tracTracEvents.listTrackableRaces(BMW_CUP_JSON_URL);
|
||||
tracTracEvents.addConnectionAndListTrackableRaces(BMW_CUP_JSON_URL);
|
||||
assertThat(tracTracEvents.getTrackableRaces().size(), is(12));
|
||||
}
|
||||
|
||||
@@ -37,7 +46,7 @@ public class TestRaceFilterForTracTracEvents extends AbstractSeleniumTest {
|
||||
public void testPartialFilter() {
|
||||
AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot());
|
||||
TracTracEventManagementPanelPO tracTracEvents = adminConsole.goToTracTracEvents();
|
||||
tracTracEvents.listTrackableRaces(BMW_CUP_JSON_URL);
|
||||
tracTracEvents.addConnectionAndListTrackableRaces(BMW_CUP_JSON_URL);
|
||||
tracTracEvents.setFilterForTrackableRaces("BMW Cup Race 1"); //$NON-NLS-1$
|
||||
assertThat(tracTracEvents.getTrackableRaces().size(), is(5));
|
||||
}
|
||||
@@ -49,7 +58,7 @@ public class TestRaceFilterForTracTracEvents extends AbstractSeleniumTest {
|
||||
public void testExactFilter() {
|
||||
AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot());
|
||||
TracTracEventManagementPanelPO tracTracEvents = adminConsole.goToTracTracEvents();
|
||||
tracTracEvents.listTrackableRaces(BMW_CUP_JSON_URL);
|
||||
tracTracEvents.addConnectionAndListTrackableRaces(BMW_CUP_JSON_URL);
|
||||
tracTracEvents.setFilterForTrackableRaces("BMW Cup Race 12"); //$NON-NLS-1$
|
||||
assertThat(tracTracEvents.getTrackableRaces().size(), is(1));
|
||||
}
|
||||
@@ -61,7 +70,7 @@ public class TestRaceFilterForTracTracEvents extends AbstractSeleniumTest {
|
||||
public void testNoneMatchingFilter() {
|
||||
AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot());
|
||||
TracTracEventManagementPanelPO tracTracEvents = adminConsole.goToTracTracEvents();
|
||||
tracTracEvents.listTrackableRaces(BMW_CUP_JSON_URL);
|
||||
tracTracEvents.addConnectionAndListTrackableRaces(BMW_CUP_JSON_URL);
|
||||
tracTracEvents.setFilterForTrackableRaces("BMW Cup Race 18"); //$NON-NLS-1$
|
||||
assertThat(tracTracEvents.getTrackableRaces().size(), is(0));
|
||||
}
|
||||
|
||||
+1
-1
@@ -259,7 +259,7 @@ public class TestRefreshableSelectionModel extends AbstractSeleniumTest {
|
||||
|
||||
// Start the tracking for the races and wait until they are ready to use
|
||||
TracTracEventManagementPanelPO tracTracEvents = adminConsole.goToTracTracEvents();
|
||||
tracTracEvents.listTrackableRaces(IDM_5O5_2013_JSON_URL);
|
||||
tracTracEvents.addConnectionAndListTrackableRaces(IDM_5O5_2013_JSON_URL);
|
||||
tracTracEvents.setReggataForTracking(this.regatta);
|
||||
tracTracEvents.setTrackSettings(false, false, false);
|
||||
tracTracEvents.startTrackingForRaces(this.trackableRaces);
|
||||
|
||||
+1
-1
@@ -129,7 +129,7 @@ public class TestSmartphoneTrackingEventManagementPanel extends AbstractSelenium
|
||||
|
||||
// Start the tracking for the races and wait until they are ready to use
|
||||
TracTracEventManagementPanelPO tracTracEvents = adminConsole.goToTracTracEvents();
|
||||
tracTracEvents.listTrackableRaces(IDM_5O5_2013_JSON_URL);
|
||||
tracTracEvents.addConnectionAndListTrackableRaces(IDM_5O5_2013_JSON_URL);
|
||||
tracTracEvents.setReggataForTracking(this.regatta);
|
||||
tracTracEvents.setTrackSettings(false, false, false);
|
||||
tracTracEvents.startTrackingForRaces(this.trackableRaces);
|
||||
|
||||
+3
-3
@@ -63,7 +63,7 @@ public class TestStartAndStopTrackingForTracTracEvents extends AbstractSeleniumT
|
||||
RegattaStructureManagementPanelPO regattaStructure = adminConsole.goToRegattaStructure();
|
||||
regattaStructure.createRegatta(bmwCupDescriptor);
|
||||
TracTracEventManagementPanelPO tracTracEvents = adminConsole.goToTracTracEvents();
|
||||
tracTracEvents.listTrackableRaces(BMW_CUP_JSON_URL);
|
||||
tracTracEvents.addConnectionAndListTrackableRaces(BMW_CUP_JSON_URL);
|
||||
tracTracEvents.setReggataForTracking(bmwCupDescriptor);
|
||||
tracTracEvents.setTrackSettings(false, false, false);
|
||||
tracTracEvents.startTrackingForRace(this.trackableRace);
|
||||
@@ -81,7 +81,7 @@ public class TestStartAndStopTrackingForTracTracEvents extends AbstractSeleniumT
|
||||
RegattaStructureManagementPanelPO regattaStructure = adminConsole.goToRegattaStructure();
|
||||
regattaStructure.createRegatta(new RegattaDescriptor(BMW_CUP_EVENT, BMW_CUP_BOAT_CLASS));
|
||||
TracTracEventManagementPanelPO tracTracEvents = adminConsole.goToTracTracEvents();
|
||||
tracTracEvents.listTrackableRaces(BMW_CUP_JSON_URL);
|
||||
tracTracEvents.addConnectionAndListTrackableRaces(BMW_CUP_JSON_URL);
|
||||
tracTracEvents.setReggataForTracking(DEFAULT_REGATTA);
|
||||
tracTracEvents.setTrackSettings(false, false, false);
|
||||
tracTracEvents.startTrackingForRacesAndAcceptDefaultRegattaWarning(this.trackableRace);
|
||||
@@ -96,7 +96,7 @@ public class TestStartAndStopTrackingForTracTracEvents extends AbstractSeleniumT
|
||||
regattaStructure.createRegatta(bmwCupDescriptor);
|
||||
regattaStructure.createRegatta(idm2013Descriptor);
|
||||
TracTracEventManagementPanelPO tracTracEvents = adminConsole.goToTracTracEvents();
|
||||
tracTracEvents.listTrackableRaces(BMW_CUP_JSON_URL);
|
||||
tracTracEvents.addConnectionAndListTrackableRaces(BMW_CUP_JSON_URL);
|
||||
tracTracEvents.setReggataForTracking(idm2013Descriptor);
|
||||
tracTracEvents.setTrackSettings(false, false, false);
|
||||
tracTracEvents.startTrackingForRaceAndAwaitBoatClassError(this.trackableRace, IDM_2013_BOAT_CLASS);
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ public class TestAutoPlay extends AbstractSeleniumTest {
|
||||
String.format(BMW_RACE, 1));
|
||||
|
||||
TracTracEventManagementPanelPO tracTracEvents = adminConsole.goToTracTracEvents();
|
||||
tracTracEvents.listTrackableRaces(BMW_CUP_JSON_URL);
|
||||
tracTracEvents.addConnectionAndListTrackableRaces(BMW_CUP_JSON_URL);
|
||||
RegattaDescriptor bmwCupDescriptor = new RegattaDescriptor(BMW_CUP_EVENT, BMW_CUP_BOAT_CLASS);
|
||||
tracTracEvents.setReggataForTracking(bmwCupDescriptor);
|
||||
tracTracEvents.setTrackSettings(true, false, false);
|
||||
|
||||
+10
-4
@@ -9,6 +9,7 @@ import static org.junit.Assert.assertTrue;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sailing.selenium.pages.adminconsole.AdminConsolePage;
|
||||
@@ -57,6 +58,7 @@ public class TestColumnsInLeaderboard extends AbstractSeleniumTest {
|
||||
configureLeaderboard();
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@Test
|
||||
public void testCorrectDisplayOfAllColumns() {
|
||||
LeaderboardPage leaderboard = LeaderboardPage.goToPage(getWebDriver(), getContextRoot(), LEADERBOARD, true);
|
||||
@@ -106,7 +108,7 @@ public class TestColumnsInLeaderboard extends AbstractSeleniumTest {
|
||||
assertFalse(races.iterator().next().isLinked()); // removing the race must make the race column unlinked.
|
||||
}
|
||||
// now back to the TracTrac management panel, load the race again and make sure it is auto-linked to the column
|
||||
startTrackingRaceAndStopWhenFinished(adminConsole);
|
||||
startTrackingRaceAndStopWhenFinished(adminConsole, false);
|
||||
{
|
||||
LeaderboardConfigurationPanelPO leaderboardConfiguration = adminConsole.goToLeaderboardConfiguration();
|
||||
LeaderboardDetailsPanelPO details = leaderboardConfiguration.getLeaderboardDetails(LEADERBOARD);
|
||||
@@ -128,7 +130,7 @@ public class TestColumnsInLeaderboard extends AbstractSeleniumTest {
|
||||
seriesDialog.pressOk();
|
||||
regattaDetails.deleteSeries("Default");
|
||||
// Start the tracking for the races and wait until they are ready to use
|
||||
startTrackingRaceAndStopWhenFinished(adminConsole);
|
||||
startTrackingRaceAndStopWhenFinished(adminConsole, true);
|
||||
LeaderboardConfigurationPanelPO leaderboardConfiguration = adminConsole.goToLeaderboardConfiguration();
|
||||
leaderboardConfiguration.createRegattaLeaderboard(this.regatta);
|
||||
LeaderboardDetailsPanelPO leaderboardDetails = leaderboardConfiguration.getLeaderboardDetails(LEADERBOARD);
|
||||
@@ -138,9 +140,13 @@ public class TestColumnsInLeaderboard extends AbstractSeleniumTest {
|
||||
/**
|
||||
* @param adminConsole
|
||||
*/
|
||||
private void startTrackingRaceAndStopWhenFinished(AdminConsolePage adminConsole) {
|
||||
private void startTrackingRaceAndStopWhenFinished(AdminConsolePage adminConsole, boolean addConnection) {
|
||||
TracTracEventManagementPanelPO tracTracEvents = adminConsole.goToTracTracEvents();
|
||||
tracTracEvents.listTrackableRaces(KIELER_WOCHE_2013_JSON_URL);
|
||||
if (addConnection) {
|
||||
tracTracEvents.addConnectionAndListTrackableRaces(KIELER_WOCHE_2013_JSON_URL);
|
||||
} else {
|
||||
tracTracEvents.listRacesForExistingConnection(KIELER_WOCHE_2013_JSON_URL);
|
||||
}
|
||||
tracTracEvents.setReggataForTracking(this.regatta);
|
||||
tracTracEvents.setTrackSettings(false, false, false);
|
||||
tracTracEvents.startTrackingForRace(this.trackableRace);
|
||||
|
||||
+1
-1
@@ -204,7 +204,7 @@ public class TestLeaderboardConfiguration extends AbstractSeleniumTest {
|
||||
|
||||
// Start the tracking for the races and wait until they are ready to use
|
||||
TracTracEventManagementPanelPO tracTracEvents = adminConsole.goToTracTracEvents();
|
||||
tracTracEvents.listTrackableRaces(IDM_5O5_2013_JSON_URL);
|
||||
tracTracEvents.addConnectionAndListTrackableRaces(IDM_5O5_2013_JSON_URL);
|
||||
tracTracEvents.setReggataForTracking(this.regatta);
|
||||
tracTracEvents.setTrackSettings(false, false, false);
|
||||
tracTracEvents.startTrackingForRaces(trackableRaces);
|
||||
|
||||
+1
-1
@@ -104,7 +104,7 @@ public class TestSwitchingOffStartOfRaceInference extends AbstractSeleniumTest {
|
||||
regattaDetails.deleteSeries("Default");
|
||||
// Start the tracking for the races and wait until they are ready to use
|
||||
TracTracEventManagementPanelPO tracTracEvents = adminConsole.goToTracTracEvents();
|
||||
tracTracEvents.listTrackableRaces(BMW_CUP_JSON_URL);
|
||||
tracTracEvents.addConnectionAndListTrackableRaces(BMW_CUP_JSON_URL);
|
||||
tracTracEvents.setReggataForTracking(this.regatta);
|
||||
tracTracEvents.setTrackSettings(false, false, false);
|
||||
tracTracEvents.startTrackingForRace(this.trackableRace);
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ public class TestLeaderboardEditing extends AbstractSeleniumTest {
|
||||
private void startTrackingRaceAndWait(AdminConsolePage adminConsole, String jsonUrl, TrackableRaceDescriptor trackableRace,
|
||||
TrackedRaceDescriptor trackedRace, long waitingTime) {
|
||||
TracTracEventManagementPanelPO tracTracEvents = adminConsole.goToTracTracEvents();
|
||||
tracTracEvents.listTrackableRaces(jsonUrl);
|
||||
tracTracEvents.addConnectionAndListTrackableRaces(jsonUrl);
|
||||
tracTracEvents.setTrackSettings(false, true, false);
|
||||
tracTracEvents.startTrackingForRace(trackableRace);
|
||||
TrackedRacesListPO trackedRacesList = tracTracEvents.getTrackedRacesList();
|
||||
|
||||
+1
-1
@@ -340,7 +340,7 @@ public class SettingsTest extends AbstractSeleniumTest {
|
||||
TrackedRaceDescriptor trackedRace = new TrackedRaceDescriptor(BMW_CUP_REGATTA, BMW_CUP_BOAT_CLASS,
|
||||
String.format(BMW_RACE, 1));
|
||||
TracTracEventManagementPanelPO tracTracEvents = adminConsole.goToTracTracEvents();
|
||||
tracTracEvents.listTrackableRaces(BMW_CUP_JSON_URL);
|
||||
tracTracEvents.addConnectionAndListTrackableRaces(BMW_CUP_JSON_URL);
|
||||
RegattaDescriptor bmwCupDescriptor = new RegattaDescriptor(BMW_CUP_EVENT, BMW_CUP_BOAT_CLASS);
|
||||
tracTracEvents.setReggataForTracking(bmwCupDescriptor);
|
||||
tracTracEvents.setTrackSettings(true, false, false);
|
||||
|
||||
+1
-1
@@ -124,7 +124,7 @@ public class SimulatorOverlayTest extends AbstractSeleniumTest {
|
||||
}
|
||||
|
||||
private void trackRacesFor49er(final RegattaDescriptor regattaDescriptor, final TracTracEventManagementPanelPO tracTracEvents) {
|
||||
tracTracEvents.listTrackableRaces(JSON_URL);
|
||||
tracTracEvents.addConnectionAndListTrackableRaces(JSON_URL);
|
||||
tracTracEvents.setReggataForTracking(regattaDescriptor);
|
||||
tracTracEvents.setTrackSettings(true, false, false);
|
||||
tracTracEvents.setFilterForTrackableRaces("(49er)");
|
||||
|
||||
Loaded 100 of 132 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user