1 /* 2 * Copyright 2015 Data Archiving and Networked Services (an institute of 3 * Koninklijke Nederlandse Akademie van Wetenschappen), King's College London, 4 * Georg-August-Universitaet Goettingen Stiftung Oeffentlichen Rechts 5 * 6 * Licensed under the EUPL, Version 1.1 or – as soon they will be approved by 7 * the European Commission - subsequent versions of the EUPL (the "Licence"); 8 * You may not use this work except in compliance with the Licence. 9 * You may obtain a copy of the Licence at: 10 * 11 * https://joinup.ec.europa.eu/software/page/eupl 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the Licence is distributed on an "AS IS" basis, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the Licence for the specific language governing 17 * permissions and limitations under the Licence. 18 */ 19 20 package eu.ehri.extension; 21 22 import eu.ehri.extension.base.AbstractAccessibleResource; 23 import eu.ehri.extension.base.AbstractResource; 24 import eu.ehri.extension.base.GetResource; 25 import eu.ehri.project.api.EventsApi; 26 import eu.ehri.project.core.Tx; 27 import eu.ehri.project.definitions.Entities; 28 import eu.ehri.project.exceptions.AccessDenied; 29 import eu.ehri.project.exceptions.ItemNotFound; 30 import eu.ehri.project.models.base.Accessible; 31 import eu.ehri.project.models.events.SystemEvent; 32 import org.neo4j.graphdb.GraphDatabaseService; 33 34 import javax.ws.rs.DefaultValue; 35 import javax.ws.rs.GET; 36 import javax.ws.rs.Path; 37 import javax.ws.rs.PathParam; 38 import javax.ws.rs.Produces; 39 import javax.ws.rs.QueryParam; 40 import javax.ws.rs.core.Context; 41 import javax.ws.rs.core.MediaType; 42 import javax.ws.rs.core.Response; 43 44 /** 45 * Provides a web service interface for the Event model. Note: Event instances 46 * are created by the system, so we do not have create/update/delete methods 47 * here. 48 * <p> 49 * The following query parameters apply to all actions in this 50 * resource to apply filtering to the event streams. 51 * <p> 52 * <dl> 53 * <dt>eventTypes</dt><dd>Filter events by type</dd> 54 * <dt>itemTypes</dt><dd>Filter events based on the item type of their subjects</dd> 55 * <dt>itemIds</dt><dd>Filter events pertaining to specific item IDs</dd> 56 * <dt>users</dt><dd>Filter events based on the user IDs they involve</dd> 57 * <dt>from</dt><dd>Exclude events prior to this date (ISO 8601 format)</dd> 58 * <dt>to</dt><dd>Exclude events after this date (ISO 8601 format)</dd> 59 * </dl> 60 * <p> 61 * Additionally the aggregate* end-points accept an <code>aggregation</code> 62 * parameter that groups sequential events according to one of two different 63 * strategies: 64 * <dl> 65 * <dt>user</dt> 66 * <dd>Groups sequential events of all types that are initiated by the same actioner</dd> 67 * <dt>strict</dt> 68 * <dd> 69 * Groups sequential events that: 70 * <ul> 71 * <li>have the same type</li> 72 * <li>have the same actioner</li> 73 * <li>have the same subjects</li> 74 * <li>have the same scope</li> 75 * <li>have the same log message</li> 76 * </ul> 77 * </dd> 78 * </dl> 79 * <p> 80 * Additionally, aggregation can be disabled by using <code>aggregation=off</code>. 81 * <p> 82 * Standard paging parameters apply to all end-points. 83 */ 84 @Path(AbstractResource.RESOURCE_ENDPOINT_PREFIX + "/" + Entities.SYSTEM_EVENT) 85 public class SystemEventResource extends AbstractAccessibleResource<SystemEvent> 86 implements GetResource { 87 88 89 public SystemEventResource(@Context GraphDatabaseService database) { 90 super(database, SystemEvent.class); 91 } 92 93 @GET 94 @Produces(MediaType.APPLICATION_JSON) 95 @Path("{id:[^/]+}") 96 @Override 97 public Response get(@PathParam("id") String id) throws ItemNotFound { 98 return getItem(id); 99 } 100 101 /** 102 * List aggregated global events. Standard list parameters for paging apply. 103 * 104 * @param aggregation The manner in which to aggregate the results, accepting 105 * "user", "strict" or "off" (no aggregation). Default is 106 * "user". 107 */ 108 @GET 109 @Produces(MediaType.APPLICATION_JSON) 110 public Response list( 111 @QueryParam(AGGREGATION_PARAM) @DefaultValue("user") EventsApi.Aggregation aggregation) { 112 try (final Tx tx = beginTx()) { 113 EventsApi eventsApi = getEventsApi() 114 .withAggregation(aggregation); 115 Response response = streamingListOfLists(eventsApi::aggregate); 116 tx.success(); 117 return response; 118 } 119 } 120 121 /** 122 * Fetch a page of subjects for a given event. 123 * 124 * @param id the event id 125 * @return a list of subject items 126 */ 127 @GET 128 @Produces(MediaType.APPLICATION_JSON) 129 @Path("{id:[^/]+}/subjects") 130 public Response pageSubjectsForEvent(@PathParam("id") String id) 131 throws ItemNotFound, AccessDenied { 132 try (final Tx tx = beginTx()) { 133 SystemEvent event = api().detail(id, cls); 134 // Subjects are only serialized to depth 1 for efficiency... 135 Response response = streamingPage(() -> getQuery() 136 .page(event.getSubjects(), Accessible.class), 137 getSerializer().withDepth(1).withCache()); 138 tx.success(); 139 return response; 140 } 141 } 142 }