mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-23 14:08:40 +00:00
Bug 4104: Added first draft of REST API for tags. Allows to receive all public tags in general and appends them by private tags in case user is logged in.
This commit is contained in:
@@ -29,5 +29,6 @@ Export-Package: com.sap.sailing.domain.common,
|
||||
com.sap.sailing.domain.common.windfinder
|
||||
Require-Bundle: com.sap.sse.common,
|
||||
com.sap.sse.security.common,
|
||||
com.sap.sse.datamining.annotations;bundle-version="1.0.0"
|
||||
com.sap.sse.datamining.annotations;bundle-version="1.0.0",
|
||||
org.json.simple;bundle-version="1.1.0"
|
||||
Automatic-Module-Name: com.sap.sailing.domain.common
|
||||
|
||||
+19
-2
@@ -15,16 +15,33 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogTagEvent;
|
||||
public class TagFinder extends RaceLogAnalyzer<List<RaceLogTagEvent>> {
|
||||
|
||||
private final RaceLog raceLog;
|
||||
private final boolean onlyUnrevokedEvents;
|
||||
|
||||
/**
|
||||
* Creates instance of {@link TagFinder}.
|
||||
* Creates instance of {@link TagFinder} which searches the given <code>raceLog</code> for {@link RaceLogTagEvent
|
||||
* RaceLogTagEvents} and their {@link RaceLogRevokeEvent revocations}.
|
||||
*
|
||||
* @param raceLog
|
||||
* racelog to scan for {@link RaceLogTagEvent RaceLogTagEvents}
|
||||
*/
|
||||
public TagFinder(RaceLog raceLog) {
|
||||
this(raceLog, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates instance of {@link TagFinder} which searches the given <code>raceLog</code> for {@link RaceLogTagEvent
|
||||
* RaceLogTagEvents} and for their {@link RaceLogRevokeEvent revocations} if <code>onlyUnrevokedEvents</code> is set
|
||||
* to <code>false</code>.
|
||||
*
|
||||
* @param raceLog
|
||||
* racelog to scan for {@link RaceLogTagEvent RaceLogTagEvents}
|
||||
* @param onlyUnrevokedEvents
|
||||
* <code>true</code> to search only for unrevoked event, otherwise <code>false</code>
|
||||
*/
|
||||
public TagFinder(RaceLog raceLog, boolean onlyUnrevokedEvents) {
|
||||
super(raceLog);
|
||||
this.raceLog = raceLog;
|
||||
this.onlyUnrevokedEvents = onlyUnrevokedEvents;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -34,7 +51,7 @@ public class TagFinder extends RaceLogAnalyzer<List<RaceLogTagEvent>> {
|
||||
*/
|
||||
@Override
|
||||
protected List<RaceLogTagEvent> performAnalysis() {
|
||||
Iterable<RaceLogEvent> raceLogEvents = getAllEvents();
|
||||
Iterable<RaceLogEvent> raceLogEvents = onlyUnrevokedEvents ? raceLog.getUnrevokedEvents() : getAllEvents();
|
||||
List<RaceLogTagEvent> result = new ArrayList<>();
|
||||
for (RaceLogEvent raceLogEvent : raceLogEvents) {
|
||||
if (raceLogEvent instanceof RaceLogTagEvent) {
|
||||
|
||||
+1
@@ -30,6 +30,7 @@ public class RestApiApplication extends Application {
|
||||
classes.add(StatisticsResource.class);
|
||||
classes.add(WindResource.class);
|
||||
classes.add(MarkRessource.class);
|
||||
classes.add(TagsResource.class);
|
||||
|
||||
// Exception Mappers
|
||||
classes.add(ShiroAuthorizationExceptionTo401ResponseMapper.class);
|
||||
|
||||
+218
@@ -0,0 +1,218 @@
|
||||
package com.sap.sailing.server.gateway.jaxrs.api;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogTagEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.TagFinder;
|
||||
import com.sap.sailing.domain.common.dto.TagDTO;
|
||||
import com.sap.sailing.server.gateway.jaxrs.AbstractSailingServerResource;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.security.SecurityService;
|
||||
import com.sap.sse.security.UserStore;
|
||||
|
||||
@Path("/v1/tags")
|
||||
public class TagsResource extends AbstractSailingServerResource {
|
||||
|
||||
/**
|
||||
* Serializes and deserializes {@link TagDTO tags}. <b>Before changing this class, have a look at
|
||||
* {@link TagDTO.TagDeSerializer}.</b>
|
||||
*
|
||||
* @see TagDTO.TagDeSerializer
|
||||
*/
|
||||
private class TagDTODeSerializer extends TagDTO.TagDeSerializer {
|
||||
|
||||
private final JSONParser parser = new JSONParser();
|
||||
|
||||
/**
|
||||
* Serializes {@link TagDTO tag} as {@link JSONObject}.
|
||||
*
|
||||
* @param tag
|
||||
* {@link TagDTO tag} to be serialized
|
||||
* @return {@link JSONObject json object}
|
||||
*/
|
||||
private JSONObject serialize(TagDTO tag) {
|
||||
JSONObject result = new JSONObject();
|
||||
result.put(FIELD_TAG, tag.getTag());
|
||||
result.put(FIELD_COMMENT, tag.getComment());
|
||||
result.put(FIELD_IMAGE_URL, tag.getImageURL());
|
||||
result.put(FIELD_USERNAME, tag.getUsername());
|
||||
result.put(FIELD_VISIBLE_FOR_PUBLIC, tag.isVisibleForPublic());
|
||||
result.put(FIELD_RACE_TIMEPOINT, serializeTimePoint(tag.getRaceTimepoint()));
|
||||
result.put(FIELD_CREATED_AT, serializeTimePoint(tag.getCreatedAt()));
|
||||
result.put(FIELD_REVOKED_AT, serializeTimePoint(tag.getRevokedAt()));
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes list of {@link TagDTO tags} as {@link JSONArray}.
|
||||
*
|
||||
* @param tags
|
||||
* list of {@link TagDTO tags} to be serialized
|
||||
* @return {@link JSONArray json array}
|
||||
*/
|
||||
private JSONArray serialize(List<TagDTO> tags) {
|
||||
JSONArray result = new JSONArray();
|
||||
for (TagDTO tag : tags) {
|
||||
result.add(serialize(tag));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes {@link JSONObject jsonObject} to {@link TagDTO}.
|
||||
*
|
||||
* @param jsonObject
|
||||
* {@link JSONObject jsonObject} to be deserialized
|
||||
* @return {@link TagDTO tag}
|
||||
*/
|
||||
private TagDTO deserialize(JSONObject jsonObject) {
|
||||
String tag = (String) jsonObject.get(FIELD_TAG);
|
||||
String comment = (String) jsonObject.get(FIELD_COMMENT);
|
||||
String imageURL = (String) jsonObject.get(FIELD_IMAGE_URL);
|
||||
String username = (String) jsonObject.get(FIELD_USERNAME);
|
||||
boolean visibleForPublic = (Boolean) jsonObject.get(FIELD_VISIBLE_FOR_PUBLIC);
|
||||
TimePoint raceTimePoint = deserilizeTimePoint((String) (jsonObject.get(FIELD_RACE_TIMEPOINT)));
|
||||
TimePoint createdAt = deserilizeTimePoint((String) (jsonObject.get(FIELD_CREATED_AT)));
|
||||
TimePoint revokedAt = deserilizeTimePoint((String) (jsonObject.get(FIELD_REVOKED_AT)));
|
||||
return new TagDTO(tag, comment, imageURL, username, visibleForPublic, raceTimePoint, createdAt, revokedAt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes {@link JSONArray jsonArray} to list of {@link TagDTO tags}.
|
||||
*
|
||||
* @param jsonArray
|
||||
* {@link JSONArray jsonArray} to be deserialized
|
||||
* @return list of {@link TagDTO tags}
|
||||
*/
|
||||
private List<TagDTO> deserialize(JSONArray jsonArray) {
|
||||
return deserializeTags(jsonArray.toJSONString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String serializeTag(TagDTO tag) {
|
||||
return serialize(tag).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String serializeTags(List<TagDTO> tags) {
|
||||
JSONArray jsonTags = new JSONArray();
|
||||
for (int i = 0; i < tags.size(); i++) {
|
||||
jsonTags.set(i, serialize(tags.get(i)));
|
||||
}
|
||||
return jsonTags.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TagDTO deserializeTag(String jsonObject) {
|
||||
JSONObject jsonTag;
|
||||
try {
|
||||
jsonTag = (JSONObject) parser.parse(jsonObject);
|
||||
return deserialize(jsonTag);
|
||||
} catch (ParseException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TagDTO> deserializeTags(String jsonArray) {
|
||||
JSONArray jsonTags;
|
||||
List<TagDTO> result = new ArrayList<TagDTO>();
|
||||
try {
|
||||
jsonTags = (JSONArray) parser.parse(jsonArray);
|
||||
for (int i = 0; i < jsonTags.size(); i++) {
|
||||
result.add(deserialize((JSONObject) jsonTags.get(i)));
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private final TagDTODeSerializer serializer;
|
||||
// private final boolean enforceSecurityChecks;
|
||||
|
||||
public TagsResource() {
|
||||
this(true);
|
||||
}
|
||||
|
||||
public TagsResource(boolean enforceSecurityChecks) {
|
||||
// this.enforceSecurityChecks = enforceSecurityChecks;
|
||||
serializer = new TagDTODeSerializer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads public tags from {@link RaceLog} and private tags from {@link UserStore} in case current user is logged in.
|
||||
* Only loads private tags when parameters <code>leaderboardName</code>, <code>raceColumnName</code> and
|
||||
* <code>fleetName</code> can identify {@link RaceLog}.
|
||||
*/
|
||||
@GET
|
||||
@Produces("application/json;charset=UTF-8")
|
||||
@Path("/{leaderboardName}/{raceColumnName}/{fleetName}")
|
||||
public Response getTags(@PathParam("leaderboardName") String leaderboardName,
|
||||
@PathParam("raceColumnName") String raceColumnName, @PathParam("fleetName") String fleetName) {
|
||||
// default response
|
||||
Response response = Response.noContent().build();
|
||||
List<TagDTO> tags = new ArrayList<TagDTO>();
|
||||
|
||||
// check if RaceLog is available and all parameters are set
|
||||
RaceLog raceLog = getService().getRaceLog(leaderboardName, raceColumnName, fleetName);
|
||||
if (raceLog == null) {
|
||||
response = Response.status(Status.PRECONDITION_FAILED)
|
||||
.entity("RaceLog not found! Check parameters leaderboardName, raceColumnName and fleetName")
|
||||
.build();
|
||||
} else {
|
||||
// load public tags
|
||||
TagFinder finder = new TagFinder(raceLog, true);
|
||||
List<RaceLogTagEvent> publicTags = finder.analyze();
|
||||
for (RaceLogTagEvent tagEvent : publicTags) {
|
||||
tags.add(new TagDTO(tagEvent.getTag(), tagEvent.getComment(), tagEvent.getImageURL(),
|
||||
tagEvent.getUsername(), true, tagEvent.getLogicalTimePoint(), tagEvent.getCreatedAt()));
|
||||
}
|
||||
|
||||
// load private tags
|
||||
Subject subject = SecurityUtils.getSubject();
|
||||
if (subject.getPrincipal() != null) {
|
||||
String username = subject.getPrincipal().toString();
|
||||
SecurityService securityService = getService(SecurityService.class);
|
||||
|
||||
// TODO: check preferences key in home and set private tag
|
||||
String preference = securityService.getPreference(username,
|
||||
serializer.generateUniqueKey(leaderboardName, raceColumnName, fleetName));
|
||||
if (preference != null) {
|
||||
try {
|
||||
JSONParser jsonParser = new JSONParser();
|
||||
JSONArray jsonArray = (JSONArray) jsonParser.parse(preference);
|
||||
List<TagDTO> privateTags = serializer.deserialize(jsonArray);
|
||||
tags.addAll(privateTags);
|
||||
} catch (ParseException e) {
|
||||
// TODO: add error handling, could not read private tags
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// convert tags to JSON
|
||||
JSONArray jsonTags = serializer.serialize(tags);
|
||||
response = Response.ok(jsonTags.toJSONString()).build();
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user