View Javadoc

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 com.google.common.base.Charsets;
23  import eu.ehri.extension.base.AbstractResource;
24  import eu.ehri.project.core.Tx;
25  import eu.ehri.project.exceptions.DeserializationError;
26  import eu.ehri.project.exceptions.ItemNotFound;
27  import eu.ehri.project.exceptions.ValidationError;
28  import eu.ehri.project.importers.ImportLog;
29  import eu.ehri.project.importers.json.BatchOperations;
30  import eu.ehri.project.models.base.Actioner;
31  import eu.ehri.project.models.base.PermissionScope;
32  import eu.ehri.project.utils.Table;
33  import org.neo4j.graphdb.GraphDatabaseService;
34  import org.slf4j.Logger;
35  import org.slf4j.LoggerFactory;
36  
37  import javax.ws.rs.Consumes;
38  import javax.ws.rs.DefaultValue;
39  import javax.ws.rs.POST;
40  import javax.ws.rs.PUT;
41  import javax.ws.rs.Path;
42  import javax.ws.rs.Produces;
43  import javax.ws.rs.QueryParam;
44  import javax.ws.rs.core.Context;
45  import javax.ws.rs.core.MediaType;
46  import java.io.IOException;
47  import java.io.InputStream;
48  import java.nio.file.Files;
49  import java.nio.file.Paths;
50  import java.util.Collections;
51  import java.util.Optional;
52  
53  /**
54   * Resource class for import endpoints.
55   */
56  @Path(BatchResource.ENDPOINT)
57  public class BatchResource extends AbstractResource {
58  
59      public static final String ENDPOINT = "batch";
60  
61      private static final Logger logger = LoggerFactory.getLogger(BatchResource.class);
62  
63      public BatchResource(@Context GraphDatabaseService database) {
64          super(database);
65      }
66  
67      /**
68       * Update a batch of items via JSON containing (partial)
69       * data bundles.
70       *
71       * @param scope       the ID of there item's permission scope
72       * @param tolerant    whether to allow individual validation failures
73       * @param version     whether to create a version prior to delete
74       * @param log         an optional log message
75       * @param inputStream a JSON document containing partial bundles containing
76       *                    the needed data transformations
77       * @return an import log describing the changes committed
78       */
79      @PUT
80      @Consumes(MediaType.APPLICATION_JSON)
81      @Produces(MediaType.APPLICATION_JSON)
82      @Path("update")
83      public ImportLog batchUpdate(
84              @QueryParam(SCOPE_PARAM) String scope,
85              @DefaultValue("false") @QueryParam(TOLERANT_PARAM) Boolean tolerant,
86              @DefaultValue("true") @QueryParam(VERSION_PARAM) Boolean version,
87              @QueryParam(LOG_PARAM) String log,
88              @QueryParam(COMMIT_PARAM) @DefaultValue("false") boolean commit,
89              InputStream inputStream)
90              throws IOException, ItemNotFound, ValidationError, DeserializationError {
91          try (final Tx tx = beginTx()) {
92              Actioner user = getCurrentActioner();
93              PermissionScope parent = scope != null
94                      ? manager.getEntity(scope, PermissionScope.class)
95                      : null;
96              ImportLog importLog = new BatchOperations(graph, parent, version, tolerant, Collections.emptyList())
97                      .batchUpdate(inputStream, user, getLogMessage(log));
98              if (commit) {
99                  logger.debug("Committing batch update transaction...");
100                 tx.success();
101             }
102             return importLog;
103         }
104     }
105 
106     /**
107      * Delete a batch of objects via JSON containing their IDs.
108      *
109      * @param scope   the ID of there item's permission scope
110      * @param version whether to create a version prior to delete
111      * @param log     an optional log message.
112      * @return the number of items deleted
113      */
114     @POST
115     @Produces({MediaType.APPLICATION_JSON, CSV_MEDIA_TYPE})
116     @Consumes({MediaType.APPLICATION_JSON, CSV_MEDIA_TYPE})
117     @Path("delete")
118     public String batchDelete(
119             @QueryParam(SCOPE_PARAM) String scope,
120             @DefaultValue("true") @QueryParam(VERSION_PARAM) Boolean version,
121             @QueryParam(LOG_PARAM) String log,
122             @QueryParam(COMMIT_PARAM) @DefaultValue("false") boolean commit,
123             Table ids)
124             throws IOException, DeserializationError {
125         try (final Tx tx = beginTx()) {
126             Actioner user = getCurrentActioner();
127             PermissionScope parent = scope != null
128                     ? manager.getEntity(scope, PermissionScope.class)
129                     : null;
130             int done = new BatchOperations(graph, parent, version, false, Collections.emptyList())
131                     .batchDelete(ids.column(0), user, getLogMessage(log));
132             if (commit) {
133                 logger.debug("Committing batch delete transaction...");
134                 tx.success();
135             }
136             return String.valueOf(done);
137         } catch (ItemNotFound e) {
138             throw new DeserializationError("Unable to locate item with ID: " + e.getValue());
139         }
140     }
141 
142 
143     // Helpers
144 
145     private Optional<String> getLogMessage(String logMessagePathOrText) throws IOException {
146         if (logMessagePathOrText == null || logMessagePathOrText.trim().isEmpty()) {
147             return getLogMessage();
148         } else {
149             java.nio.file.Path fileTest = Paths.get(logMessagePathOrText);
150             if (Files.isRegularFile(fileTest)) {
151                 return Optional.of(new String(Files.readAllBytes(fileTest), Charsets.UTF_8));
152             } else {
153                 return Optional.of(logMessagePathOrText);
154             }
155         }
156     }
157 
158 }