Skip to content

Commit

Permalink
Remove unused stuff from the annotations API
Browse files Browse the repository at this point in the history
  • Loading branch information
JulianKniephoff committed Jan 28, 2025
1 parent f1fec68 commit ae07a4e
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 183 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -283,25 +283,11 @@ Annotation createAnnotation(long trackId, double start, Option<Double> duration,
/**
* Get annotations of a track.
*
* @param trackId
* the track id
* @param offset
* pagination offset
* @param limit
* limit the result set to the said amount
* @param since
* limit the result set to annotations modified since the said date
* @param tagsAnd
* the tags logical AND Map
* @param tagsOr
* the tags logical OR Map
* @param trackId the track id
* @return the annotation list or an empty list if no annotation has been found
* @throws ExtendedAnnotationException
* if an error occurs while storing/retrieving from persistence storage
* @throws ExtendedAnnotationException if an error occurs while storing/retrieving from persistence storage
*/
List<Annotation> getAnnotations(long trackId, Option<Double> start, Option<Double> end, Option<Integer> offset,
Option<Integer> limit, Option<Date> since, Option<Map<String, String>> tagsAnd,
Option<Map<String, String>> tagsOr) throws ExtendedAnnotationException;
Stream<Annotation> getAnnotations(long trackId) throws ExtendedAnnotationException;

/**
* Create a scale
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -280,21 +280,15 @@ public Response apply() {
public Response postAnnotation(@PathParam("trackId") final long trackId, @FormParam("start") final Double start,
@FormParam("duration") final Double duration, @FormParam("content") @DefaultValue("[]") final String content,
@FormParam("createdFromQuestionnaire") final long createdFromQuestionnaire,
@FormParam("settings") final String settings, @FormParam("tags") final String tags) {
return run(array(start), new Function0<Response>() {
@FormParam("settings") final String settings) {
return run(array(start), new Function0<>() {
@Override
public Response apply() {
if (videoOpt.isSome() && eas.getTrack(trackId).isSome()) {
final Option<Option<Map<String, String>>> tagsMap = trimToNone(tags).map(parseToJsonMap);
if (tagsMap.isSome() && tagsMap.get().isNone())
return BAD_REQUEST;

Resource resource = eas.createResource(
tagsMap.bind(Functions.identity()));
Resource resource = eas.createResource(none());
final Annotation a = eas.createAnnotation(trackId, start, option(duration), content, createdFromQuestionnaire,
trimToNone(settings), resource);
return Response.created(annotationLocationUri(videoId, a))
.entity(AnnotationDto.toJson.apply(eas, a).toString()).build();
trimToNone(settings), resource);
return Response.created(annotationLocationUri(videoId, a)).entity(AnnotationDto.toJson.apply(eas, a).toString()).build();
} else {
return BAD_REQUEST;
}
Expand All @@ -309,47 +303,37 @@ public Response putAnnotation(@PathParam("trackId") final long trackId, @PathPar
@FormParam("start") final double start, @FormParam("duration") final Double duration,
@FormParam("content") @DefaultValue("[]") final String content,
@FormParam("createdFromQuestionnaire") final long createdFromQuestionnaire,
@FormParam("settings") final String settings,
@FormParam("tags") final String tags) {
return run(array(start), new Function0<Response>() {
@FormParam("settings") final String settings) {
return run(array(start), new Function0<>() {
@Override
public Response apply() {
Option<Option<Map<String, String>>> tagsMap = trimToNone(tags).map(parseToJsonMap);
if (tagsMap.isSome() && tagsMap.get().isNone())
return BAD_REQUEST;

final Option<Map<String, String>> tags = tagsMap.bind(Functions.identity());

// check if video and track exist
if (videoOpt.isSome() && eas.getTrack(trackId).isSome()) {
return eas.getAnnotation(id).fold(new Option.Match<Annotation, Response>() {
return eas.getAnnotation(id).fold(new Option.Match<>() {
// update annotation
@Override
public Response some(Annotation annotation) {
if (!eas.hasResourceAccess(annotation))
if (!eas.hasResourceAccess(annotation)) {
return UNAUTHORIZED;
}

Resource resource = eas.updateResource(annotation, tags);
Resource resource = eas.updateResource(annotation, Option.none());
final Annotation updated = new AnnotationImpl(id, trackId, start, option(duration), content,
createdFromQuestionnaire, trimToNone(settings), resource);
createdFromQuestionnaire, trimToNone(settings), resource);
if (!annotation.equals(updated)) {
eas.updateAnnotation(updated);
annotation = updated;
}
return Response.ok(AnnotationDto.toJson.apply(eas, annotation).toString())
.header(LOCATION, annotationLocationUri(videoId, updated))
.build();
return Response.ok(AnnotationDto.toJson.apply(eas, annotation).toString()).header(LOCATION, annotationLocationUri(videoId, updated)).build();
}

// create a new one
@Override
public Response none() {
Resource resource = eas.createResource(tags);
Resource resource = eas.createResource(Option.none());
final Annotation a = eas.createAnnotation(
new AnnotationImpl(id, trackId, start, option(duration), content, createdFromQuestionnaire,
trimToNone(settings), resource));
return Response.created(annotationLocationUri(videoId, a))
.entity(AnnotationDto.toJson.apply(eas, a).toString()).build();
new AnnotationImpl(id, trackId, start, option(duration), content, createdFromQuestionnaire, trimToNone(settings), resource));
return Response.created(annotationLocationUri(videoId, a)).entity(AnnotationDto.toJson.apply(eas, a).toString()).build();
}
});
} else {
Expand All @@ -364,14 +348,15 @@ public Response none() {
@Path("tracks/{trackId}/annotations/{id}")
public Response deleteAnnotation(@PathParam("trackId") final long trackId, @PathParam("id") final long id) {
if (videoOpt.isSome() && eas.getTrack(trackId).isSome()) {
return run(nil, new Function0<Response>() {
return run(nil, new Function0<>() {
@Override
public Response apply() {
return eas.getAnnotation(id).fold(new Option.Match<Annotation, Response>() {
return eas.getAnnotation(id).fold(new Option.Match<>() {
@Override
public Response some(Annotation a) {
if (!eas.hasResourceAccess(a))
if (!eas.hasResourceAccess(a)) {
return UNAUTHORIZED;
}
return eas.deleteAnnotation(a) ? NO_CONTENT : NOT_FOUND;
}

Expand All @@ -393,14 +378,15 @@ public Response none() {
public Response getAnnotation(@PathParam("trackId") final long trackId, @PathParam("id") final long id) {
// TODO optimize querying for the existence of video and track
if (videoOpt.isSome() && eas.getTrack(trackId).isSome()) {
return run(nil, new Function0<Response>() {
return run(nil, new Function0<>() {
@Override
public Response apply() {
return eas.getAnnotation(id).fold(new Option.Match<Annotation, Response>() {
return eas.getAnnotation(id).fold(new Option.Match<>() {
@Override
public Response some(Annotation a) {
if (!eas.hasResourceAccess(a))
if (!eas.hasResourceAccess(a)) {
return UNAUTHORIZED;
}
return Response.ok(AnnotationDto.toJson.apply(eas, a).toString()).build();
}

Expand All @@ -417,37 +403,17 @@ public Response none() {
}
}

// TODO Is this even used?
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("tracks/{trackId}/annotations")
public Response getAnnotations(@PathParam("trackId") final long trackId, @QueryParam("limit") final int limit,
@QueryParam("offset") final int offset, @QueryParam("start") final double start,
@QueryParam("end") final double end, @QueryParam("since") final String date,
@QueryParam("tags-and") final String tagsAnd, @QueryParam("tags-or") final String tagsOr) {
return run(nil, new Function0<Response>() {
public Response getAnnotations(@PathParam("trackId") final long trackId) {
return run(nil, new Function0<>() {
@Override
public Response apply() {
if (videoOpt.isSome()) {
final Option<Double> startm = start > 0 ? some(start) : none();
final Option<Double> endm = end > 0 ? some(end) : none();
final Option<Integer> offsetm = offset > 0 ? some(offset) : none();
final Option<Integer> limitm = limit > 0 ? some(limit) : none();
final Option<Option<Date>> datem = trimToNone(date).map(parseDate);
final Option<Option<Map<String, String>>> tagsAndArray = trimToNone(tagsAnd).map(parseToJsonMap);
final Option<Option<Map<String, String>>> tagsOrArray = trimToNone(tagsOr).map(parseToJsonMap);

if ((datem.isSome() && datem.get().isNone()) || (tagsAndArray.isSome() && tagsAndArray.get().isNone())
|| (tagsOrArray.isSome() && tagsOrArray.get().isNone())) {
return BAD_REQUEST;
} else {
return Response.ok(AnnotationDto.toJson(
eas,
offset,
eas.getAnnotations(trackId, startm, endm, offsetm, limitm,
datem.bind(Functions.identity()),
tagsAndArray.bind(Functions.identity()),
tagsOrArray.bind(Functions.identity()))).toString()).build();
}
return Response.ok(AnnotationDto.toJson(eas,
eas.getAnnotations(trackId)).toString()).build();
} else {
return NOT_FOUND;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ public class AnnotationImpl extends ResourceImpl implements Annotation {
public AnnotationImpl(long id, long trackId, double start, Option<Double> duration,
String content, long createdFromQuestionnaire, Option<String> settings, Resource resource) {
super(Option.option(resource.getAccess()), resource.getCreatedBy(), resource.getUpdatedBy(), resource
.getDeletedBy(), resource.getCreatedAt(), resource.getUpdatedAt(), resource.getDeletedAt(), resource
.getTags());
.getDeletedBy(), resource.getCreatedAt(), resource.getUpdatedAt(), resource.getDeletedAt(), null);
this.id = id;
this.trackId = trackId;
this.start = start;
Expand All @@ -59,7 +58,7 @@ public long getId() {

@Override
public Option<Long> getVideo(final ExtendedAnnotationService eas) {
return eas.getTrack(trackId).bind(new Function<Track, Option<Long>>() {
return eas.getTrack(trackId).bind(new Function<>() {
@Override
public Option<Long> apply(Track track) {
return track.getVideo(eas);
Expand Down Expand Up @@ -106,11 +105,11 @@ public boolean equals(Object o) {
Annotation annotation = (Annotation) o;
return id == annotation.getId() && trackId == annotation.getTrackId() && duration.equals(annotation.getDuration())
&& start == annotation.getStart() && content.equals(annotation.getContent())
&& settings.equals(annotation.getSettings()) && getTags().equals(annotation.getTags());
&& settings.equals(annotation.getSettings());
}

@Override
public int hashCode() {
return Objects.hash(id, trackId, start, duration, content, settings, getTags());
return Objects.hash(id, trackId, start, duration, content, settings);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import static org.opencast.annotation.impl.Jsons.jA;
import static org.opencast.annotation.impl.Jsons.jO;
import static org.opencast.annotation.impl.Jsons.p;
import static org.opencastproject.util.data.Monadics.mlist;
import static org.opencastproject.util.data.Option.option;

import org.opencast.annotation.api.Annotation;
Expand All @@ -34,20 +33,14 @@

import org.json.simple.JSONObject;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.MapKeyColumn;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
Expand All @@ -58,11 +51,6 @@
@NamedQueries({
@NamedQuery(name = "Annotation.findById", query = "select a from Annotation a where a.id = :id and a.deletedAt IS NULL"),
@NamedQuery(name = "Annotation.findAllOfTrack", query = "select a from Annotation a where a.trackId = :id and a.deletedAt IS NULL"),
@NamedQuery(name = "Annotation.findAllOfTrackStart", query = "select a from Annotation a where a.trackId = :id and a.start >= :start"),
@NamedQuery(name = "Annotation.findAllOfTrackEnd", query = "select a from Annotation a where a.trackId = :id and (a.start + a.duration) <= :end"),
@NamedQuery(name = "Annotation.findAllOfTrackStartEnd", query = "select a from Annotation a where a.trackId = :id and a.start >= :start and (a.start + a.duration) <= :end"),
@NamedQuery(name = "Annotation.findAllOfTrackSince", query = "select a from Annotation a where a.trackId = :id and a.deletedAt IS NULL and ((a.updatedAt IS NOT NULL AND a.updatedAt >= :since) OR (a.updatedAt IS NULL AND a.createdAt >= :since))"),
@NamedQuery(name = "Annotation.deleteById", query = "delete from Annotation a where a.id = :id"),
@NamedQuery(name = "Annotation.clear", query = "delete from Annotation") })
public class AnnotationDto extends AbstractResourceDto {
@Id
Expand Down Expand Up @@ -91,12 +79,6 @@ public class AnnotationDto extends AbstractResourceDto {
@Column(name = "track_id", nullable = false)
private long trackId;

@ElementCollection
@MapKeyColumn(name = "name")
@Column(name = "value")
@CollectionTable(name = "xannotations_annotation_tags", joinColumns = @JoinColumn(name = "annotation_id"))
protected Map<String, String> tags = new HashMap<String, String>();

public static AnnotationDto create(long trackId, double start, Option<Double> duration, String content,
long createdFromQuestionnaire, Option<String> settings, Resource resource) {
final AnnotationDto dto = new AnnotationDto().update(start, duration, content, createdFromQuestionnaire,
Expand All @@ -113,8 +95,6 @@ public AnnotationDto update(double start, Option<Double> duration, String conten
this.duration = duration.getOrElseNull();
this.createdFromQuestionnaire = createdFromQuestionnaire;
this.settings = settings.getOrElseNull();
if (resource.getTags() != null)
this.tags = resource.getTags();
return this;
}

Expand All @@ -128,27 +108,26 @@ public static AnnotationDto fromAnnotation(Annotation a) {
public Annotation toAnnotation() {
return new AnnotationImpl(id, trackId, start, option(duration), content, createdFromQuestionnaire, option(settings),
new ResourceImpl(option(access), option(createdBy), option(updatedBy),
option(deletedBy), option(createdAt), option(updatedAt), option(deletedAt), tags));
option(deletedBy), option(createdAt), option(updatedAt), option(deletedAt), null));
}

public static final Function<AnnotationDto, Annotation> toAnnotation = new Function<AnnotationDto, Annotation>() {
public static final Function<AnnotationDto, Annotation> toAnnotation = new Function<>() {
@Override
public Annotation apply(AnnotationDto dto) {
return dto.toAnnotation();
}
};

public static final Function2<ExtendedAnnotationService, Annotation, JSONObject> toJson = new Function2<ExtendedAnnotationService, Annotation, JSONObject>() {
public static final Function2<ExtendedAnnotationService, Annotation, JSONObject> toJson = new Function2<>() {
@Override
public JSONObject apply(ExtendedAnnotationService s, Annotation a) {
return conc(
AbstractResourceDto.toJson.apply(s, a),
jO(p("id", a.getId()), p("start", a.getStart()), p("duration", a.getDuration()), p("content", a.getContent()),
p("createdFromQuestionnaire", a.getCreatedFromQuestionnaire()), p("settings", a.getSettings())));
return conc(AbstractResourceDto.toJson.apply(s, a),
jO(p("id", a.getId()), p("start", a.getStart()), p("duration", a.getDuration()), p("content", a.getContent()),
p("createdFromQuestionnaire", a.getCreatedFromQuestionnaire()), p("settings", a.getSettings())));
}
};

public static JSONObject toJson(ExtendedAnnotationService s, int offset, List<Annotation> as) {
return jO(p("offset", offset), p("count", as.size()), p("annotations", jA(mlist(as).map(toJson.curry(s)))));
public static JSONObject toJson(ExtendedAnnotationService s, Stream<Annotation> as) {
return jO(p("annotations", jA(as.map(a -> toJson.apply(s, a)).toArray())));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -287,10 +287,7 @@ public boolean deleteTrack(Track t) throws ExtendedAnnotationException {
deleteResource);
updateTrack(updated);

List<Annotation> annotations = getAnnotations(t.getId(), none(), none(), none(), none(), none(), none(), none());
for (Annotation a : annotations) {
deleteAnnotation(a);
}
getAnnotations(t.getId()).forEach(this::deleteAnnotation);
return true;
}

Expand Down Expand Up @@ -388,37 +385,13 @@ public Option<Annotation> getAnnotation(long id) throws ExtendedAnnotationExcept
}

@Override
public List<Annotation> getAnnotations(final long trackId, final Option<Double> start, final Option<Double> end,
final Option<Integer> offset, final Option<Integer> limit, final Option<Date> since,
final Option<Map<String, String>> tagsAnd, final Option<Map<String, String>> tagsOr)
public Stream<Annotation> getAnnotations(final long trackId)
throws ExtendedAnnotationException {

// TODO refactoring with since
List<AnnotationDto> annotationDtos;
if (start.isSome() && end.isSome()) {
annotationDtos = findAllWithOffsetAndLimit(AnnotationDto.class, "Annotation.findAllOfTrackStartEnd", offset, limit, Pair.of("start", start.get()), Pair.of("end", end.get()));
} else if (start.isSome()) {
annotationDtos = findAllWithOffsetAndLimit(AnnotationDto.class, "Annotation.findAllOfTrackStart", offset, limit, Pair.of("start", start.get()));
} else if (end.isSome()) {
annotationDtos = findAllWithOffsetAndLimit(AnnotationDto.class, "Annotation.findAllOfTrackEnd", offset, limit, Pair.of("end", end.get()));
} else {
annotationDtos = findAllWithOffsetAndLimit(AnnotationDto.class, "Annotation.findAllOfTrack", offset, limit, id(trackId));
}

List<Annotation> annotations = annotationDtos.stream()
return findAllWithOffsetAndLimit(AnnotationDto.class, "Annotation.findAllOfTrack", none(), none(), id(trackId))
.stream()
.map(AnnotationDto::toAnnotation)
.collect(Collectors.toList());

if (tagsAnd.isSome())
annotations = filterAndTags(annotations, tagsAnd.get());

if (tagsOr.isSome())
annotations = filterOrTags(annotations, tagsOr.get());

// Filter out structured annotations from categories the current user cannot access
annotations = filterByCategoryAccess(annotations);

return annotations;
.filter(this::hasCategoryAccess);
}

@Override
Expand Down
Loading

0 comments on commit ae07a4e

Please sign in to comment.