mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-11 05:12:43 +00:00
Merge branch 'bug4104' of ssh://trac@sapsailing.com/home/trac/git into bug4104
This commit is contained in:
commit
b45a8a7165
23 files changed
+609
-495
No files matched your search
@@ -17,12 +17,13 @@ Export-Package: com.sap.sailing.domain.common,
|
||||
com.sap.sailing.domain.common.quadtree,
|
||||
com.sap.sailing.domain.common.quadtree.impl;x-friends:="com.sap.sailing.domain.test",
|
||||
com.sap.sailing.domain.common.racelog,
|
||||
com.sap.sailing.domain.common.sharding,
|
||||
com.sap.sailing.domain.common.racelog.tracking,
|
||||
com.sap.sailing.domain.common.racelog.utils,
|
||||
com.sap.sailing.domain.common.scalablevalue.impl,
|
||||
com.sap.sailing.domain.common.security,
|
||||
com.sap.sailing.domain.common.sensordata,
|
||||
com.sap.sailing.domain.common.sharding,
|
||||
com.sap.sailing.domain.common.tagging,
|
||||
com.sap.sailing.domain.common.trackfiles,
|
||||
com.sap.sailing.domain.common.tracking,
|
||||
com.sap.sailing.domain.common.tracking.impl,
|
||||
|
||||
+55
-41
@@ -5,12 +5,17 @@ import java.io.Serializable;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
/**
|
||||
* Used to send tags over network. Allows to create tags with all possible combinations of states (private/public and
|
||||
* valid/revoked).
|
||||
* Tags are used to link input of users in form of "tags" (extended comments) to a specific race. These tags consists of
|
||||
* {@link #tag title}, optional {@link #comment}, optional {@link imageURL image URL} and a {@link #visibleForPublic
|
||||
* visibility status}. They can be set to be visible only for the author or visible for everybody. Private tags will be
|
||||
* stored in the user store, public tags will be stored as event in the racelog. Not every user has write access to the
|
||||
* racelog therefor the default visibility should be private. The {@link com.sap.sailing.server.tagging.TaggingService
|
||||
* TaggingService} is able to perform all CRUD operations on tags and also checks for permissions.<br/>
|
||||
* <br/>
|
||||
* Tags should be unique for the key consisting of: {@link #tag title}, {@link #comment}, {@link imageURL image URL},
|
||||
* {@link #visibleForPublic visibility status}, {@link #username} and {@link #raceTimepoint}. <code>NOT</code> part of
|
||||
* the key are {@link #createdAt} and {@link #revokedAt}.
|
||||
*/
|
||||
// TODO: Remove max length
|
||||
// TODO: add Javadoc, which parameter has which meaning? what can be guessed from parameters (revokedAt = null)? what is
|
||||
// the key to identify a tag?
|
||||
public class TagDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 3907411584518452300L;
|
||||
@@ -19,15 +24,23 @@ public class TagDTO implements Serializable {
|
||||
|
||||
private String tag, comment, imageURL, username;
|
||||
private boolean visibleForPublic;
|
||||
/**
|
||||
* By default every tag should have set the attributes {@link #raceTimepoint} and {@link #createdAt}.<br/>
|
||||
* <code>raceTimepoint</code>: absolute timepoint of race when the tag got created<br/>
|
||||
* <code>createdAt</code>: actual absolute creation timepoint of tag<br/>
|
||||
* <br/>
|
||||
* The racelog does not allow to delete events. Instead these events can only be revoked which is implemented as a
|
||||
* new revocation event. This applies also for tags so it is not possible to "delete" public tags. To mark a tag as
|
||||
* revoked, set the attribute {@link #revokedAt} to a value which does not equal <code>null</code>. So every tag
|
||||
* where {@link #revokedAt} equals <code>null</code> can be seen as valid and <code>NOT</code> revoked.
|
||||
*/
|
||||
private TimePoint raceTimepoint, createdAt, revokedAt;
|
||||
|
||||
public static final int MAX_TAG_LENGTH = 100;
|
||||
public static final int MAX_COMMENT_LENGTH = 400;
|
||||
|
||||
/**
|
||||
* Required by GWT, do <b>NOT</b> use this constructor! Use the other constructors instead to allow information
|
||||
* transfer.
|
||||
*/
|
||||
@Deprecated
|
||||
TagDTO() {
|
||||
}
|
||||
|
||||
@@ -40,18 +53,18 @@ public class TagDTO implements Serializable {
|
||||
* comment of tag, may be <code>null</code> as comment is optional
|
||||
* @param imageURL
|
||||
* image URL of tag, may be <code>null</code> as image is optional
|
||||
* @param username
|
||||
* name of user who created the tag
|
||||
* @param visibleForPublic
|
||||
* should be <code>true</code> if everbidy should see this tag, otherwise <code>false</code>
|
||||
* @param username
|
||||
* name of user who created the tag
|
||||
* @param raceTimepoint
|
||||
* timepoint of race where tag ot created
|
||||
* @param createdAt
|
||||
* timepoint where <code>username</code> created the tag
|
||||
*/
|
||||
public TagDTO(String tag, String comment, String imageURL, String username, boolean visibleForPublic,
|
||||
public TagDTO(String tag, String comment, String imageURL, boolean visibleForPublic, String username,
|
||||
TimePoint raceTimepoint, TimePoint createdAt) {
|
||||
this(tag, comment, imageURL, username, visibleForPublic, raceTimepoint, createdAt, null);
|
||||
this(tag, comment, imageURL, visibleForPublic, username, raceTimepoint, createdAt, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,10 +76,10 @@ public class TagDTO implements Serializable {
|
||||
* comment of tag, may be <code>null</code> as comment is optional
|
||||
* @param imageURL
|
||||
* image URL of tag, may be <code>null</code> as image is optional
|
||||
* @param username
|
||||
* name of user who created the tag
|
||||
* @param visibleForPublic
|
||||
* should be <code>true</code> if everbidy should see this tag, otherwise <code>false</code>
|
||||
* @param username
|
||||
* name of user who created the tag
|
||||
* @param raceTimepoint
|
||||
* timepoint of race where tag ot created
|
||||
* @param createdAt
|
||||
@@ -74,15 +87,15 @@ public class TagDTO implements Serializable {
|
||||
* @param revokedAt
|
||||
* timepoint where tag got revoked, may be <code>null</code> if tag is not revoked
|
||||
*/
|
||||
public TagDTO(String tag, String comment, String imageURL, String username, boolean visibleForPublic,
|
||||
public TagDTO(String tag, String comment, String imageURL, boolean visibleForPublic, String username,
|
||||
TimePoint raceTimepoint, TimePoint createdAt, TimePoint revokedAt) {
|
||||
this.tag = tag;
|
||||
this.comment = comment;
|
||||
this.imageURL = imageURL;
|
||||
this.visibleForPublic = visibleForPublic;
|
||||
this.username = username;
|
||||
this.raceTimepoint = raceTimepoint;
|
||||
this.createdAt = createdAt;
|
||||
this.visibleForPublic = visibleForPublic;
|
||||
this.revokedAt = revokedAt;
|
||||
}
|
||||
|
||||
@@ -113,15 +126,6 @@ public class TagDTO implements Serializable {
|
||||
return imageURL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns name of user who created this tag.
|
||||
*
|
||||
* @return username
|
||||
*/
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns visibilty of tag.
|
||||
*
|
||||
@@ -131,6 +135,15 @@ public class TagDTO implements Serializable {
|
||||
return visibleForPublic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns name of user who created this tag.
|
||||
*
|
||||
* @return username
|
||||
*/
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns logical timepoint of race where tag was created.
|
||||
*
|
||||
@@ -172,6 +185,11 @@ public class TagDTO implements Serializable {
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
TagDTO other = (TagDTO) obj;
|
||||
if (tag == null) {
|
||||
if (other.tag != null)
|
||||
return false;
|
||||
} else if (!tag.equals(other.tag))
|
||||
return false;
|
||||
if (comment == null) {
|
||||
if (other.comment != null)
|
||||
return false;
|
||||
@@ -182,34 +200,30 @@ public class TagDTO implements Serializable {
|
||||
return false;
|
||||
} else if (!imageURL.equals(other.imageURL))
|
||||
return false;
|
||||
if (raceTimepoint == null) {
|
||||
if (other.raceTimepoint != null)
|
||||
return false;
|
||||
} else if (!raceTimepoint.equals(other.raceTimepoint))
|
||||
return false;
|
||||
if (tag == null) {
|
||||
if (other.tag != null)
|
||||
return false;
|
||||
} else if (!tag.equals(other.tag))
|
||||
if (isVisibleForPublic() != other.isVisibleForPublic()) {
|
||||
return false;
|
||||
}
|
||||
if (username == null) {
|
||||
if (other.username != null)
|
||||
return false;
|
||||
} else if (!username.equals(other.username)) {
|
||||
return false;
|
||||
}
|
||||
if (isVisibleForPublic() != other.isVisibleForPublic()) {
|
||||
if (raceTimepoint == null) {
|
||||
if (other.raceTimepoint != null)
|
||||
return false;
|
||||
} else if (!raceTimepoint.equals(other.raceTimepoint))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares {@link TagDTO} with given attributes.
|
||||
*
|
||||
* @return <code>true</code> if all parameters match the attributes of {@link TagDTO}, otherwise <code>false</code>
|
||||
* @return <code>true</code> if all parameters match the key attributes of {@link TagDTO}, otherwise
|
||||
* <code>false</code>
|
||||
*/
|
||||
public boolean equals(String tag, String comment, String imageURL, String username, boolean visibleForPublic,
|
||||
public boolean equals(String tag, String comment, String imageURL, boolean visibleForPublic, String username,
|
||||
TimePoint raceTimepoint) {
|
||||
if (this.comment == null) {
|
||||
if (comment != null)
|
||||
@@ -251,8 +265,8 @@ public class TagDTO implements Serializable {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TagDTO [tag=" + tag + ", comment=" + comment + ", imageURL=" + imageURL + ", username=" + username
|
||||
+ ", raceTimepoint=" + raceTimepoint + ", createdAt=" + createdAt + ", isPublic=" + visibleForPublic
|
||||
+ ", revokedAt=" + revokedAt + "]";
|
||||
return "TagDTO [tag=" + tag + ", comment=" + comment + ", imageURL=" + imageURL + ", visibleForPublic="
|
||||
+ visibleForPublic + ", username=" + username + ", raceTimepoint=" + raceTimepoint + ", createdAt="
|
||||
+ createdAt + ", revokedAt=" + revokedAt + "]";
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package com.sap.sailing.domain.common.tagging;
|
||||
|
||||
public class RaceLogNotFoundException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = -1935079125197798550L;
|
||||
|
||||
public RaceLogNotFoundException() {
|
||||
|
||||
}
|
||||
|
||||
public RaceLogNotFoundException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package com.sap.sailing.domain.common.tagging;
|
||||
|
||||
public class ServiceNotFoundException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 4354757061181985766L;
|
||||
|
||||
public ServiceNotFoundException() {
|
||||
|
||||
}
|
||||
|
||||
public ServiceNotFoundException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package com.sap.sailing.domain.common.tagging;
|
||||
|
||||
public class TagAlreadyExistsException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = -3908869597780348971L;
|
||||
|
||||
public TagAlreadyExistsException() {
|
||||
|
||||
}
|
||||
|
||||
public TagAlreadyExistsException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
+50
-5
@@ -23,7 +23,6 @@ import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.gwt.client.ErrorReporter;
|
||||
import com.sap.sse.gwt.client.async.AsyncActionsExecutor;
|
||||
|
||||
// TODO: add Javadoc
|
||||
public class RaceTimesInfoProvider {
|
||||
|
||||
private final SailingServiceAsync sailingService;
|
||||
@@ -37,10 +36,27 @@ public class RaceTimesInfoProvider {
|
||||
private final Set<RaceTimesInfoProviderListener> listeners;
|
||||
private boolean terminated = false;
|
||||
|
||||
// Should server send tag updates for this RaceTimesInfoProvider instance? Default is set to false,
|
||||
// TaggingPanel will set value to true for corresponding instance.
|
||||
// => decrease server load by not requesting tags every roundtrip.
|
||||
/**
|
||||
* If set to true, {@link com.sap.sailing.domain.common.dto.TagDTO tags} will also be requested from server by this
|
||||
* {@link RaceTimesInfoProvider}. This is only a temporarily workaround to save a new repeating request which is
|
||||
* only used for tags. This attribute will be set by {@link com.sap.sailing.gwt.ui.raceboard.tagging.TaggingPanel
|
||||
* TaggingPanel} by calling methods {@link #enableTagRequests()} and {@link #disableTagRequests()} and should not
|
||||
* affect any data of the other attributes of {@link RaceTimesInfoDTO}.
|
||||
*/
|
||||
// TODO: remove this workaround as soon as bug 4736 is resolved
|
||||
private boolean requestTags = false;
|
||||
/**
|
||||
* Used to save timepoints of the client for differential transmission of
|
||||
* {@link com.sap.sailing.domain.common.dto.TagDTO tags} from the server. The {@link RaceTimesInfoProvider} will
|
||||
* only request {@link com.sap.sailing.domain.common.dto.TagDTO tags} since the saved timepoint of the requested
|
||||
* race. The saved timepoint does equal the latest {@link com.sap.sailing.domain.common.dto.TagDTO#createdAt
|
||||
* createdAt} or {@link com.sap.sailing.domain.common.dto.TagDTO#revokedAt revokedAt} timepoint of all already
|
||||
* received tags of the current client. This allows the server to filter all tags only for updates for this specific
|
||||
* client and therefor only updates will be transmitted over network. The saved timepoint can be <code>null</code>
|
||||
* or <code>0</code> to request all tags from server.<br/>
|
||||
* Timepoints can be updated via method call {@link #setLatestReceivedTagTime(RegattaAndRaceIdentifier, TimePoint)}
|
||||
* and should be updated everytime the client receives a change of the tags to use minimal network bandwidth.
|
||||
*/
|
||||
private Map<RegattaAndRaceIdentifier, TimePoint> latestReceivedTagTimes;
|
||||
|
||||
/**
|
||||
@@ -246,18 +262,47 @@ public class RaceTimesInfoProvider {
|
||||
raceTimesInfos.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the saved timepoint for the given <code>raceIdentifier</code> which is used as known point of time when
|
||||
* data is requested from server and {@link #requestTags} is set to <code>true</code>.
|
||||
*
|
||||
* @param raceIdentifier
|
||||
* identifies race
|
||||
* @return timepoint of latest received tag, may be <code>null</code> when no timepoint is saved
|
||||
*/
|
||||
public TimePoint getLatestReceivedTagTime(RegattaAndRaceIdentifier raceIdentifier) {
|
||||
return latestReceivedTagTimes.get(raceIdentifier);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the timepoint to request {@link com.sap.sailing.domain.common.dto.TagDTO tags} from when request is send to
|
||||
* {@link SailingService}. <code>latestReceivedTagTime</code> may be <code>null</code> or <code>0</code> to request
|
||||
* all tags.
|
||||
*
|
||||
* @param raceIdentifier
|
||||
* identifies race
|
||||
* @param latestReceivedTagTime
|
||||
* timepoint to request {@link com.sap.sailing.domain.common.dto.TagDTO tags} from. Should be
|
||||
* {@link com.sap.sailing.domain.common.dto.TagDTO#createdAt createdAt} or
|
||||
* {@link com.sap.sailing.domain.common.dto.TagDTO#revokedAt revokedAt} timepoint of tags of the latests
|
||||
* known tag to optimize network bandwidth.
|
||||
*/
|
||||
public void setLatestReceivedTagTime(RegattaAndRaceIdentifier raceIdentifier, TimePoint latestReceivedTagTime) {
|
||||
latestReceivedTagTimes.put(raceIdentifier, latestReceivedTagTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables the repeating request to receive also {@link com.sap.sailing.domain.common.dto.TagDTO tags} from
|
||||
* {@link SailingService}.
|
||||
*/
|
||||
public void enableTagRequests() {
|
||||
requestTags = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the repeating request to receive {@link com.sap.sailing.domain.common.dto.TagDTO tags} from
|
||||
* {@link SailingService}.
|
||||
*/
|
||||
public void disableTagRequests() {
|
||||
requestTags = false;
|
||||
}
|
||||
|
||||
+16
-3
@@ -12,6 +12,7 @@ import com.google.gwt.user.client.rpc.RemoteService;
|
||||
import com.sap.sailing.domain.abstractlog.Revokable;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogTagEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.state.ReadonlyRaceState;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent;
|
||||
import com.sap.sailing.domain.base.RaceColumn;
|
||||
import com.sap.sailing.domain.common.CompetitorDescriptor;
|
||||
@@ -121,6 +122,8 @@ import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.Util.Pair;
|
||||
import com.sap.sse.common.Util.Triple;
|
||||
import com.sap.sse.common.mail.MailException;
|
||||
import com.sap.sse.common.media.MediaTagConstants;
|
||||
import com.sap.sse.filestorage.FileStorageService;
|
||||
import com.sap.sse.gwt.client.ServerInfoDTO;
|
||||
import com.sap.sse.gwt.client.filestorage.FileStorageManagementGwtService;
|
||||
import com.sap.sse.gwt.client.media.ImageDTO;
|
||||
@@ -197,13 +200,23 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS
|
||||
|
||||
RaceTimesInfoDTO getRaceTimesInfo(RegattaAndRaceIdentifier raceIdentifier);
|
||||
|
||||
RaceTimesInfoDTO getRaceTimesInfoIncludingTags(RegattaAndRaceIdentifier raceIdentifier,
|
||||
TimePoint latestReceivedTagTime);
|
||||
/**
|
||||
* Returns {@link RaceTimesInfoDTO race times info} for specified race (<code>raceIdentifier</code>) including
|
||||
* {@link RaceLogTagEvent tag events} since received timestamp (<code>searchSince</code>). Loads tags from
|
||||
* {@link ReadonlyRaceState cache} instead of scanning the whole {@link RaceLog} every request.
|
||||
*/
|
||||
RaceTimesInfoDTO getRaceTimesInfoIncludingTags(RegattaAndRaceIdentifier raceIdentifier, TimePoint searchSince);
|
||||
|
||||
List<RaceTimesInfoDTO> getRaceTimesInfos(Collection<RegattaAndRaceIdentifier> raceIdentifiers);
|
||||
|
||||
/**
|
||||
* Collects besides {@link RaceTimesInfoDTO race times infos} public {@link RaceLogTagEvent tag events} from
|
||||
* {@link ReadonlyRaceState cache} and compares the <code>createdAt</code> timepoint to the received
|
||||
* <code>searchSince</code> timepoint. Returns {@link RaceTimesInfoDTO race times infos} including
|
||||
* {@link RaceLogTagEvent public tag events} since the latest client-side received tag.
|
||||
*/
|
||||
List<RaceTimesInfoDTO> getRaceTimesInfosIncludingTags(Collection<RegattaAndRaceIdentifier> raceIdentifiers,
|
||||
Map<RegattaAndRaceIdentifier, TimePoint> latestReceivedTagTimes);
|
||||
Map<RegattaAndRaceIdentifier, TimePoint> searchSinceMap);
|
||||
|
||||
CoursePositionsDTO getCoursePositions(RegattaAndRaceIdentifier raceIdentifier, Date date);
|
||||
|
||||
|
||||
+2
-3
@@ -240,15 +240,14 @@ public interface SailingServiceAsync extends ServerInfoRetriever, FileStorageMan
|
||||
|
||||
void getRaceTimesInfo(RegattaAndRaceIdentifier raceIdentifier, AsyncCallback<RaceTimesInfoDTO> callback);
|
||||
|
||||
void getRaceTimesInfoIncludingTags(RegattaAndRaceIdentifier raceIdentifier, TimePoint latestReceivedTagTime,
|
||||
void getRaceTimesInfoIncludingTags(RegattaAndRaceIdentifier raceIdentifier, TimePoint searchSince,
|
||||
AsyncCallback<RaceTimesInfoDTO> callback);
|
||||
|
||||
void getRaceTimesInfos(Collection<RegattaAndRaceIdentifier> raceIdentifiers,
|
||||
AsyncCallback<List<RaceTimesInfoDTO>> callback);
|
||||
|
||||
void getRaceTimesInfosIncludingTags(Collection<RegattaAndRaceIdentifier> raceIdentifiers,
|
||||
Map<RegattaAndRaceIdentifier, TimePoint> latestReceivedTagTimes,
|
||||
AsyncCallback<List<RaceTimesInfoDTO>> callback);
|
||||
Map<RegattaAndRaceIdentifier, TimePoint> searchSinceMap, AsyncCallback<List<RaceTimesInfoDTO>> callback);
|
||||
|
||||
void getCoursePositions(RegattaAndRaceIdentifier raceIdentifier, Date date,
|
||||
AsyncCallback<CoursePositionsDTO> asyncCallback);
|
||||
|
||||
+8
-19
@@ -7,50 +7,40 @@ import com.google.gwt.json.client.JSONArray;
|
||||
import com.google.gwt.json.client.JSONBoolean;
|
||||
import com.google.gwt.json.client.JSONObject;
|
||||
import com.google.gwt.json.client.JSONString;
|
||||
import com.sap.sailing.gwt.ui.client.GwtJsonDeSerializer;
|
||||
|
||||
/**
|
||||
* Serializes and deserializes {@link TagButton tag-buttons} to save them in the {@link com.sap.sse.security.UserStore
|
||||
* UserStore}.
|
||||
*/
|
||||
// TODO: Don't use key for tag-buttons, save array directly instead.
|
||||
public class TagButtonJsonDeSerializer implements GwtJsonDeSerializer<List<TagButton>> {
|
||||
public class TagButtonJsonDeSerializer {
|
||||
|
||||
private static final String FIELD_TAG_BUTTONS = "tagButtons";
|
||||
private static final String FIELD_BUTTON_NAME = "buttonName";
|
||||
private static final String FIELD_TAG = "tag";
|
||||
private static final String FIELD_COMMENT = "comment";
|
||||
private static final String FIELD_IMAGE_URL = "imageURL";
|
||||
private static final String FIELD_VISIBLE_FOR_PUBLIC = "public";
|
||||
|
||||
@Override
|
||||
public JSONObject serialize(List<TagButton> tagButtons) {
|
||||
JSONObject result = new JSONObject();
|
||||
|
||||
JSONArray tagButtonsArray = new JSONArray();
|
||||
result.put(FIELD_TAG_BUTTONS, tagButtonsArray);
|
||||
|
||||
public JSONArray serialize(List<TagButton> tagButtons) {
|
||||
JSONArray result = new JSONArray();
|
||||
int i = 0;
|
||||
for (TagButton button : tagButtons) {
|
||||
JSONObject tagButtonObject = new JSONObject();
|
||||
tagButtonsArray.set(i++, tagButtonObject);
|
||||
tagButtonObject.put(FIELD_BUTTON_NAME, new JSONString(button.getText()));
|
||||
tagButtonObject.put(FIELD_TAG, new JSONString(button.getTag()));
|
||||
tagButtonObject.put(FIELD_COMMENT, new JSONString(button.getComment()));
|
||||
tagButtonObject.put(FIELD_IMAGE_URL, new JSONString(button.getImageURL()));
|
||||
tagButtonObject.put(FIELD_VISIBLE_FOR_PUBLIC, JSONBoolean.getInstance(button.isVisibleForPublic()));
|
||||
result.set(i++, tagButtonObject);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TagButton> deserialize(JSONObject rootObject) {
|
||||
List<TagButton> result = null;
|
||||
public List<TagButton> deserialize(JSONArray rootObject) {
|
||||
List<TagButton> result = new ArrayList<TagButton>();
|
||||
if (rootObject != null) {
|
||||
result = new ArrayList<TagButton>();
|
||||
JSONArray tagButtonsArray = (JSONArray) rootObject.get(FIELD_TAG_BUTTONS);
|
||||
for (int i = 0; i < tagButtonsArray.size(); i++) {
|
||||
JSONObject tagButtonValue = (JSONObject) tagButtonsArray.get(i);
|
||||
for (int i = 0; i < rootObject.size(); i++) {
|
||||
JSONObject tagButtonValue = (JSONObject) rootObject.get(i);
|
||||
JSONString tagButtonName = (JSONString) tagButtonValue.get(FIELD_BUTTON_NAME);
|
||||
JSONString tagButtonTag = (JSONString) tagButtonValue.get(FIELD_TAG);
|
||||
JSONString tagButtonComment = (JSONString) tagButtonValue.get(FIELD_COMMENT);
|
||||
@@ -63,5 +53,4 @@ public class TagButtonJsonDeSerializer implements GwtJsonDeSerializer<List<TagBu
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
+6
-6
@@ -1,6 +1,6 @@
|
||||
package com.sap.sailing.gwt.ui.raceboard.tagging;
|
||||
|
||||
import com.google.gwt.json.client.JSONObject;
|
||||
import com.google.gwt.json.client.JSONArray;
|
||||
import com.google.gwt.json.client.JSONParser;
|
||||
import com.google.gwt.json.client.JSONValue;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
@@ -18,7 +18,7 @@ import com.sap.sse.security.ui.client.UserService;
|
||||
*/
|
||||
public class TagButtonPanel extends FlowPanel {
|
||||
|
||||
private static final String USER_STORAGE_TAG_BUTTONS_KEY = "sailingAnalytics.raceBoard.tagButtons";
|
||||
private static final String USER_STORAGE_TAG_BUTTONS_KEY = "sailing.tags.buttons";
|
||||
|
||||
private final TagPanelStyle style = TagPanelResources.INSTANCE.style();
|
||||
|
||||
@@ -71,8 +71,8 @@ public class TagButtonPanel extends FlowPanel {
|
||||
if (result != null && !result.isEmpty()) {
|
||||
final TagButtonJsonDeSerializer deserializer = new TagButtonJsonDeSerializer();
|
||||
final JSONValue value = JSONParser.parseStrict(result);
|
||||
if (value.isObject() != null) {
|
||||
for (TagButton tagButton : deserializer.deserialize((JSONObject) value)) {
|
||||
if (value.isArray() != null) {
|
||||
for (TagButton tagButton : deserializer.deserialize((JSONArray) value)) {
|
||||
taggingPanel.addTagButton(tagButton);
|
||||
}
|
||||
}
|
||||
@@ -92,8 +92,8 @@ public class TagButtonPanel extends FlowPanel {
|
||||
*/
|
||||
protected void storeAllTagButtons() {
|
||||
TagButtonJsonDeSerializer serializer = new TagButtonJsonDeSerializer();
|
||||
JSONObject jsonObject = serializer.serialize(taggingPanel.getTagButtons());
|
||||
userService.setPreference(USER_STORAGE_TAG_BUTTONS_KEY, jsonObject.toString(), new AsyncCallback<Void>() {
|
||||
JSONArray jsonArray = serializer.serialize(taggingPanel.getTagButtons());
|
||||
userService.setPreference(USER_STORAGE_TAG_BUTTONS_KEY, jsonArray.toString(), new AsyncCallback<Void>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
Notification.notify(stringMessages.tagButtonNotSavable(), NotificationType.WARNING);
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ import com.sap.sse.security.ui.client.UserService;
|
||||
*/
|
||||
public class TagFilterPanel extends FlowPanel implements KeyUpHandler, Filter<TagDTO> {
|
||||
|
||||
private final static String LOCAL_STORAGE_TAGS_FILTER_SETS_KEY = "sailingAnalytics.raceBoard.tagsFilterSets";
|
||||
private final static String LOCAL_STORAGE_TAGS_FILTER_SETS_KEY = "sailing.tags.filtersets";
|
||||
|
||||
private final TagPanelStyle style = TagPanelResources.INSTANCE.style();
|
||||
|
||||
|
||||
-2
@@ -44,7 +44,6 @@ public class TagInputPanel extends FlowPanel {
|
||||
tagTextBox = new TextBox();
|
||||
tagTextBox.setStyleName(style.tagInputPanelTag());
|
||||
tagTextBox.setTitle(stringMessages.tagLabelTag());
|
||||
tagTextBox.getElement().setAttribute("maxlength", Integer.toString(TagDTO.MAX_TAG_LENGTH));
|
||||
tagTextBox.getElement().setPropertyString("placeholder", stringMessages.tagLabelTag());
|
||||
add(tagTextBox);
|
||||
|
||||
@@ -57,7 +56,6 @@ public class TagInputPanel extends FlowPanel {
|
||||
commentTextArea = new TextArea();
|
||||
commentTextArea.setStyleName(style.tagInputPanelComment());
|
||||
commentTextArea.setVisibleLines(4);
|
||||
commentTextArea.getElement().setAttribute("maxlength", Integer.toString(TagDTO.MAX_COMMENT_LENGTH));
|
||||
commentTextArea.setTitle(stringMessages.tagLabelComment());
|
||||
commentTextArea.getElement().setPropertyString("placeholder", stringMessages.tagLabelComment());
|
||||
add(commentTextArea);
|
||||
|
||||
+1
-1
@@ -70,7 +70,7 @@ public class TagPreviewPanel extends FlowPanel {
|
||||
protected void renderPreview(TagInputPanel inputPanel) {
|
||||
listContainingPreviewTag.removeAll(listContainingPreviewTag);
|
||||
listContainingPreviewTag.add(new TagDTO(inputPanel.getTag(), inputPanel.getComment(), inputPanel.getImageURL(),
|
||||
userService.getCurrentUser().getName(), inputPanel.isVisibleForPublic(),
|
||||
inputPanel.isVisibleForPublic(), userService.getCurrentUser().getName(),
|
||||
new MillisecondsTimePoint(taggingPanel.getTimerTime()), MillisecondsTimePoint.now()));
|
||||
tagPreviewCellList.setRowData(listContainingPreviewTag);
|
||||
|
||||
|
||||
+3
-4
@@ -56,13 +56,12 @@ import com.sap.sse.security.ui.shared.UserDTO;
|
||||
* so on. Best practice: The constructor of subcomponents of the TaggingPanel contains only the TaggingPanel as a
|
||||
* parameter. Every other required shared resource (string messages, service references, ...) can be requested from the
|
||||
* TaggingPanel itself.
|
||||
*
|
||||
* @author Julian Rendl, Henri Kohlberg
|
||||
*/
|
||||
// TODO: Add refresh button which resets lastReceivedTagTime
|
||||
// TODO: resize plus of "add tags" button
|
||||
// TODO: get URL params as constructor parameter and not from Window object
|
||||
// TODO: Goal: Show tags in time slider (add bugzilla bug)
|
||||
// TODO: Unit Tests (incl. concatenation)
|
||||
// TODO: use HTML storage as event provider to update other tabs when user modifies private tags (new bugzilla bug)
|
||||
// TODO: cache user settings and use observer pattern for cache
|
||||
public class TaggingPanel extends ComponentWithoutSettings
|
||||
implements RaceTimesInfoProviderListener, UserStatusEventHandler, TimeListener {
|
||||
@@ -243,7 +242,7 @@ public class TaggingPanel extends ComponentWithoutSettings
|
||||
boolean tagIsNewTag = true;
|
||||
// check if tag already exists
|
||||
for (TagDTO tagDTO : tagListProvider.getAllTags()) {
|
||||
if (tagDTO.equals(tag, comment, imageURL, userService.getCurrentUser().getName(), visibleForPublic,
|
||||
if (tagDTO.equals(tag, comment, imageURL, visibleForPublic, userService.getCurrentUser().getName(),
|
||||
new MillisecondsTimePoint(getTimerTime()))) {
|
||||
tagIsNewTag = false;
|
||||
break;
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@
|
||||
background-color: #efaa00;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 60%;
|
||||
background-size: 40%;
|
||||
}
|
||||
|
||||
.taggingPanel button.toggleEditState:hover {
|
||||
|
||||
+97
-38
@@ -63,6 +63,7 @@ import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.http.client.ClientProtocolException;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.authz.AuthorizationException;
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.osgi.framework.InvalidSyntaxException;
|
||||
import org.osgi.framework.ServiceReference;
|
||||
@@ -289,6 +290,9 @@ import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
|
||||
import com.sap.sailing.domain.common.security.Permission;
|
||||
import com.sap.sailing.domain.common.security.Permission.Mode;
|
||||
import com.sap.sailing.domain.common.sharding.ShardingType;
|
||||
import com.sap.sailing.domain.common.tagging.RaceLogNotFoundException;
|
||||
import com.sap.sailing.domain.common.tagging.ServiceNotFoundException;
|
||||
import com.sap.sailing.domain.common.tagging.TagAlreadyExistsException;
|
||||
import com.sap.sailing.domain.common.tracking.BravoFix;
|
||||
import com.sap.sailing.domain.common.tracking.GPSFix;
|
||||
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
|
||||
@@ -2234,17 +2238,11 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet
|
||||
return raceTimesInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link RaceTimesInfoDTO race times info} for specified race (<code>raceIdentifier</code>) including
|
||||
* {@link RaceLogTagEvent tag events} since received timestamp (<code>latestReceivedTagTime</code>). Loads tags from
|
||||
* {@link ReadonlyRaceState cache} instead of scanning the whole {@link RaceLog} every request.
|
||||
*/
|
||||
// TODO: rename latestReceivedTagTime to match role
|
||||
@Override
|
||||
public RaceTimesInfoDTO getRaceTimesInfoIncludingTags(RegattaAndRaceIdentifier raceIdentifier,
|
||||
TimePoint latestReceivedTagTime) {
|
||||
TimePoint searchSince) {
|
||||
RaceTimesInfoDTO raceTimesInfo = getRaceTimesInfo(raceIdentifier);
|
||||
raceTimesInfo.setTags(getService().getTaggingService().getPublicTags(raceIdentifier, latestReceivedTagTime));
|
||||
raceTimesInfo.setTags(getService().getTaggingService().getPublicTags(raceIdentifier, searchSince));
|
||||
return raceTimesInfo;
|
||||
}
|
||||
|
||||
@@ -2260,19 +2258,13 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet
|
||||
return raceTimesInfos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects besides {@link RaceTimesInfoDTO race times infos} public {@link RaceLogTagEvent tag events} from
|
||||
* {@link ReadonlyRaceState cache} and compares the <code>createdAt</code> timepoint to the received latest tag
|
||||
* creation timepoint. Returns {@link RaceTimesInfoDTO race times infos} including {@link RaceLogTagEvents public
|
||||
* tag events} since the latest client-side received tag.
|
||||
*/
|
||||
@Override
|
||||
public List<RaceTimesInfoDTO> getRaceTimesInfosIncludingTags(Collection<RegattaAndRaceIdentifier> raceIdentifiers,
|
||||
Map<RegattaAndRaceIdentifier, TimePoint> latestReceivedTagTimes) {
|
||||
Map<RegattaAndRaceIdentifier, TimePoint> searchSinceMap) {
|
||||
List<RaceTimesInfoDTO> raceTimesInfos = new ArrayList<RaceTimesInfoDTO>();
|
||||
for (RegattaAndRaceIdentifier raceIdentifier : raceIdentifiers) {
|
||||
RaceTimesInfoDTO raceTimesInfo = getRaceTimesInfoIncludingTags(raceIdentifier,
|
||||
latestReceivedTagTimes.get(raceIdentifier));
|
||||
searchSinceMap.get(raceIdentifier));
|
||||
if (raceTimesInfo != null) {
|
||||
raceTimesInfos.add(raceTimesInfo);
|
||||
}
|
||||
@@ -6476,12 +6468,27 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet
|
||||
public SuccessInfo addTag(String leaderboardName, String raceColumnName, String fleetName, String tag,
|
||||
String comment, String imageURL, boolean visibleForPublic, TimePoint raceTimepoint) {
|
||||
SuccessInfo successInfo = new SuccessInfo(true, null, null, null);
|
||||
boolean successful = getService().getTaggingService().addTag(leaderboardName, raceColumnName, fleetName, tag,
|
||||
comment, imageURL, visibleForPublic, raceTimepoint);
|
||||
if (!successful) {
|
||||
String message = serverStringMessages.get(getClientLocale(),
|
||||
getService().getTaggingService().getLastErrorCode().getCode());
|
||||
successInfo = new SuccessInfo(false, message, null, null);
|
||||
try {
|
||||
getService().getTaggingService().addTag(leaderboardName, raceColumnName, fleetName, tag, comment, imageURL,
|
||||
visibleForPublic, raceTimepoint);
|
||||
} catch (AuthorizationException e) {
|
||||
successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "missingAuthorization"),
|
||||
null, null);
|
||||
} catch (IllegalArgumentException e) {
|
||||
successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "invalidParameters"), null,
|
||||
null);
|
||||
} catch (RaceLogNotFoundException e) {
|
||||
successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "raceLogNotFound"), null,
|
||||
null);
|
||||
} catch (ServiceNotFoundException e) {
|
||||
successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "securityServiceNotFound"),
|
||||
null, null);
|
||||
} catch (TagAlreadyExistsException e) {
|
||||
successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "tagAlreadyExists"), null,
|
||||
null);
|
||||
} catch (Exception e) {
|
||||
successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "unknownError"), null,
|
||||
null);
|
||||
}
|
||||
return successInfo;
|
||||
}
|
||||
@@ -6489,12 +6496,26 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet
|
||||
@Override
|
||||
public SuccessInfo removeTag(String leaderboardName, String raceColumnName, String fleetName, TagDTO tag) {
|
||||
SuccessInfo successInfo = new SuccessInfo(true, null, null, null);
|
||||
boolean successful = getService().getTaggingService().removeTag(leaderboardName, raceColumnName, fleetName,
|
||||
tag);
|
||||
if (!successful) {
|
||||
String message = serverStringMessages.get(getClientLocale(),
|
||||
getService().getTaggingService().getLastErrorCode().getCode());
|
||||
successInfo = new SuccessInfo(false, message, null, null);
|
||||
try {
|
||||
getService().getTaggingService().removeTag(leaderboardName, raceColumnName, fleetName, tag);
|
||||
} catch (AuthorizationException e) {
|
||||
successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "missingAuthorization"),
|
||||
null, null);
|
||||
} catch (IllegalArgumentException e) {
|
||||
successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "invalidParameters"), null,
|
||||
null);
|
||||
} catch (NotRevokableException e) {
|
||||
successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "tagNotRevokable"), null,
|
||||
null);
|
||||
} catch (RaceLogNotFoundException e) {
|
||||
successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "raceLogNotFound"), null,
|
||||
null);
|
||||
} catch (ServiceNotFoundException e) {
|
||||
successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "securityServiceNotFound"),
|
||||
null, null);
|
||||
} catch (Exception e) {
|
||||
successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "unknownError"), null,
|
||||
null);
|
||||
}
|
||||
return successInfo;
|
||||
}
|
||||
@@ -6503,12 +6524,30 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet
|
||||
public SuccessInfo updateTag(String leaderboardName, String raceColumnName, String fleetName, TagDTO tagToUpdate,
|
||||
String tag, String comment, String imageURL, boolean visibleForPublic) {
|
||||
SuccessInfo successInfo = new SuccessInfo(true, null, null, null);
|
||||
boolean successful = getService().getTaggingService().updateTag(leaderboardName, raceColumnName, fleetName,
|
||||
tagToUpdate, tag, comment, imageURL, visibleForPublic);
|
||||
if (!successful) {
|
||||
String message = serverStringMessages.get(getClientLocale(),
|
||||
getService().getTaggingService().getLastErrorCode().getCode());
|
||||
successInfo = new SuccessInfo(false, message, null, null);
|
||||
try {
|
||||
getService().getTaggingService().updateTag(leaderboardName, raceColumnName, fleetName, tagToUpdate, tag,
|
||||
comment, imageURL, visibleForPublic);
|
||||
} catch (AuthorizationException e) {
|
||||
successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "missingAuthorization"),
|
||||
null, null);
|
||||
} catch (IllegalArgumentException e) {
|
||||
successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "invalidParameters"), null,
|
||||
null);
|
||||
} catch (NotRevokableException e) {
|
||||
successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "tagNotRevokable"), null,
|
||||
null);
|
||||
} catch (RaceLogNotFoundException e) {
|
||||
successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "raceLogNotFound"), null,
|
||||
null);
|
||||
} catch (ServiceNotFoundException e) {
|
||||
successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "securityServiceNotFound"),
|
||||
null, null);
|
||||
} catch (TagAlreadyExistsException e) {
|
||||
successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "tagAlreadyExists"), null,
|
||||
null);
|
||||
} catch (Exception e) {
|
||||
successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "unknownError"), null,
|
||||
null);
|
||||
}
|
||||
return successInfo;
|
||||
}
|
||||
@@ -6516,19 +6555,39 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet
|
||||
@Override
|
||||
public List<TagDTO> getAllTags(String leaderboardName, String raceColumnName, String fleetName) {
|
||||
List<TagDTO> result = new ArrayList<TagDTO>();
|
||||
result.addAll(getService().getTaggingService().getPrivateTags(leaderboardName, raceColumnName, fleetName));
|
||||
result.addAll(getService().getTaggingService().getPublicTags(leaderboardName, raceColumnName, fleetName));
|
||||
try {
|
||||
result.addAll(getService().getTaggingService().getPublicTags(leaderboardName, raceColumnName, fleetName));
|
||||
} catch (RaceLogNotFoundException e) {
|
||||
// do nothing and try to return as much tags as possible (private tags)
|
||||
}
|
||||
try {
|
||||
result.addAll(getService().getTaggingService().getPrivateTags(leaderboardName, raceColumnName, fleetName));
|
||||
} catch (ServiceNotFoundException e) {
|
||||
// do nothing and try to return as much tags as possible (public tags)
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TagDTO> getPublicTags(String leaderboardName, String raceColumnName, String fleetName) {
|
||||
return getService().getTaggingService().getPublicTags(leaderboardName, raceColumnName, fleetName);
|
||||
List<TagDTO> result = new ArrayList<TagDTO>();
|
||||
try {
|
||||
result.addAll(getService().getTaggingService().getPublicTags(leaderboardName, raceColumnName, fleetName));
|
||||
} catch (RaceLogNotFoundException e) {
|
||||
// do nothing as method will always return at least an empty list
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TagDTO> getPrivateTags(String leaderboardName, String raceColumnName, String fleetName) {
|
||||
return getService().getTaggingService().getPrivateTags(leaderboardName, raceColumnName, fleetName);
|
||||
List<TagDTO> result = new ArrayList<TagDTO>();
|
||||
try {
|
||||
result.addAll(getService().getTaggingService().getPrivateTags(leaderboardName, raceColumnName, fleetName));
|
||||
} catch (ServiceNotFoundException e) {
|
||||
// do nothing as method will always return at least an empty list
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+6
-11
@@ -4,14 +4,9 @@ slicingTimeRangeOutOfBounds=The TimeRange to slice is not part of the race
|
||||
slicingCouldNotObtainRace=Could not obtain sliced race
|
||||
slicingError=Error slicing race
|
||||
unknownError=Unknown error
|
||||
notLoggedIn=You are not logged in
|
||||
missingPermissions=Missing permissions
|
||||
securityServiceNotFound=Security service not found
|
||||
racelogNotFound=Racelog not found
|
||||
tagNotRevokable=This tag cannot be revoked
|
||||
tagAlreadyExists=Tag does already exist, duplicated tags are not allowed
|
||||
tagAlreadyRemoved=Tag cannot be removed twice!
|
||||
tagNotEmpty=Tag may not be empty
|
||||
timepointNotEmpty=Timepoint may not be empty
|
||||
tagTooLong=Tag is too long
|
||||
commentToLong=Comment is too long
|
||||
missingAuthorization=You are not logged in or missing the required permission!
|
||||
securityServiceNotFound=Security service not found!
|
||||
raceLogNotFound=Racelog not found!
|
||||
tagNotRevokable=This tag cannot be revoked!
|
||||
tagAlreadyExists=Tag does already exist, duplicated tags are not allowed!
|
||||
invalidParameters=One of the given parameters does not have a valid value!
|
||||
+7
-12
@@ -3,15 +3,10 @@ slicingRaceColumnAlreadyUsedThe=Der Rennspaltenname ist in der Regatta bereits v
|
||||
slicingTimeRangeOutOfBounds=Die angegebene Zeitspanne ist ausserhalb des Rennens
|
||||
slicingCouldNotObtainRace=Das geschnittene Rennen konnte nicht gefunden werden
|
||||
slicingError=Fehler beim Schneiden des Rennens
|
||||
unknownError=Unbekannter Fehler
|
||||
notLoggedIn=Du bist nicht eingeloggt
|
||||
missingPermissions=Fehlende Berechtigung
|
||||
securityServiceNotFound=Sicherheits-Service konnte nicht gefunden werden
|
||||
racelogNotFound=Racelog konnte nicht gefunden werden
|
||||
tagNotRevokable=Dieser Tag ist nicht umkehrbar
|
||||
tagAlreadyExists=Dieser Tag existiert bereits
|
||||
tagAlreadyRemoved=Dieser Tag wurde bereits geloescht
|
||||
tagNotEmpty=Der Tag darf nicht leer sein
|
||||
timepointNotEmpty=Der Zeitpunkt darf nicht leer sein
|
||||
tagTooLong=Der Tag ist zu lang
|
||||
commentToLong=Der Kommentar ist zu lang
|
||||
unknownError=Unbekannter Fehler!
|
||||
missingAuthorization=Du bist nicht eingeloggt oder dir fehlen die benoetigten Informationen!
|
||||
securityServiceNotFound=Sicherheits-Service konnte nicht gefunden werden!
|
||||
raceLogNotFound=Racelog konnte nicht gefunden werden!
|
||||
tagNotRevokable=Dieser Tag ist nicht umkehrbar!
|
||||
tagAlreadyExists=Dieser Tag existiert bereits!
|
||||
invalidParameters=Einer der Parameter hat einen ungueltigen Wert!
|
||||
+69
-53
@@ -21,10 +21,14 @@ import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
import org.apache.shiro.authz.AuthorizationException;
|
||||
import org.json.simple.JSONArray;
|
||||
|
||||
import com.sap.sailing.domain.common.abstractlog.NotRevokableException;
|
||||
import com.sap.sailing.domain.common.dto.TagDTO;
|
||||
import com.sap.sailing.domain.common.racelog.RaceLogServletConstants;
|
||||
import com.sap.sailing.domain.common.tagging.RaceLogNotFoundException;
|
||||
import com.sap.sailing.domain.common.tagging.TagAlreadyExistsException;
|
||||
import com.sap.sailing.server.gateway.jaxrs.AbstractSailingServerResource;
|
||||
import com.sap.sailing.server.tagging.TagDTODeSerializer;
|
||||
import com.sap.sailing.server.tagging.TaggingService;
|
||||
@@ -68,32 +72,31 @@ public class TagsResource extends AbstractSailingServerResource {
|
||||
@PathParam(RaceLogServletConstants.PARAMS_RACE_COLUMN_NAME) String raceColumnName,
|
||||
@PathParam(RaceLogServletConstants.PARAMS_RACE_FLEET_NAME) String fleetName,
|
||||
@DefaultValue("both") @QueryParam("visibility") String visibility) {
|
||||
|
||||
boolean lookForPublic = visibility.equalsIgnoreCase("both") || visibility.equalsIgnoreCase("public");
|
||||
boolean lookForPrivate = visibility.equalsIgnoreCase("both") || visibility.equalsIgnoreCase("private");
|
||||
|
||||
Response response;
|
||||
TaggingService taggingService = getService().getTaggingService();
|
||||
if (taggingService != null) {
|
||||
List<TagDTO> tags = new ArrayList<TagDTO>();
|
||||
|
||||
final TaggingService taggingService = getService().getTaggingService();
|
||||
final List<TagDTO> tags = new ArrayList<TagDTO>();
|
||||
final boolean lookForPublic = visibility.equalsIgnoreCase("both") || visibility.equalsIgnoreCase("public");
|
||||
final boolean lookForPrivate = visibility.equalsIgnoreCase("both") || visibility.equalsIgnoreCase("private");
|
||||
try {
|
||||
if (lookForPublic) {
|
||||
Util.addAll(taggingService.getPublicTags(leaderboardName, raceColumnName, fleetName), tags);
|
||||
}
|
||||
|
||||
if (lookForPrivate) {
|
||||
Util.addAll(taggingService.getPrivateTags(leaderboardName, raceColumnName, fleetName), tags);
|
||||
try {
|
||||
Util.addAll(taggingService.getPrivateTags(leaderboardName, raceColumnName, fleetName), tags);
|
||||
} catch (AuthorizationException e) {
|
||||
// do nothing when user is not logged in
|
||||
}
|
||||
}
|
||||
|
||||
// remove revoked tags from result
|
||||
tags.removeIf(tag -> tag.getRevokedAt() != null && tag.getRevokedAt().asMillis() != 0);
|
||||
|
||||
JSONArray jsonTags = serializer.serialize(tags);
|
||||
response = Response.ok(jsonTags.toJSONString()).type(APPLICATION_JSON_UTF8).build();
|
||||
} else {
|
||||
response = Response.status(Status.INTERNAL_SERVER_ERROR).type(TEXT_PLAIN_UTF8)
|
||||
.entity("Tagging Service not found!").build();
|
||||
logger.warning("Tagging Service not found!");
|
||||
} catch (RaceLogNotFoundException e) {
|
||||
response = Response.status(Status.BAD_REQUEST).type(TEXT_PLAIN_UTF8).build();
|
||||
} catch (Exception e) {
|
||||
logger.warning("Could not load tags! " + e.getMessage());
|
||||
response = Response.status(Status.INTERNAL_SERVER_ERROR).type(TEXT_PLAIN_UTF8).build();
|
||||
}
|
||||
return response;
|
||||
}
|
||||
@@ -106,11 +109,12 @@ public class TagsResource extends AbstractSailingServerResource {
|
||||
* @param visible
|
||||
* default is <code>false</code>
|
||||
*
|
||||
* @return status 201 (created) if creation was successful, otherwise 400 (bad request)
|
||||
* @return status 201 (created) if creation was successful, otherwise 400 (bad request) 401 (unauthorized) or 500
|
||||
* (internal server error)
|
||||
* @see TaggingService#addTag(String, String, String, String, String, String, boolean, TimePoint)
|
||||
*/
|
||||
@POST
|
||||
@Produces({ APPLICATION_JSON_UTF8, TEXT_PLAIN_UTF8 })
|
||||
@Produces({ TEXT_PLAIN_UTF8 })
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
public Response createTag(@Context UriInfo uriInfo,
|
||||
@PathParam(RaceLogServletConstants.PARAMS_LEADERBOARD_NAME) String leaderboardName,
|
||||
@@ -119,15 +123,18 @@ public class TagsResource extends AbstractSailingServerResource {
|
||||
@FormParam("comment") String comment, @FormParam("image") String imageURL,
|
||||
@FormParam("public") boolean visibleForPublic, @FormParam("raceTimepoint") long raceTimepoint) {
|
||||
Response response;
|
||||
TaggingService taggingService = getService().getTaggingService();
|
||||
boolean successful = taggingService.addTag(leaderboardName, raceColumnName, fleetName, tag, comment, imageURL,
|
||||
visibleForPublic, new MillisecondsTimePoint(raceTimepoint));
|
||||
if (successful) {
|
||||
final TaggingService taggingService = getService().getTaggingService();
|
||||
try {
|
||||
taggingService.addTag(leaderboardName, raceColumnName, fleetName, tag, comment, imageURL, visibleForPublic,
|
||||
new MillisecondsTimePoint(raceTimepoint));
|
||||
response = Response.created(uriInfo.getRequestUri()).build();
|
||||
} else {
|
||||
String errorMessage = taggingService.getLastErrorCode().getMessage();
|
||||
response = Response.status(Status.BAD_REQUEST).type(TEXT_PLAIN_UTF8).entity(errorMessage).build();
|
||||
logger.warning("Could not save tag! " + errorMessage);
|
||||
} catch (IllegalArgumentException | RaceLogNotFoundException | TagAlreadyExistsException e) {
|
||||
response = Response.status(Status.BAD_REQUEST).type(TEXT_PLAIN_UTF8).build();
|
||||
} catch (AuthorizationException e) {
|
||||
response = Response.status(Status.UNAUTHORIZED).type(TEXT_PLAIN_UTF8).build();
|
||||
} catch (Exception e) {
|
||||
logger.warning("Could not save tag! " + e.getMessage());
|
||||
response = Response.status(Status.INTERNAL_SERVER_ERROR).type(TEXT_PLAIN_UTF8).build();
|
||||
}
|
||||
return response;
|
||||
}
|
||||
@@ -135,12 +142,13 @@ public class TagsResource extends AbstractSailingServerResource {
|
||||
/**
|
||||
* Removes tag given as json string.
|
||||
*
|
||||
* @return status 204 (no content) if deletion was successful, otherwise 400 (bad request)
|
||||
* @return status 204 (no content) if deletion was successful, otherwise 400 (bad request), 401 (unauthorized) or
|
||||
* 500 (internal server error)
|
||||
* @see TagDTO
|
||||
* @see TaggingService#removeTag(String, String, String, TagDTO)
|
||||
*/
|
||||
@DELETE
|
||||
@Produces({ APPLICATION_JSON_UTF8, TEXT_PLAIN_UTF8 })
|
||||
@Produces({ TEXT_PLAIN_UTF8 })
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
public Response deleteTag(@PathParam(RaceLogServletConstants.PARAMS_LEADERBOARD_NAME) String leaderboardName,
|
||||
@PathParam(RaceLogServletConstants.PARAMS_RACE_COLUMN_NAME) String raceColumnName,
|
||||
@@ -149,13 +157,16 @@ public class TagsResource extends AbstractSailingServerResource {
|
||||
Response response;
|
||||
TagDTO tagToRemove = serializer.deserializeTag(tagJson);
|
||||
TaggingService taggingService = getService().getTaggingService();
|
||||
boolean successful = taggingService.removeTag(leaderboardName, raceColumnName, fleetName, tagToRemove);
|
||||
if (successful) {
|
||||
try {
|
||||
taggingService.removeTag(leaderboardName, raceColumnName, fleetName, tagToRemove);
|
||||
response = Response.noContent().build();
|
||||
} else {
|
||||
String errorMessage = taggingService.getLastErrorCode().getMessage();
|
||||
response = Response.status(Status.BAD_REQUEST).type(TEXT_PLAIN_UTF8).entity(errorMessage).build();
|
||||
logger.warning("Could not remove tag! " + errorMessage);
|
||||
} catch (IllegalArgumentException | NotRevokableException | RaceLogNotFoundException e) {
|
||||
response = Response.status(Status.BAD_REQUEST).type(TEXT_PLAIN_UTF8).build();
|
||||
} catch (AuthorizationException e) {
|
||||
response = Response.status(Status.UNAUTHORIZED).type(TEXT_PLAIN_UTF8).build();
|
||||
} catch (Exception e) {
|
||||
logger.warning("Could not remove tag! " + e.getMessage());
|
||||
response = Response.status(Status.INTERNAL_SERVER_ERROR).type(TEXT_PLAIN_UTF8).build();
|
||||
}
|
||||
return response;
|
||||
}
|
||||
@@ -168,12 +179,13 @@ public class TagsResource extends AbstractSailingServerResource {
|
||||
* @param tag
|
||||
* may not be empty
|
||||
*
|
||||
* @return status 204 (no content) if update was successful, otherwise 400 (bad request)
|
||||
* @return status 204 (no content) if update was successful, otherwise 400 (bad request), 401 (unauthorized) or 500
|
||||
* (internal server error)
|
||||
* @see TagDTO
|
||||
* @see TaggingService#updateTag(String, String, String, TagDTO, String, String, String, boolean)
|
||||
*/
|
||||
@PUT
|
||||
@Produces({ APPLICATION_JSON_UTF8, TEXT_PLAIN_UTF8 })
|
||||
@Produces({ TEXT_PLAIN_UTF8 })
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
public Response updateTag(@PathParam(RaceLogServletConstants.PARAMS_LEADERBOARD_NAME) String leaderboardName,
|
||||
@PathParam(RaceLogServletConstants.PARAMS_RACE_COLUMN_NAME) String raceColumnName,
|
||||
@@ -182,28 +194,32 @@ public class TagsResource extends AbstractSailingServerResource {
|
||||
@FormParam("comment") String commentParam, @FormParam("image") String imageURLParam,
|
||||
@FormParam("public") String visibleForPublicParam) {
|
||||
Response response;
|
||||
boolean successful = true;
|
||||
TagDTO tagToUpdate = serializer.deserializeTag(tagJson);
|
||||
TaggingService taggingService = getService().getTaggingService();
|
||||
final TagDTO tagToUpdate = serializer.deserializeTag(tagJson);
|
||||
final TaggingService taggingService = getService().getTaggingService();
|
||||
|
||||
// only call update method when any of the parameters needs to be changed
|
||||
if (tagParam != null || commentParam != null || imageURLParam != null || visibleForPublicParam != null) {
|
||||
// keep old values when no new values are provided
|
||||
String tag = tagParam == null ? tagToUpdate.getTag() : tagParam;
|
||||
String comment = commentParam == null ? tagToUpdate.getComment() : commentParam;
|
||||
String imageURL = imageURLParam == null ? tagToUpdate.getImageURL() : imageURLParam;
|
||||
boolean visibleForPublic = visibleForPublicParam == null ? tagToUpdate.isVisibleForPublic()
|
||||
: visibleForPublicParam.equalsIgnoreCase("true") ? true : false;
|
||||
|
||||
successful = taggingService.updateTag(leaderboardName, raceColumnName, fleetName, tagToUpdate, tag, comment,
|
||||
imageURL, visibleForPublic);
|
||||
}
|
||||
if (successful) {
|
||||
response = Response.noContent().build();
|
||||
String tag = (tagParam == null ? tagToUpdate.getTag() : tagParam);
|
||||
String comment = (commentParam == null ? tagToUpdate.getComment() : commentParam);
|
||||
String imageURL = (imageURLParam == null ? tagToUpdate.getImageURL() : imageURLParam);
|
||||
boolean visibleForPublic = (visibleForPublicParam == null ? tagToUpdate.isVisibleForPublic()
|
||||
: visibleForPublicParam.equalsIgnoreCase("true") ? true : false);
|
||||
try {
|
||||
taggingService.updateTag(leaderboardName, raceColumnName, fleetName, tagToUpdate, tag, comment,
|
||||
imageURL, visibleForPublic);
|
||||
response = Response.noContent().build();
|
||||
} catch (IllegalArgumentException | NotRevokableException | RaceLogNotFoundException
|
||||
| TagAlreadyExistsException e) {
|
||||
response = Response.status(Status.BAD_REQUEST).type(TEXT_PLAIN_UTF8).build();
|
||||
} catch (AuthorizationException e) {
|
||||
response = Response.status(Status.UNAUTHORIZED).type(TEXT_PLAIN_UTF8).build();
|
||||
} catch (Exception e) {
|
||||
logger.warning("Could not update tag! " + e.getMessage());
|
||||
response = Response.status(Status.INTERNAL_SERVER_ERROR).type(TEXT_PLAIN_UTF8).build();
|
||||
}
|
||||
} else {
|
||||
String errorMessage = taggingService.getLastErrorCode().getMessage();
|
||||
response = Response.status(Status.BAD_REQUEST).type(TEXT_PLAIN_UTF8).entity(errorMessage).build();
|
||||
logger.warning("Could not update tag! " + errorMessage);
|
||||
response = Response.noContent().build();
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
@@ -606,9 +606,16 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch
|
||||
PolarDataService getPolarDataService();
|
||||
|
||||
SimulationService getSimulationService();
|
||||
|
||||
|
||||
/**
|
||||
* {@link TaggingService} can be used to perform all CRUD operations on private and pulic
|
||||
* {@link com.sap.sailing.domain.common.dto.TagDTO tags}. This service is used by the REST API and GWT client and
|
||||
* needs to perform independant of the requesting resource.
|
||||
*
|
||||
* @return instance of TaggingService
|
||||
*/
|
||||
TaggingService getTaggingService();
|
||||
|
||||
|
||||
RaceTracker getRaceTrackerById(Object id);
|
||||
|
||||
/**
|
||||
|
||||
+2
-2
@@ -25,7 +25,7 @@ public class TagDTODeSerializer {
|
||||
public static final String FIELD_CREATED_AT = "createdAt";
|
||||
public static final String FIELD_REVOKED_AT = "revokedAt";
|
||||
|
||||
private static final String UNIQUE_KEY_PREFIX = "Tags:";
|
||||
private static final String UNIQUE_KEY_PREFIX = "sailing.tags.";
|
||||
|
||||
private final JSONParser parser = new JSONParser();
|
||||
|
||||
@@ -82,7 +82,7 @@ public class TagDTODeSerializer {
|
||||
TimePoint raceTimePoint = deserilizeTimePoint((Long) (jsonObject.get(FIELD_RACE_TIMEPOINT)));
|
||||
TimePoint createdAt = deserilizeTimePoint((Long) (jsonObject.get(FIELD_CREATED_AT)));
|
||||
TimePoint revokedAt = deserilizeTimePoint((Long) (jsonObject.get(FIELD_REVOKED_AT)));
|
||||
return new TagDTO(tag, comment, imageURL, username, visibleForPublic, raceTimePoint, createdAt, revokedAt);
|
||||
return new TagDTO(tag, comment, imageURL, visibleForPublic, username, raceTimePoint, createdAt, revokedAt);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
+72
-63
@@ -2,56 +2,28 @@ package com.sap.sailing.server.tagging;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.shiro.authz.AuthorizationException;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
import com.sap.sailing.domain.common.abstractlog.NotRevokableException;
|
||||
import com.sap.sailing.domain.common.dto.TagDTO;
|
||||
import com.sap.sailing.domain.common.tagging.RaceLogNotFoundException;
|
||||
import com.sap.sailing.domain.common.tagging.ServiceNotFoundException;
|
||||
import com.sap.sailing.domain.common.tagging.TagAlreadyExistsException;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
// TODO: Add Javadoc, what does TaggingService do?
|
||||
// TODO: Replace error handling by throwing exceptions, see "topleveltranslations.json"
|
||||
// TODO: Remove public at interfaces
|
||||
// TODO: CommentTooLong
|
||||
// TODO: Remove max length
|
||||
// TODO: rename latestReceivedTagTime to match role
|
||||
// TODO: remove entry in settings if there are no private tags for this race anymore
|
||||
// TODO: rename keys to naming pattern (ssailing.tags....)
|
||||
// TODO: see "translation_v2.json" for new translation files
|
||||
// TODO: use document settings id for tags/tag-buttons/... as race identifier
|
||||
/**
|
||||
* This service is used to perform all CRUD operations on {@link TagDTO tags} and is used by the
|
||||
* {@link com.sap.sailing.server.gateway.jaxrs.api.TagsResource REST API} for mobile apps as well as the GWT client via
|
||||
* the {@link com.sap.sailing.gwt.ui.server.SailingServiceImpl SailingService}.
|
||||
*
|
||||
* @author Henri Kohlberg
|
||||
*/
|
||||
public interface TaggingService {
|
||||
|
||||
/**
|
||||
* Enum used to identify issues.
|
||||
*/
|
||||
public enum ErrorCode {
|
||||
UNKNOWN_ERROR("unknownError", "Unknown error"),
|
||||
NOT_LOGGED_IN("notLoggedIn", "You are not logged in"),
|
||||
MISSING_PERMISSIONS("missingPermissions", "Missing permissions"),
|
||||
SECURITY_SERIVCE_NOT_FOUND("securityServiceNotFound", "Security service not found"),
|
||||
RACELOG_NOT_FOUND("racelogNotFound", "Racelog not found"),
|
||||
TAG_NOT_REVOKABLE("tagNotRevokable", "This tag cannot be revoked"),
|
||||
TAG_ALREADY_EXISTS("tagAlreadyExists", "Tag does already exist, duplicated tags are not allowed"),
|
||||
TAG_ALREADY_REMOVED("tagAlreadyRemoved", "Tag cannot be removed twice!"),
|
||||
TAG_NOT_EMPTY("tagNotEmpty", "Tag may not be empty"),
|
||||
TIMEPOINT_NOT_EMPTY("timepointNotEmpty", "Timepoint may not be empty"),
|
||||
TAG_TOO_LONG("tagTooLong", "Tag is too long"),
|
||||
COMMENT_TOO_LONG("commentToLong", "Comment is too long");
|
||||
|
||||
private final String code;
|
||||
private final String message;
|
||||
|
||||
ErrorCode(String code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves given properties as tag for given race. Checks if all parameters are valid and all required parameters are
|
||||
* set.
|
||||
@@ -74,10 +46,21 @@ public interface TaggingService {
|
||||
* tag will be saved in {@link com.sap.sse.security.UserStore UserStore} (only visible for the creator)
|
||||
* @param raceTimepoint
|
||||
* timepoint in race when user created tag, must <b>NOT</b> be <code>null</code>
|
||||
* @return <code>true</code> if tag was saved successfully, otherwise <code>false</code>
|
||||
* @throws AuthorizationException
|
||||
* thrown if user is not logged in or is missing permissions
|
||||
* @throws IllegalArgumentException
|
||||
* thrown if one of the required parameters has an invalid value
|
||||
* @throws RaceLogNotFoundException
|
||||
* thrown if racelog cannot be found (e.g. when <code>leaderboardName</code>,
|
||||
* <code>raceColumnName</code> or <code>fleetName</code> are missing)
|
||||
* @throws ServiceNotFoundException
|
||||
* thrown if security service cannot be found
|
||||
* @throws TagAlreadyExistsException
|
||||
* thrown if tag already exists
|
||||
*/
|
||||
public boolean addTag(String leaderboardName, String raceColumnName, String fleetName, String tag, String comment,
|
||||
String imageURL, boolean visibleForPublic, TimePoint raceTimepoint);
|
||||
void addTag(String leaderboardName, String raceColumnName, String fleetName, String tag, String comment,
|
||||
String imageURL, boolean visibleForPublic, TimePoint raceTimepoint) throws AuthorizationException,
|
||||
IllegalArgumentException, RaceLogNotFoundException, ServiceNotFoundException, TagAlreadyExistsException;
|
||||
|
||||
/**
|
||||
* Removes public {@link TagDTO tag} from {@link com.sap.sailing.domain.abstractlog.race.RaceLog RaceLog} and
|
||||
@@ -91,9 +74,21 @@ public interface TaggingService {
|
||||
* required to identify {@link RaceLog}, must <b>NOT</b> be <code>null</code>
|
||||
* @param tag
|
||||
* tag to remove
|
||||
* @return <code>true</code> if tag was removed successfully, otherwise <code>false</code>
|
||||
* @throws AuthorizationException
|
||||
* thrown if user is not logged in or is missing permissions
|
||||
* @throws IllegalArgumentException
|
||||
* thrown if one of the required parameters has an invalid value
|
||||
* @throws NotRevokableException
|
||||
* thrown if tag is public and not revokable from racelog
|
||||
* @throws RaceLogNotFoundException
|
||||
* thrown if racelog cannot be found (e.g. when <code>leaderboardName</code>,
|
||||
* <code>raceColumnName</code> or <code>fleetName</code> are missing)
|
||||
* @throws ServiceNotFoundException
|
||||
* thrown if security service cannot be found
|
||||
*/
|
||||
public boolean removeTag(String leaderboardName, String raceColumnName, String fleetName, TagDTO tag);
|
||||
void removeTag(String leaderboardName, String raceColumnName, String fleetName, TagDTO tag)
|
||||
throws AuthorizationException, IllegalArgumentException, NotRevokableException, RaceLogNotFoundException,
|
||||
ServiceNotFoundException;
|
||||
|
||||
/**
|
||||
* Updates given <code>tagToUpdate</code> with the given parameters <code>tag</code>, <code>comment</code>,
|
||||
@@ -115,10 +110,24 @@ public interface TaggingService {
|
||||
* new iamge URL
|
||||
* @param visibleForPublic
|
||||
* new privacy status
|
||||
* @return <code>true</code> if tag was updated successfully, otherwise <code>false</code>
|
||||
* @throws AuthorizationException
|
||||
* thrown if user is not logged in or is missing permissions
|
||||
* @throws IllegalArgumentException
|
||||
* thrown if one of the required parameters has an invalid value
|
||||
* @throws NotRevokableException
|
||||
* thrown if tag is public and not revokable from racelog
|
||||
* @throws TagAlreadyExistsException
|
||||
* thrown if tag already exists
|
||||
* @throws RaceLogNotFoundException
|
||||
* thrown if racelog cannot be found (e.g. when <code>leaderboardName</code>,
|
||||
* <code>raceColumnName</code> or <code>fleetName</code> are missing)
|
||||
* @throws ServiceNotFoundException
|
||||
* thrown if security service cannot be found
|
||||
*/
|
||||
public boolean updateTag(String leaderboardName, String raceColumnName, String fleetName, TagDTO tagToUpdate,
|
||||
String tag, String comment, String imageURL, boolean visibleForPublic);
|
||||
void updateTag(String leaderboardName, String raceColumnName, String fleetName, TagDTO tagToUpdate, String tag,
|
||||
String comment, String imageURL, boolean visibleForPublic)
|
||||
throws AuthorizationException, IllegalArgumentException, NotRevokableException, RaceLogNotFoundException,
|
||||
ServiceNotFoundException, TagAlreadyExistsException;
|
||||
|
||||
/**
|
||||
* Returns all public tags for the specified race.
|
||||
@@ -131,18 +140,24 @@ public interface TaggingService {
|
||||
* required to identify {@link RaceLog}, must <b>NOT</b> be <code>null</code>
|
||||
* @return list of {@link TagDTO tags}, empty list in case an error occurs or there are no tags available but
|
||||
* <b>never null</b>!
|
||||
* @throws RaceLogNotFoundException
|
||||
* thrown if racelog cannot be found (e.g. when <code>leaderboardName</code>,
|
||||
* <code>raceColumnName</code> or <code>fleetName</code> are missing)
|
||||
*/
|
||||
public List<TagDTO> getPublicTags(String leaderboardName, String raceColumnName, String fleetName);
|
||||
List<TagDTO> getPublicTags(String leaderboardName, String raceColumnName, String fleetName)
|
||||
throws RaceLogNotFoundException;
|
||||
|
||||
/**
|
||||
* Returns all public tags since the given <code>latestReceivedTagTime</code> for the specified race.
|
||||
* Returns all public tags since the given <code>searchSinceTimePoint</code> for the specified race.
|
||||
*
|
||||
* @param raceIdentifier
|
||||
* required to identify {@link RaceLog}, must <b>NOT</b> be <code>null</code>
|
||||
* @param searchSince
|
||||
* tags will only be returned if they got created after this time point
|
||||
* @return list of {@link TagDTO tags}, empty list in case an error occurs or there are no tags available but
|
||||
* <b>never null</b>!
|
||||
*/
|
||||
public List<TagDTO> getPublicTags(RegattaAndRaceIdentifier raceIdentifier, TimePoint latestReceivedTagTime);
|
||||
List<TagDTO> getPublicTags(RegattaAndRaceIdentifier raceIdentifier, TimePoint searchSince);
|
||||
|
||||
/**
|
||||
* Returns all private tags of current user for the specified race.
|
||||
@@ -155,15 +170,9 @@ public interface TaggingService {
|
||||
* required to identify {@link RaceLog}, must <b>NOT</b> be <code>null</code>
|
||||
* @return list of {@link TagDTO tags}, empty list in case an error occurs or there are no tags available but
|
||||
* <b>never null</b>!
|
||||
* @throws ServiceNotFoundException
|
||||
* thrown if security service cannot be found
|
||||
*/
|
||||
public List<TagDTO> getPrivateTags(String leaderboardName, String raceColumnName, String fleetName);
|
||||
|
||||
/**
|
||||
* Returns the last error code of the current user. Needs to be converted into error message to display this message
|
||||
* to the user.
|
||||
*
|
||||
* @return last {@link ErrorCode error code} which occured if error is known, otherwise
|
||||
* {@link ErrorCode#UNKNOWN_ERROR unknown error}
|
||||
*/
|
||||
public ErrorCode getLastErrorCode();
|
||||
List<TagDTO> getPrivateTags(String leaderboardName, String raceColumnName, String fleetName)
|
||||
throws ServiceNotFoundException;
|
||||
}
|
||||
+160
-227
@@ -1,9 +1,7 @@
|
||||
package com.sap.sailing.server.tagging;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.authz.AuthorizationException;
|
||||
@@ -19,6 +17,9 @@ import com.sap.sailing.domain.common.abstractlog.NotRevokableException;
|
||||
import com.sap.sailing.domain.common.dto.TagDTO;
|
||||
import com.sap.sailing.domain.common.security.Permission;
|
||||
import com.sap.sailing.domain.common.security.Permission.Mode;
|
||||
import com.sap.sailing.domain.common.tagging.RaceLogNotFoundException;
|
||||
import com.sap.sailing.domain.common.tagging.ServiceNotFoundException;
|
||||
import com.sap.sailing.domain.common.tagging.TagAlreadyExistsException;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.server.RacingEventService;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
@@ -30,263 +31,209 @@ public class TaggingServiceImpl implements TaggingService {
|
||||
|
||||
private final RacingEventService racingService;
|
||||
private final TagDTODeSerializer serializer;
|
||||
private final Map<Subject, ErrorCode> lastErrorCodes;
|
||||
|
||||
public TaggingServiceImpl(RacingEventService racingService) {
|
||||
this.racingService = racingService;
|
||||
serializer = new TagDTODeSerializer();
|
||||
lastErrorCodes = new HashMap<Subject, ErrorCode>();
|
||||
}
|
||||
|
||||
private void setLastErrorCode(ErrorCode errorCode) {
|
||||
lastErrorCodes.put(SecurityUtils.getSubject(), errorCode);
|
||||
}
|
||||
|
||||
private String getCurrentUsername() {
|
||||
String result = null;
|
||||
/**
|
||||
* Returns current username.
|
||||
*
|
||||
* @throws AuthorizationException
|
||||
* @return username of current user
|
||||
*/
|
||||
private String getCurrentUsername() throws AuthorizationException {
|
||||
Object principal = SecurityUtils.getSubject().getPrincipal();
|
||||
if (principal != null) {
|
||||
result = principal.toString();
|
||||
} else {
|
||||
setLastErrorCode(ErrorCode.NOT_LOGGED_IN);
|
||||
if (principal == null) {
|
||||
throw new AuthorizationException();
|
||||
}
|
||||
return result;
|
||||
return principal.toString();
|
||||
}
|
||||
|
||||
private SecurityService getSecurityService() {
|
||||
/**
|
||||
* Returns instance of {@link SecurityService} to access the user store.
|
||||
*
|
||||
* @return instance of {@link SecurityService}
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
private SecurityService getSecurityService() throws ServiceNotFoundException {
|
||||
SecurityService securityService = Activator.getSecurityService();
|
||||
if (securityService == null) {
|
||||
setLastErrorCode(ErrorCode.SECURITY_SERIVCE_NOT_FOUND);
|
||||
throw new ServiceNotFoundException("Security service not found!");
|
||||
}
|
||||
return securityService;
|
||||
}
|
||||
|
||||
private boolean addPublicTag(String leaderboardName, String raceColumnName, String fleetName, String tag,
|
||||
String comment, String imageURL, TimePoint raceTimepoint) {
|
||||
boolean successful = true;
|
||||
try {
|
||||
// TODO: As soon as permission-vertical branch got merged into master, apply
|
||||
// new permission system at this permission check (see bug 4104, comment 9)
|
||||
// functionality: Check if user has the permission to add RaceLogEvents to RaceLog.
|
||||
SecurityUtils.getSubject().checkPermission(
|
||||
Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName));
|
||||
RaceLog raceLog = racingService.getRaceLog(leaderboardName, raceColumnName, fleetName);
|
||||
if (raceLog == null) {
|
||||
setLastErrorCode(ErrorCode.RACELOG_NOT_FOUND);
|
||||
successful = false;
|
||||
} else {
|
||||
// check if tag already exists
|
||||
boolean alreadyExists = false;
|
||||
List<TagDTO> publicTags = getPublicTags(leaderboardName, raceColumnName, fleetName);
|
||||
for (TagDTO publicTag : publicTags) {
|
||||
// ignore revoked tags as TagDTO.equals() does ignore revokedAt timepoint
|
||||
if (publicTag.getRevokedAt() == null && publicTag.equals(tag, comment, imageURL,
|
||||
racingService.getServerAuthor().getName(), true, raceTimepoint)) {
|
||||
alreadyExists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (alreadyExists) {
|
||||
setLastErrorCode(ErrorCode.TAG_ALREADY_EXISTS);
|
||||
successful = false;
|
||||
} else {
|
||||
raceLog.add(new RaceLogTagEventImpl(tag, comment, imageURL, raceTimepoint,
|
||||
racingService.getServerAuthor(), raceLog.getCurrentPassId()));
|
||||
}
|
||||
}
|
||||
} catch (AuthorizationException e) {
|
||||
setLastErrorCode(ErrorCode.MISSING_PERMISSIONS);
|
||||
successful = false;
|
||||
}
|
||||
return successful;
|
||||
}
|
||||
|
||||
private boolean addPrivateTag(String leaderboardName, String raceColumnName, String fleetName, String tag,
|
||||
String comment, String imageURL, TimePoint raceTimepoint) {
|
||||
boolean successful = true;
|
||||
SecurityService securityService = Activator.getSecurityService();
|
||||
if (securityService == null) {
|
||||
setLastErrorCode(ErrorCode.SECURITY_SERIVCE_NOT_FOUND);
|
||||
successful = false;
|
||||
} else {
|
||||
Subject subject = SecurityUtils.getSubject();
|
||||
if (subject.getPrincipal() != null) {
|
||||
String username = subject.getPrincipal().toString();
|
||||
TagDTODeSerializer serializer = new TagDTODeSerializer();
|
||||
String key = serializer.generateUniqueKey(leaderboardName, raceColumnName, fleetName);
|
||||
String privateTagsJson = securityService.getPreference(username, key);
|
||||
List<TagDTO> privateTags = serializer.deserializeTags(privateTagsJson);
|
||||
TagDTO tagToAdd = new TagDTO(tag, comment, imageURL, username, false, raceTimepoint,
|
||||
MillisecondsTimePoint.now());
|
||||
if (privateTags.contains(tagToAdd)) {
|
||||
setLastErrorCode(ErrorCode.TAG_ALREADY_EXISTS);
|
||||
successful = false;
|
||||
} else {
|
||||
privateTags.add(tagToAdd);
|
||||
securityService.setPreference(username, key, serializer.serializeTags(privateTags));
|
||||
}
|
||||
} else {
|
||||
setLastErrorCode(ErrorCode.NOT_LOGGED_IN);
|
||||
successful = false;
|
||||
}
|
||||
}
|
||||
return successful;
|
||||
}
|
||||
|
||||
private boolean removePublicTag(String leaderboardName, String raceColumnName, String fleetName, TagDTO tag) {
|
||||
boolean successful = true;
|
||||
private void addPublicTag(String leaderboardName, String raceColumnName, String fleetName, String tag,
|
||||
String comment, String imageURL, TimePoint raceTimepoint)
|
||||
throws RaceLogNotFoundException, TagAlreadyExistsException {
|
||||
// TODO: As soon as permission-vertical branch got merged into master, apply
|
||||
// new permission system at this permission check (see bug 4104, comment 9)
|
||||
// functionality: Check if user has the permission to add RaceLogEvents to RaceLog.
|
||||
SecurityUtils.getSubject()
|
||||
.checkPermission(Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName));
|
||||
RaceLog raceLog = racingService.getRaceLog(leaderboardName, raceColumnName, fleetName);
|
||||
if (raceLog == null) {
|
||||
setLastErrorCode(ErrorCode.RACELOG_NOT_FOUND);
|
||||
successful = false;
|
||||
} else {
|
||||
ReadonlyRaceState raceState = ReadonlyRaceStateImpl.getOrCreate(racingService, raceLog);
|
||||
Iterable<RaceLogTagEvent> foundTagEvents = raceState.getTagEvents();
|
||||
for (RaceLogTagEvent tagEvent : foundTagEvents) {
|
||||
if (tagEvent.getRevokedAt() != null) {
|
||||
continue;
|
||||
} else if (tagEvent.getTag().equals(tag.getTag()) && tagEvent.getComment().equals(tag.getComment())
|
||||
&& tagEvent.getImageURL().equals(tag.getImageURL())
|
||||
&& tagEvent.getUsername().equals(tag.getUsername())
|
||||
&& tagEvent.getLogicalTimePoint().equals(tag.getRaceTimepoint())) {
|
||||
|
||||
try {
|
||||
// TODO: As soon as permission-vertical branch got merged into master, apply
|
||||
// new permission system at this permission check (see bug 4104, comment 9)
|
||||
// functionality: Check if user has the permission to delete tag from RaceLog (same user or
|
||||
// admin).
|
||||
Subject subject = SecurityUtils.getSubject();
|
||||
subject.checkPermission(
|
||||
Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName));
|
||||
if ((subject.getPrincipal() != null && subject.getPrincipal().equals(tag.getUsername()))
|
||||
|| subject.hasRole("admin")) {
|
||||
raceLog.revokeEvent(tagEvent.getAuthor(), tagEvent, "Revoked");
|
||||
} else {
|
||||
setLastErrorCode(ErrorCode.MISSING_PERMISSIONS);
|
||||
successful = false;
|
||||
}
|
||||
} catch (AuthorizationException e) {
|
||||
setLastErrorCode(ErrorCode.MISSING_PERMISSIONS);
|
||||
successful = false;
|
||||
} catch (NotRevokableException e) {
|
||||
setLastErrorCode(ErrorCode.TAG_NOT_REVOKABLE);
|
||||
successful = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
throw new RaceLogNotFoundException();
|
||||
}
|
||||
// check if tag already exists
|
||||
List<TagDTO> publicTags = getPublicTags(leaderboardName, raceColumnName, fleetName);
|
||||
for (TagDTO publicTag : publicTags) {
|
||||
// ignore revoked tags as TagDTO.equals() does ignore revokedAt timepoint
|
||||
if (publicTag.getRevokedAt() == null && publicTag.equals(tag, comment, imageURL, true,
|
||||
racingService.getServerAuthor().getName(), raceTimepoint)) {
|
||||
throw new TagAlreadyExistsException();
|
||||
}
|
||||
}
|
||||
return successful;
|
||||
raceLog.add(new RaceLogTagEventImpl(tag, comment, imageURL, raceTimepoint, racingService.getServerAuthor(),
|
||||
raceLog.getCurrentPassId()));
|
||||
}
|
||||
|
||||
private boolean removePrivateTag(String leaderboardName, String raceColumnName, String fleetName, TagDTO tag) {
|
||||
boolean successful = true;
|
||||
private void addPrivateTag(String leaderboardName, String raceColumnName, String fleetName, String tag,
|
||||
String comment, String imageURL, TimePoint raceTimepoint)
|
||||
throws AuthorizationException, ServiceNotFoundException, TagAlreadyExistsException {
|
||||
SecurityService securityService = Activator.getSecurityService();
|
||||
if (securityService == null) {
|
||||
throw new ServiceNotFoundException("Security service not found!");
|
||||
}
|
||||
Subject subject = SecurityUtils.getSubject();
|
||||
if (subject.getPrincipal() == null) {
|
||||
throw new AuthorizationException();
|
||||
}
|
||||
String username = subject.getPrincipal().toString();
|
||||
TagDTODeSerializer serializer = new TagDTODeSerializer();
|
||||
String key = serializer.generateUniqueKey(leaderboardName, raceColumnName, fleetName);
|
||||
String privateTagsJson = securityService.getPreference(username, key);
|
||||
List<TagDTO> privateTags = serializer.deserializeTags(privateTagsJson);
|
||||
TagDTO tagToAdd = new TagDTO(tag, comment, imageURL, false, username, raceTimepoint,
|
||||
MillisecondsTimePoint.now());
|
||||
if (privateTags.contains(tagToAdd)) {
|
||||
throw new TagAlreadyExistsException();
|
||||
}
|
||||
privateTags.add(tagToAdd);
|
||||
securityService.setPreference(username, key, serializer.serializeTags(privateTags));
|
||||
}
|
||||
|
||||
private void removePublicTag(String leaderboardName, String raceColumnName, String fleetName, TagDTO tag)
|
||||
throws AuthorizationException, NotRevokableException, RaceLogNotFoundException {
|
||||
RaceLog raceLog = racingService.getRaceLog(leaderboardName, raceColumnName, fleetName);
|
||||
if (raceLog == null) {
|
||||
throw new RaceLogNotFoundException();
|
||||
}
|
||||
ReadonlyRaceState raceState = ReadonlyRaceStateImpl.getOrCreate(racingService, raceLog);
|
||||
Iterable<RaceLogTagEvent> foundTagEvents = raceState.getTagEvents();
|
||||
for (RaceLogTagEvent tagEvent : foundTagEvents) {
|
||||
if (tagEvent.getRevokedAt() != null) {
|
||||
continue;
|
||||
} else if (tagEvent.getTag().equals(tag.getTag()) && tagEvent.getComment().equals(tag.getComment())
|
||||
&& tagEvent.getImageURL().equals(tag.getImageURL())
|
||||
&& tagEvent.getUsername().equals(tag.getUsername())
|
||||
&& tagEvent.getLogicalTimePoint().equals(tag.getRaceTimepoint())) {
|
||||
|
||||
// TODO: As soon as permission-vertical branch got merged into master, apply
|
||||
// new permission system at this permission check (see bug 4104, comment 9)
|
||||
// functionality: Check if user has the permission to delete tag from RaceLog (same user or
|
||||
// admin).
|
||||
Subject subject = SecurityUtils.getSubject();
|
||||
subject.checkPermission(
|
||||
Permission.LEADERBOARD.getStringPermissionForObjects(Mode.UPDATE, leaderboardName));
|
||||
if (!(subject.getPrincipal() != null && subject.getPrincipal().equals(tag.getUsername()))
|
||||
|| subject.hasRole("admin")) {
|
||||
throw new AuthorizationException();
|
||||
}
|
||||
raceLog.revokeEvent(tagEvent.getAuthor(), tagEvent, "Revoked");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void removePrivateTag(String leaderboardName, String raceColumnName, String fleetName, TagDTO tag)
|
||||
throws AuthorizationException, ServiceNotFoundException {
|
||||
String username = getCurrentUsername();
|
||||
if (username == null) {
|
||||
setLastErrorCode(ErrorCode.NOT_LOGGED_IN);
|
||||
successful = false;
|
||||
} else {
|
||||
List<TagDTO> privateTags = getPrivateTags(leaderboardName, raceColumnName, fleetName);
|
||||
privateTags.remove(tag);
|
||||
SecurityService securityService = getSecurityService();
|
||||
String key = serializer.generateUniqueKey(leaderboardName, raceColumnName, fleetName);
|
||||
// error code will be set during collection of required data
|
||||
if (username != null && securityService != null && key != null) {
|
||||
List<TagDTO> privateTags = getPrivateTags(leaderboardName, raceColumnName, fleetName);
|
||||
privateTags.remove(tag);
|
||||
SecurityService securityService = getSecurityService();
|
||||
String key = serializer.generateUniqueKey(leaderboardName, raceColumnName, fleetName);
|
||||
// error code will be set during collection of required data
|
||||
if (username != null && securityService != null && key != null) {
|
||||
if (privateTags.isEmpty()) {
|
||||
securityService.unsetPreference(username, key);
|
||||
} else {
|
||||
securityService.setPreference(username, key, serializer.serializeTags(privateTags));
|
||||
}
|
||||
}
|
||||
return successful;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addTag(String leaderboardName, String raceColumnName, String fleetName, String tag, String comment,
|
||||
String imageURL, boolean visibleForPublic, TimePoint raceTimepoint) {
|
||||
boolean successful;
|
||||
public void addTag(String leaderboardName, String raceColumnName, String fleetName, String tag, String comment,
|
||||
String imageURL, boolean visibleForPublic, TimePoint raceTimepoint) throws AuthorizationException,
|
||||
IllegalArgumentException, RaceLogNotFoundException, ServiceNotFoundException, TagAlreadyExistsException {
|
||||
// prefill optional parameters
|
||||
comment = comment == null ? "" : comment;
|
||||
imageURL = imageURL == null ? "" : imageURL;
|
||||
|
||||
// check all parameters for validity
|
||||
if (tag == null || tag.isEmpty()) {
|
||||
setLastErrorCode(ErrorCode.TAG_NOT_EMPTY);
|
||||
successful = false;
|
||||
} else if (tag.length() > TagDTO.MAX_TAG_LENGTH) {
|
||||
setLastErrorCode(ErrorCode.TAG_TOO_LONG);
|
||||
successful = false;
|
||||
} else if (comment.length() > TagDTO.MAX_COMMENT_LENGTH) {
|
||||
setLastErrorCode(ErrorCode.COMMENT_TOO_LONG);
|
||||
successful = false;
|
||||
} else if (raceTimepoint == null || raceTimepoint.asMillis() == 0) {
|
||||
throw new IllegalArgumentException("Tag may not be empty!");
|
||||
}
|
||||
if (raceTimepoint == null || raceTimepoint.asMillis() == 0) {
|
||||
// TODO: Check if timepoint is near start/end of race (+/- x%)
|
||||
setLastErrorCode(ErrorCode.TIMEPOINT_NOT_EMPTY);
|
||||
successful = false;
|
||||
throw new IllegalArgumentException("Timepoint may not be empty!");
|
||||
}
|
||||
if (visibleForPublic) {
|
||||
addPublicTag(leaderboardName, raceColumnName, fleetName, tag, comment, imageURL, raceTimepoint);
|
||||
} else {
|
||||
// all parameters are valid => save tag
|
||||
if (visibleForPublic) {
|
||||
successful = addPublicTag(leaderboardName, raceColumnName, fleetName, tag, comment, imageURL,
|
||||
raceTimepoint);
|
||||
} else {
|
||||
successful = addPrivateTag(leaderboardName, raceColumnName, fleetName, tag, comment, imageURL,
|
||||
raceTimepoint);
|
||||
}
|
||||
addPrivateTag(leaderboardName, raceColumnName, fleetName, tag, comment, imageURL, raceTimepoint);
|
||||
}
|
||||
return successful;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeTag(String leaderboardName, String raceColumnName, String fleetName, TagDTO tag) {
|
||||
boolean successful = true;
|
||||
// check all parameters for validity
|
||||
public void removeTag(String leaderboardName, String raceColumnName, String fleetName, TagDTO tag)
|
||||
throws AuthorizationException, IllegalArgumentException, NotRevokableException, RaceLogNotFoundException,
|
||||
ServiceNotFoundException {
|
||||
if (tag == null) {
|
||||
setLastErrorCode(ErrorCode.TAG_NOT_EMPTY);
|
||||
successful = false;
|
||||
throw new IllegalArgumentException("Tag may not be empty!");
|
||||
}
|
||||
if (tag.isVisibleForPublic()) {
|
||||
removePublicTag(leaderboardName, raceColumnName, fleetName, tag);
|
||||
} else {
|
||||
// all parameters are valid => remove tag
|
||||
if (tag.isVisibleForPublic()) {
|
||||
successful = removePublicTag(leaderboardName, raceColumnName, fleetName, tag);
|
||||
} else {
|
||||
successful = removePrivateTag(leaderboardName, raceColumnName, fleetName, tag);
|
||||
}
|
||||
removePrivateTag(leaderboardName, raceColumnName, fleetName, tag);
|
||||
}
|
||||
return successful;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateTag(String leaderboardName, String raceColumnName, String fleetName, TagDTO tagToUpdate,
|
||||
String tag, String comment, String imageURL, boolean visibleForPublic) {
|
||||
boolean successful = true;
|
||||
public void updateTag(String leaderboardName, String raceColumnName, String fleetName, TagDTO tagToUpdate,
|
||||
String tag, String comment, String imageURL, boolean visibleForPublic)
|
||||
throws AuthorizationException, IllegalArgumentException, NotRevokableException, RaceLogNotFoundException,
|
||||
ServiceNotFoundException, TagAlreadyExistsException {
|
||||
String username = getCurrentUsername();
|
||||
if (username != null && tagToUpdate.getUsername().equals(username)) {
|
||||
if (removeTag(leaderboardName, raceColumnName, fleetName, tagToUpdate)) {
|
||||
successful = addTag(leaderboardName, raceColumnName, fleetName, tag, comment, imageURL,
|
||||
visibleForPublic, tagToUpdate.getRaceTimepoint());
|
||||
} else {
|
||||
successful = false;
|
||||
}
|
||||
removeTag(leaderboardName, raceColumnName, fleetName, tagToUpdate);
|
||||
addTag(leaderboardName, raceColumnName, fleetName, tag, comment, imageURL, visibleForPublic,
|
||||
tagToUpdate.getRaceTimepoint());
|
||||
|
||||
}
|
||||
return successful;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TagDTO> getPublicTags(String leaderboardName, String raceColumnName, String fleetName) {
|
||||
public List<TagDTO> getPublicTags(String leaderboardName, String raceColumnName, String fleetName)
|
||||
throws RaceLogNotFoundException {
|
||||
final List<TagDTO> result = new ArrayList<TagDTO>();
|
||||
RaceLog raceLog = racingService.getRaceLog(leaderboardName, raceColumnName, fleetName);
|
||||
if (raceLog == null) {
|
||||
setLastErrorCode(ErrorCode.RACELOG_NOT_FOUND);
|
||||
} else {
|
||||
ReadonlyRaceState raceState = ReadonlyRaceStateImpl.getOrCreate(racingService, raceLog);
|
||||
Iterable<RaceLogTagEvent> foundTagEvents = raceState.getTagEvents();
|
||||
for (RaceLogTagEvent tagEvent : foundTagEvents) {
|
||||
result.add(new TagDTO(tagEvent.getTag(), tagEvent.getComment(), tagEvent.getImageURL(),
|
||||
tagEvent.getUsername(), true, tagEvent.getLogicalTimePoint(), tagEvent.getCreatedAt(),
|
||||
tagEvent.getRevokedAt()));
|
||||
}
|
||||
throw new RaceLogNotFoundException();
|
||||
}
|
||||
ReadonlyRaceState raceState = ReadonlyRaceStateImpl.getOrCreate(racingService, raceLog);
|
||||
Iterable<RaceLogTagEvent> foundTagEvents = raceState.getTagEvents();
|
||||
for (RaceLogTagEvent tagEvent : foundTagEvents) {
|
||||
result.add(new TagDTO(tagEvent.getTag(), tagEvent.getComment(), tagEvent.getImageURL(), true,
|
||||
tagEvent.getUsername(), tagEvent.getLogicalTimePoint(), tagEvent.getCreatedAt(),
|
||||
tagEvent.getRevokedAt()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TagDTO> getPublicTags(RegattaAndRaceIdentifier raceIdentifier, TimePoint latestReceivedTagTime) {
|
||||
public List<TagDTO> getPublicTags(RegattaAndRaceIdentifier raceIdentifier, TimePoint searchSince) {
|
||||
final List<TagDTO> result = new ArrayList<TagDTO>();
|
||||
TrackedRace trackedRace = racingService.getExistingTrackedRace(raceIdentifier);
|
||||
Iterable<RaceLog> raceLogs = trackedRace.getAttachedRaceLogs();
|
||||
@@ -294,13 +241,13 @@ public class TaggingServiceImpl implements TaggingService {
|
||||
ReadonlyRaceState raceState = ReadonlyRaceStateImpl.getOrCreate(racingService, raceLog);
|
||||
Iterable<RaceLogTagEvent> foundTagEvents = raceState.getTagEvents();
|
||||
for (RaceLogTagEvent tagEvent : foundTagEvents) {
|
||||
if ((latestReceivedTagTime == null && tagEvent.getRevokedAt() == null)
|
||||
|| (latestReceivedTagTime != null && tagEvent.getRevokedAt() == null
|
||||
&& tagEvent.getCreatedAt().after(latestReceivedTagTime))
|
||||
|| (latestReceivedTagTime != null && tagEvent.getRevokedAt() != null
|
||||
&& tagEvent.getRevokedAt().after(latestReceivedTagTime))) {
|
||||
result.add(new TagDTO(tagEvent.getTag(), tagEvent.getComment(), tagEvent.getImageURL(),
|
||||
tagEvent.getUsername(), true, tagEvent.getLogicalTimePoint(), tagEvent.getCreatedAt(),
|
||||
if ((searchSince == null && tagEvent.getRevokedAt() == null)
|
||||
|| (searchSince != null && tagEvent.getRevokedAt() == null
|
||||
&& tagEvent.getCreatedAt().after(searchSince))
|
||||
|| (searchSince != null && tagEvent.getRevokedAt() != null
|
||||
&& tagEvent.getRevokedAt().after(searchSince))) {
|
||||
result.add(new TagDTO(tagEvent.getTag(), tagEvent.getComment(), tagEvent.getImageURL(), true,
|
||||
tagEvent.getUsername(), tagEvent.getLogicalTimePoint(), tagEvent.getCreatedAt(),
|
||||
tagEvent.getRevokedAt()));
|
||||
}
|
||||
}
|
||||
@@ -309,27 +256,13 @@ public class TaggingServiceImpl implements TaggingService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TagDTO> getPrivateTags(String leaderboardName, String raceColumnName, String fleetName) {
|
||||
public List<TagDTO> getPrivateTags(String leaderboardName, String raceColumnName, String fleetName)
|
||||
throws AuthorizationException, ServiceNotFoundException {
|
||||
final List<TagDTO> result = new ArrayList<TagDTO>();
|
||||
SecurityService securityService = getSecurityService();
|
||||
if (securityService != null) {
|
||||
String username = getCurrentUsername();
|
||||
if (username != null) {
|
||||
String key = serializer.generateUniqueKey(leaderboardName, raceColumnName, fleetName);
|
||||
String privateTagsJson = securityService.getPreference(username, key);
|
||||
List<TagDTO> privateTags = serializer.deserializeTags(privateTagsJson);
|
||||
result.addAll(privateTags);
|
||||
}
|
||||
}
|
||||
String key = serializer.generateUniqueKey(leaderboardName, raceColumnName, fleetName);
|
||||
String privateTagsJson = getSecurityService().getPreference(getCurrentUsername(), key);
|
||||
List<TagDTO> privateTags = serializer.deserializeTags(privateTagsJson);
|
||||
result.addAll(privateTags);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ErrorCode getLastErrorCode() {
|
||||
ErrorCode lastErrorCode = lastErrorCodes.get(SecurityUtils.getSubject());
|
||||
if (lastErrorCode == null) {
|
||||
lastErrorCode = ErrorCode.UNKNOWN_ERROR;
|
||||
}
|
||||
return lastErrorCode;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user