33aa04d1da1ffcc4090b870def0520090bfac96b
[policy/gui.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
4  *  Modifications Copyright (C) 2020 Nordix Foundation.
5  * ================================================================================
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * SPDX-License-Identifier: Apache-2.0
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.policy.gui.editors.apex.rest.handling;
23
24 import java.io.IOException;
25 import java.io.InputStream;
26 import javax.ws.rs.Consumes;
27 import javax.ws.rs.DELETE;
28 import javax.ws.rs.GET;
29 import javax.ws.rs.POST;
30 import javax.ws.rs.PUT;
31 import javax.ws.rs.Path;
32 import javax.ws.rs.PathParam;
33 import javax.ws.rs.Produces;
34 import javax.ws.rs.QueryParam;
35 import javax.ws.rs.core.MediaType;
36 import org.glassfish.jersey.media.multipart.FormDataParam;
37 import org.onap.policy.apex.model.modelapi.ApexApiResult;
38 import org.onap.policy.apex.model.modelapi.ApexApiResult.Result;
39 import org.onap.policy.common.parameters.ParameterService;
40 import org.onap.policy.common.utils.coder.StandardCoder;
41 import org.onap.policy.common.utils.coder.YamlJsonTranslator;
42 import org.onap.policy.common.utils.resources.TextFileUtils;
43 import org.onap.policy.gui.editors.apex.rest.UploadPluginConfigParameters;
44 import org.onap.policy.gui.editors.apex.rest.handling.converter.tosca.ApexConfigProcessor;
45 import org.onap.policy.gui.editors.apex.rest.handling.converter.tosca.PolicyToscaConverter;
46 import org.onap.policy.gui.editors.apex.rest.handling.converter.tosca.ToscaTemplateProcessor;
47 import org.onap.policy.gui.editors.apex.rest.handling.plugin.upload.UploadPluginClient;
48 import org.slf4j.ext.XLogger;
49 import org.slf4j.ext.XLoggerFactory;
50
51 /**
52  * The class represents the root resource exposed at the base URL<br> The url to access this resource would be in the
53  * form {@code <baseURL>/rest/<session>/....} <br> For example: a PUT request to the following URL
54  * {@code http://localhost:8080/apex/rest/109/ContextSchema/Update}, with a JSON string payload containing the new
55  * {@code Schema} in the body, can be explained as: <ul> <li>The server or servlet is running at the base URL
56  * {@code http://localhost:8080/apex} <li>This resource {@code ApexRestEditorResource} is used because the path
57  * {@code rest/109} matches the {@code Path} filter specification for this Resource ({@code @Path("rest/{session}")}),
58  * where the {@code int} path parameter {@code session} is assigned the {@code int} value {@code 109} <li>The path
59  * {@code ContextSchema/Update} redirects this call to the method {@link #updateContextSchema(String)}, which should be
60  * a {@link javax.ws.rs.PUT}, with a single String in the body/payload which gets mapped to the single String parameter
61  * for the method. <li>So, in summary, the REST request updates a {@code ContextSchema} as specified in the payload for
62  * {@code session} number {@code 109} </ul>
63  *
64  * <b>Note:</b> An allocated {@code Session} identifier must be included in (almost) all requests. Models for different
65  * {@code Session} identifiers are completely isolated from one another.
66  *
67  * <b>Note:</b> To create a new {@code Session}, and have a new session ID allocated use {@link javax.ws.rs.GET} request
68  * to {@code <baseURL>/rest/-1/Session/Create} (for example: {@code http://localhost:8080/apex/rest/-1/Session/Create} )
69  *
70  */
71 @Path("editor/{session}")
72 @Produces({MediaType.APPLICATION_JSON})
73 @Consumes({MediaType.APPLICATION_JSON})
74 public class ApexEditorRestResource implements RestCommandHandler {
75
76     // Get a reference to the logger
77
78     private static final XLogger LOGGER = XLoggerFactory.getXLogger(ApexEditorRestResource.class);
79     // Location of the periodi event template
80
81     private static final String PERIODIC_EVENT_TEMPLATE = "src/main/resources/templates/PeriodicEventTemplate.json";
82     // Recurring string constants
83
84     private static final String NAME = "name";
85     private static final String VERSION = "version";
86     private static final String REST_COMMAND_NOT_RECOGNISED = "REST command not recognised";
87     private static final String OK = ": OK";
88     private static final String NOT_OK = ": Not OK";
89     private static final String SESSION_CREATE = "Session/Create";
90     private static final String SESSION_CREATE_NOT_OK = "Session/Create: Not OK";
91     // The session handler for sessions on the Apex editor
92
93     private static final RestSessionHandler SESSION_HANDLER = new RestSessionHandler();
94     // Handlers for the various parts of an Apex model
95     //@formatter:off
96
97     private static final ModelHandler         MODEL_HANDLER          = new ModelHandler();
98     private static final KeyInfoHandler       KEY_INFO_HANDLER       = new KeyInfoHandler();
99     private static final ContextSchemaHandler CONTEXT_SCHEMA_HANDLER = new ContextSchemaHandler();
100     private static final ContextAlbumHandler  CONTEXT_ALBUM_HANDLER  = new ContextAlbumHandler();
101     private static final EventHandler         EVENT_HANDLER          = new EventHandler();
102     private static final TaskHandler          TASK_HANDLER           = new TaskHandler();
103     private static final PolicyHandler        POLICY_HANDLER         = new PolicyHandler();
104
105     private final PolicyUploadHandler policyUploadHandler;
106     //@formatter:on
107     // The ID of this session. This gets injected from the URL.
108
109     @PathParam("session")
110     private int sessionId = -1;
111
112     /**
113      * Creates the ApexEditorRestResource instance.
114      */
115     public ApexEditorRestResource() {
116         final StandardCoder standardCoder = new StandardCoder();
117         policyUploadHandler = new PolicyUploadHandler(
118             new UploadPluginClient(), new PolicyToscaConverter(standardCoder, new YamlJsonTranslator()),
119             new ToscaTemplateProcessor(standardCoder), new ApexConfigProcessor(standardCoder),
120             ParameterService.get(UploadPluginConfigParameters.GROUP_NAME)
121         );
122     }
123
124     /**
125      * Creates a new session. Always call this method with sessionID -1, whereby a new sessionID will be allocated. If
126      * successful the new sessionID will be available in the first message in the result.
127      *
128      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
129      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}. This includes the session id
130      *         for this session.
131      */
132     @GET
133     @Path("Session/Create")
134     public ApexApiResult createSession() {
135         if (sessionId != -1) {
136             return new ApexApiResult(Result.FAILED, "Session ID must be set to -1 to create sessions: " + sessionId);
137         }
138
139         ApexApiResult result = new ApexApiResult();
140         SESSION_HANDLER.createSession(result);
141         return result;
142     }
143
144     /**
145      * Load the model from a JSON string for this session.
146      *
147      * @param jsonString the JSON string to be parsed. The returned value(s) will be similar to {@code AxPolicyModel},
148      *        with merged {@code AxKeyInfo} for the root object.
149      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
150      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
151      */
152     @PUT
153     @Path("/Model/Load")
154     public ApexApiResult loadFromString(final String jsonString) {
155         return processRestCommand(RestCommandType.MODEL, RestCommand.LOAD, jsonString);
156     }
157
158     /**
159      * Analyse the model and return analysis results. If successful the analysis results will be available in the
160      * messages in the result.
161      *
162      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
163      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
164      */
165     @GET
166     @Path("Model/Analyse")
167     public ApexApiResult analyse() {
168         return processRestCommand(RestCommandType.MODEL, RestCommand.ANALYSE);
169     }
170
171     /**
172      * Validate the model and return validation results. If successful the validation results will be available in the
173      * messages in the result.
174      *
175      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
176      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
177      */
178     @GET
179     @Path("Model/Validate")
180     public ApexApiResult validate() {
181         return processRestCommand(RestCommandType.MODEL, RestCommand.VALIDATE);
182     }
183
184     /**
185      * Creates the new model model for this session.
186      *
187      * @param jsonString the JSON string to be parsed containing the new model. See {@code BeanModel}
188      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
189      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
190      */
191     @POST
192     @Path("Model/Create")
193     public ApexApiResult createModel(final String jsonString) {
194         return processRestCommand(RestCommandType.MODEL, RestCommand.CREATE, jsonString);
195     }
196
197     /**
198      * Update the model for this session.
199      *
200      * @param jsonString the JSON string to be parsed containing the updated model. See {@code BeanModel}
201      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
202      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
203      */
204     @PUT
205     @Path("Model/Update")
206     public ApexApiResult updateModel(final String jsonString) {
207         return processRestCommand(RestCommandType.MODEL, RestCommand.UPDATE, jsonString);
208     }
209
210     /**
211      * Gets the key for the model for this session. If successful the model key will be available in the first message
212      * in the result. See {@code AxKey}
213      *
214      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
215      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
216      */
217     @GET
218     @Path("Model/GetKey")
219     public ApexApiResult getModelKey() {
220         return processRestCommand(RestCommandType.MODEL, RestCommand.GET_KEY);
221     }
222
223     /**
224      * Retrieve the model for this session. If successful the model will be available in the first message in the
225      * result. The returned value will be similar to a {@code AxPolicyModel}, with merged {@code AxKeyInfo} for the root
226      * object.
227      *
228      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
229      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
230      */
231     @GET
232     @Path("Model/Get")
233     public ApexApiResult listModel() {
234         return processRestCommand(RestCommandType.MODEL, RestCommand.LIST);
235     }
236
237     /**
238      * Download the model for this session as a String.
239      *
240      * @return the model represented as a JSON string. See {@code AxPolicyModel}
241      */
242     @GET
243     @Path("Model/Download")
244     public String downloadModel() {
245         ApexApiResult result = processRestCommand(RestCommandType.MODEL, RestCommand.DOWNLOAD);
246         if (result != null && result.isOk()) {
247             return result.getMessage();
248         } else {
249             return null;
250         }
251     }
252
253     /**
254      * Uploads a Policy Model to a configured endpoint converting it to tosca based on the given apex config and tosca
255      * templates.
256      *
257      * @param toscaTemplateFileStream the tosca template file input stream
258      * @param apexConfigFileStream the apex config file input stream
259      * @return an ApexAPIResult that contains the operation status and success/error messages
260      */
261     @POST
262     @Path("Model/Upload")
263     @Consumes({MediaType.MULTIPART_FORM_DATA})
264     public ApexApiResult uploadModel(@FormDataParam("tosca-template-file") InputStream toscaTemplateFileStream,
265                                      @FormDataParam("apex-config-file") InputStream apexConfigFileStream) {
266         final ApexApiResult result = new ApexApiResult();
267         final RestSession session = SESSION_HANDLER.getSession(sessionId, result);
268         if (session == null) {
269             return result;
270         }
271         return policyUploadHandler.doUpload(session.getApexModel(), toscaTemplateFileStream, apexConfigFileStream);
272     }
273
274     /**
275      * Delete the model for this session.
276      *
277      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
278      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
279      */
280     @DELETE
281     @Path("Model/Delete")
282     public ApexApiResult deleteModel() {
283         return processRestCommand(RestCommandType.MODEL, RestCommand.DELETE);
284     }
285
286     /**
287      * List key information with the given key names/versions. If successful the result(s) will be available in the
288      * result messages. See {@code AxKeyInfo}
289      *
290      * @param name the name to search for. If null or empty, then all names will be queried
291      * @param version the version to search for. If null then all versions will be searched for.
292      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
293      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
294      */
295     @GET
296     @Path("KeyInformation/Get")
297     public ApexApiResult listKeyInformation(@QueryParam(NAME) final String name,
298             @QueryParam(VERSION) final String version) {
299         return processRestCommand(RestCommandType.KEY_INFO, RestCommand.LIST, name, version);
300     }
301
302     /**
303      * Creates a context schema with the information in the JSON string passed.
304      *
305      * @param jsonString the JSON string to be parsed. See {@code BeanContextSchema}
306      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
307      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
308      */
309     @POST
310     @Path("ContextSchema/Create")
311     public ApexApiResult createContextSchema(final String jsonString) {
312         return processRestCommand(RestCommandType.CONTEXT_SCHEMA, RestCommand.CREATE, jsonString);
313     }
314
315     /**
316      * Update a context schema with the information in the JSON string passed.
317      *
318      * @param jsonString the JSON string to be parsed. See {@code BeanContextSchema}
319      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
320      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
321      */
322     @PUT
323     @Path("ContextSchema/Update")
324     public ApexApiResult updateContextSchema(final String jsonString) {
325         return processRestCommand(RestCommandType.CONTEXT_SCHEMA, RestCommand.UPDATE, jsonString);
326     }
327
328     /**
329      * List context schemas with the given key names/versions. If successful the result(s) will be available in the
330      * result messages. The returned value(s) will be similar to {@code AxContextSchema}, with merged {@code AxKeyInfo}
331      * for the root object.
332      *
333      * @param name the name to search for. If null or empty, then all names will be queried
334      * @param version the version to search for. If null then all versions will be searched for.
335      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
336      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
337      */
338     @GET
339     @Path("ContextSchema/Get")
340     public ApexApiResult listContextSchemas(@QueryParam(NAME) final String name,
341             @QueryParam(VERSION) final String version) {
342         return processRestCommand(RestCommandType.CONTEXT_SCHEMA, RestCommand.LIST, name, version);
343     }
344
345     /**
346      * Delete context schemas with the given key names/versions.
347      *
348      * @param name the name to search for. If null or empty, then all names will be queried
349      * @param version the version to search for. If null then all versions will be searched for.
350      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
351      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
352      */
353     @DELETE
354     @Path("ContextSchema/Delete")
355     public ApexApiResult deleteContextSchema(@QueryParam(NAME) final String name,
356             @QueryParam(VERSION) final String version) {
357         return processRestCommand(RestCommandType.CONTEXT_SCHEMA, RestCommand.DELETE, name, version);
358     }
359
360     /**
361      * Validate context schemas with the given key names/versions. The result(s) will be available in the result
362      * messages.
363      *
364      * @param name the name to search for. If null or empty, then all names will be queried
365      * @param version the version to search for. If null then all versions will be searched for.
366      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
367      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
368      */
369     @GET
370     @Path("Validate/ContextSchema")
371     public ApexApiResult validateContextSchemas(@QueryParam(NAME) final String name,
372             @QueryParam(VERSION) final String version) {
373         return processRestCommand(RestCommandType.CONTEXT_SCHEMA, RestCommand.VALIDATE, name, version);
374     }
375
376     /**
377      * Creates a context album with the information in the JSON string passed.
378      *
379      * @param jsonString the JSON string to be parsed. See {@code BeanContextAlbum}
380      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
381      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
382      */
383     @POST
384     @Path("ContextAlbum/Create")
385     public ApexApiResult createContextAlbum(final String jsonString) {
386         return processRestCommand(RestCommandType.CONTEXT_ALBUM, RestCommand.CREATE, jsonString);
387     }
388
389     /**
390      * Update a context album with the information in the JSON string passed.
391      *
392      * @param jsonString the JSON string to be parsed. See {@code BeanContextAlbum}
393      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
394      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
395      */
396     @PUT
397     @Path("ContextAlbum/Update")
398     public ApexApiResult updateContextAlbum(final String jsonString) {
399         return processRestCommand(RestCommandType.CONTEXT_ALBUM, RestCommand.UPDATE, jsonString);
400     }
401
402     /**
403      * List context albums with the given key names/versions. If successful the result(s) will be available in the
404      * result messages. The returned value(s) will be similar to {@code AxContextAlbum}, with merged {@code AxKeyInfo}
405      * for the root object.
406      *
407      * @param name the name to search for. If null or empty, then all names will be queried
408      * @param version the version to search for. If null then all versions will be searched for.
409      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
410      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
411      */
412     @GET
413     @Path("ContextAlbum/Get")
414     public ApexApiResult listContextAlbums(@QueryParam(NAME) final String name,
415             @QueryParam(VERSION) final String version) {
416         return processRestCommand(RestCommandType.CONTEXT_ALBUM, RestCommand.LIST, name, version);
417     }
418
419     /**
420      * Delete context albums with the given key names/versions.
421      *
422      * @param name the name to search for. If null or empty, then all names will be queried
423      * @param version the version to search for. If null then all versions will be searched for.
424      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
425      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
426      */
427     @DELETE
428     @Path("ContextAlbum/Delete")
429     public ApexApiResult deleteContextAlbum(@QueryParam(NAME) final String name,
430             @QueryParam(VERSION) final String version) {
431         return processRestCommand(RestCommandType.CONTEXT_ALBUM, RestCommand.DELETE, name, version);
432     }
433
434     /**
435      * Validate context albums with the given key names/versions. The result(s) will be available in the result
436      * messages.
437      *
438      * @param name the name to search for. If null or empty, then all names will be queried
439      * @param version the version to search for. If null then all versions will be searched for.
440      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
441      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
442      */
443     @GET
444     @Path("Validate/ContextAlbum")
445     public ApexApiResult validateContextAlbums(@QueryParam(NAME) final String name,
446             @QueryParam(VERSION) final String version) {
447         return processRestCommand(RestCommandType.CONTEXT_ALBUM, RestCommand.VALIDATE, name, version);
448     }
449
450     /**
451      * Creates an event with the information in the JSON string passed.
452      *
453      * @param jsonString the JSON string to be parsed. See {@code BeanEvent}
454      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
455      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
456      */
457     @POST
458     @Path("Event/Create")
459     public ApexApiResult createEvent(final String jsonString) {
460         return processRestCommand(RestCommandType.EVENT, RestCommand.CREATE, jsonString);
461     }
462
463     /**
464      * Update an event with the information in the JSON string passed.
465      *
466      * @param jsonString the JSON string to be parsed. See {@code BeanEvent}
467      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
468      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
469      */
470     @PUT
471     @Path("Event/Update")
472     public ApexApiResult updateEvent(final String jsonString) {
473         return processRestCommand(RestCommandType.EVENT, RestCommand.UPDATE, jsonString);
474     }
475
476     /**
477      * List events with the given key names/versions. If successful the result(s) will be available in the result
478      * messages. The returned value(s) will be similar to {@code AxEvent}, with merged {@code AxKeyInfo} for the root
479      * object.
480      *
481      * @param name the name to search for. If null or empty, then all names will be queried
482      * @param version the version to search for. If null then all versions will be searched for.
483      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
484      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
485      */
486     @GET
487     @Path("Event/Get")
488     public ApexApiResult listEvent(@QueryParam(NAME) final String name, @QueryParam(VERSION) final String version) {
489         return processRestCommand(RestCommandType.EVENT, RestCommand.LIST, name, version);
490     }
491
492     /**
493      * Delete events with the given key names/versions.
494      *
495      * @param name the name to search for. If null or empty, then all names will be queried
496      * @param version the version to search for. If null then all versions will be searched for.
497      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
498      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
499      */
500     @DELETE
501     @Path("Event/Delete")
502     public ApexApiResult deleteEvent(@QueryParam(NAME) final String name, @QueryParam(VERSION) final String version) {
503         return processRestCommand(RestCommandType.EVENT, RestCommand.DELETE, name, version);
504     }
505
506     /**
507      * Validate events with the given key names/versions. The result(s) will be available in the result messages.
508      *
509      * @param name the name to search for. If null or empty, then all names will be queried
510      * @param version the version to search for. If null then all versions will be searched for.
511      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
512      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
513      */
514     @GET
515     @Path("Validate/Event")
516     public ApexApiResult validateEvent(@QueryParam(NAME) final String name, @QueryParam(VERSION) final String version) {
517         return processRestCommand(RestCommandType.EVENT, RestCommand.VALIDATE, name, version);
518     }
519
520     /**
521      * Creates a task with the information in the JSON string passed.
522      *
523      * @param jsonString the JSON string to be parsed. See {@code BeanTask}
524      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
525      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
526      */
527     @POST
528     @Path("Task/Create")
529     public ApexApiResult createTask(final String jsonString) {
530         return processRestCommand(RestCommandType.TASK, RestCommand.CREATE, jsonString);
531     }
532
533     /**
534      * Update a task with the information in the JSON string passed.
535      *
536      * @param jsonString the JSON string to be parsed. See {@code BeanTask}
537      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
538      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
539      */
540     @PUT
541     @Path("Task/Update")
542     public ApexApiResult updateTask(final String jsonString) {
543         return processRestCommand(RestCommandType.TASK, RestCommand.UPDATE, jsonString);
544     }
545
546     /**
547      * List tasks with the given key names/versions. If successful the result(s) will be available in the result
548      * messages. The returned value(s) will be similar to {@code AxTask}, with merged {@code AxKeyInfo} for the root
549      * object.
550      *
551      * @param name the name to search for. If null or empty, then all names will be queried
552      * @param version the version to search for. If null then all versions will be searched for.
553      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
554      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
555      */
556     @GET
557     @Path("Task/Get")
558     public ApexApiResult listTask(@QueryParam(NAME) final String name, @QueryParam(VERSION) final String version) {
559         return processRestCommand(RestCommandType.TASK, RestCommand.LIST, name, version);
560     }
561
562     /**
563      * Delete tasks with the given key names/versions.
564      *
565      * @param name the name to search for. If null or empty, then all names will be queried
566      * @param version the version to search for. If null then all versions will be searched for.
567      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
568      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
569      */
570     @DELETE
571     @Path("Task/Delete")
572     public ApexApiResult deleteTask(@QueryParam(NAME) final String name, @QueryParam(VERSION) final String version) {
573         return processRestCommand(RestCommandType.TASK, RestCommand.DELETE, name, version);
574     }
575
576     /**
577      * Validate tasks with the given key names/versions. The result(s) will be available in the result messages.
578      *
579      * @param name the name to search for. If null or empty, then all names will be queried
580      * @param version the version to search for. If null then all versions will be searched for.
581      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
582      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
583      */
584     @GET
585     @Path("Validate/Task")
586     public ApexApiResult validateTask(@QueryParam(NAME) final String name, @QueryParam(VERSION) final String version) {
587         return processRestCommand(RestCommandType.TASK, RestCommand.VALIDATE, name, version);
588     }
589
590     // CHECKSTYLE:OFF: MethodLength
591     /**
592      * Creates a policy with the information in the JSON string passed.
593      *
594      * @param jsonString the JSON string to be parsed See {@code BeanPolicy}
595      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
596      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
597      */
598     @POST
599     @Path("Policy/Create")
600     public ApexApiResult createPolicy(final String jsonString) {
601         return processRestCommand(RestCommandType.POLICY, RestCommand.CREATE, jsonString);
602     }
603
604     /**
605      * Update a policy with the information in the JSON string passed.
606      *
607      * @param firstStatePeriodic indicates if periodic event should be created and added to model
608      * @param jsonString the JSON string to be parsed. See {@code BeanPolicy}
609      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
610      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
611      */
612     @PUT
613     @Path("Policy/Update")
614     public ApexApiResult updatePolicy(@QueryParam("firstStatePeriodic") final boolean firstStatePeriodic,
615             final String jsonString) {
616
617         ApexApiResult result = processRestCommand(RestCommandType.POLICY, RestCommand.UPDATE, jsonString);
618         if (result != null && result.isOk() && firstStatePeriodic) {
619             result = createPeriodicEvent();
620         }
621         return result;
622     }
623
624     /**
625      * List policies with the given key names/versions. If successful the result(s) will be available in the result
626      * messages. The returned value(s) will be similar to {@code AxPolicy}, with merged {@code AxKeyInfo} for the root
627      * object.
628      *
629      * @param name the name to search for. If null or empty, then all names will be queried
630      * @param version the version to search for. If null then all versions will be searched for.
631      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
632      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
633      */
634     @GET
635     @Path("Policy/Get")
636     public ApexApiResult listPolicy(@QueryParam(NAME) final String name, @QueryParam(VERSION) final String version) {
637         return processRestCommand(RestCommandType.POLICY, RestCommand.LIST, name, version);
638     }
639
640     /**
641      * Delete policies with the given key names/versions.
642      *
643      * @param name the name to search for. If null or empty, then all names will be queried
644      * @param version the version to search for. If null then all versions will be searched for.
645      * @return an ApexAPIResult object. If successful then {@link ApexApiResult#isOk()} will return true. Any
646      *         messages/errors can be retrieved using {@link ApexApiResult#getMessages()}
647      */
648     @DELETE
649     @Path("Policy/Delete")
650     public ApexApiResult deletePolicy(@QueryParam(NAME) final String name, @QueryParam(VERSION) final String version) {
651         return processRestCommand(RestCommandType.POLICY, RestCommand.DELETE, name, version);
652     }
653
654     /**
655      * This method routes REST commands that take no parameters to their caller.
656      *
657      * @param commandType the type of REST command to process
658      * @param command the REST command to process
659      * @return the result of the REST command
660      */
661     private ApexApiResult processRestCommand(final RestCommandType commandType, final RestCommand command) {
662         LOGGER.entry(commandType);
663         try {
664             ApexApiResult result = new ApexApiResult();
665             RestSession session = SESSION_HANDLER.getSession(sessionId, result);
666             if (session == null) {
667                 return result;
668             }
669             result = executeRestCommand(session, commandType, command);
670             LOGGER.exit(SESSION_CREATE + (result != null && result.isOk() ? OK : NOT_OK));
671             return result;
672         } catch (final Exception e) {
673             LOGGER.catching(e);
674             LOGGER.exit(SESSION_CREATE_NOT_OK);
675             throw e;
676         }
677     }
678
679     /**
680      * This method routes REST commands that take a JSON string to their caller.
681      *
682      * @param commandType the type of REST command to process
683      * @param command the REST command to process
684      * @param jsonString the JSON string received in the REST request
685      * @return the result of the REST command
686      */
687     private ApexApiResult processRestCommand(final RestCommandType commandType, final RestCommand command,
688             final String jsonString) {
689         LOGGER.entry(commandType, jsonString);
690         try {
691             ApexApiResult result = new ApexApiResult();
692             RestSession session = SESSION_HANDLER.getSession(sessionId, result);
693             if (session == null) {
694                 return result;
695             }
696             result = executeRestCommand(session, commandType, command, jsonString);
697             LOGGER.exit(SESSION_CREATE + (result != null && result.isOk() ? OK : NOT_OK));
698             return result;
699         } catch (final Exception e) {
700             LOGGER.catching(e);
701             LOGGER.exit(SESSION_CREATE_NOT_OK);
702             throw e;
703         }
704     }
705
706     /**
707      * This method routes REST commands that take a name and version to their caller.
708      *
709      * @param commandType the type of REST command to process
710      * @param command the REST command to process
711      * @param name the name received in the REST request
712      * @param version the name received in the REST request
713      * @return the result of the REST command
714      */
715     private ApexApiResult processRestCommand(final RestCommandType commandType, final RestCommand command,
716             final String name, final String version) {
717         LOGGER.entry(commandType, name, version);
718         try {
719             ApexApiResult result = new ApexApiResult();
720             RestSession session = SESSION_HANDLER.getSession(sessionId, result);
721             if (session == null) {
722                 return result;
723             }
724             result = executeRestCommand(session, commandType, command, name, version);
725             LOGGER.exit(SESSION_CREATE + (result != null && result.isOk() ? OK : NOT_OK));
726             return result;
727         } catch (final Exception e) {
728             LOGGER.catching(e);
729             LOGGER.exit(SESSION_CREATE_NOT_OK);
730             throw e;
731         }
732     }
733
734     /**
735      * This method invokes callers to run REST commands that take no parameters.
736      *
737      * @param session the Apex editor session
738      * @param commandType the type of REST command to process
739      * @param command the REST command to process
740      * @return the result of the REST command
741      */
742     @Override
743     public ApexApiResult executeRestCommand(final RestSession session, final RestCommandType commandType,
744             final RestCommand command) {
745         switch (commandType) {
746             case MODEL:
747                 return MODEL_HANDLER.executeRestCommand(session, commandType, command);
748             case KEY_INFO:
749                 return KEY_INFO_HANDLER.executeRestCommand(session, commandType, command);
750             case CONTEXT_SCHEMA:
751                 return CONTEXT_SCHEMA_HANDLER.executeRestCommand(session, commandType, command);
752             case CONTEXT_ALBUM:
753                 return CONTEXT_ALBUM_HANDLER.executeRestCommand(session, commandType, command);
754             case EVENT:
755                 return EVENT_HANDLER.executeRestCommand(session, commandType, command);
756             case TASK:
757                 return TASK_HANDLER.executeRestCommand(session, commandType, command);
758             case POLICY:
759                 return POLICY_HANDLER.executeRestCommand(session, commandType, command);
760             default:
761                 return new ApexApiResult(Result.FAILED, REST_COMMAND_NOT_RECOGNISED);
762         }
763     }
764
765     /**
766      * This method invokes callers to run REST commands that take a JSON string.
767      *
768      * @param session the Apex editor session
769      * @param commandType the type of REST command to process
770      * @param command the REST command to process
771      * @param jsonString the JSON string received in the REST request
772      * @return the result of the REST command
773      */
774     @Override
775     public ApexApiResult executeRestCommand(final RestSession session, final RestCommandType commandType,
776             final RestCommand command, final String jsonString) {
777         switch (commandType) {
778             case MODEL:
779                 return MODEL_HANDLER.executeRestCommand(session, commandType, command, jsonString);
780             case KEY_INFO:
781                 return KEY_INFO_HANDLER.executeRestCommand(session, commandType, command, jsonString);
782             case CONTEXT_SCHEMA:
783                 return CONTEXT_SCHEMA_HANDLER.executeRestCommand(session, commandType, command, jsonString);
784             case CONTEXT_ALBUM:
785                 return CONTEXT_ALBUM_HANDLER.executeRestCommand(session, commandType, command, jsonString);
786             case EVENT:
787                 return EVENT_HANDLER.executeRestCommand(session, commandType, command, jsonString);
788             case TASK:
789                 return TASK_HANDLER.executeRestCommand(session, commandType, command, jsonString);
790             case POLICY:
791                 return POLICY_HANDLER.executeRestCommand(session, commandType, command, jsonString);
792             default:
793                 return new ApexApiResult(Result.FAILED, REST_COMMAND_NOT_RECOGNISED);
794         }
795     }
796
797     /**
798      * This method invokes callers to run REST commands that take a name and version.
799      *
800      * @param session the Apex editor session
801      * @param commandType the type of REST command to process
802      * @param command the REST command to process
803      * @param name the name received in the REST request
804      * @param version the name received in the REST request
805      * @return the result of the REST command
806      */
807     @Override
808     public ApexApiResult executeRestCommand(final RestSession session, final RestCommandType commandType,
809             final RestCommand command, final String name, final String version) {
810         switch (commandType) {
811             case MODEL:
812                 return MODEL_HANDLER.executeRestCommand(session, commandType, command, name, version);
813             case KEY_INFO:
814                 return KEY_INFO_HANDLER.executeRestCommand(session, commandType, command, name, version);
815             case CONTEXT_SCHEMA:
816                 return CONTEXT_SCHEMA_HANDLER.executeRestCommand(session, commandType, command, name, version);
817             case CONTEXT_ALBUM:
818                 return CONTEXT_ALBUM_HANDLER.executeRestCommand(session, commandType, command, name, version);
819             case EVENT:
820                 return EVENT_HANDLER.executeRestCommand(session, commandType, command, name, version);
821             case TASK:
822                 return TASK_HANDLER.executeRestCommand(session, commandType, command, name, version);
823             case POLICY:
824                 return POLICY_HANDLER.executeRestCommand(session, commandType, command, name, version);
825             default:
826                 return new ApexApiResult(Result.FAILED, REST_COMMAND_NOT_RECOGNISED);
827         }
828     }
829
830     /**
831      * Create a periodic event from the periodic event template.
832      */
833     private ApexApiResult createPeriodicEvent() {
834         String periodicEventJsonString;
835         try {
836             periodicEventJsonString = TextFileUtils.getTextFileAsString(PERIODIC_EVENT_TEMPLATE);
837         } catch (IOException ioException) {
838             String message = "read of periodic event tempalte from " + PERIODIC_EVENT_TEMPLATE + "failed: "
839                     + ioException.getMessage();
840             LOGGER.debug(message, ioException);
841             return new ApexApiResult(Result.FAILED, message);
842         }
843
844         return processRestCommand(RestCommandType.EVENT, RestCommand.CREATE, periodicEventJsonString);
845     }
846
847     /*
848      * This method is used only for testing and is used to cause an exception on calls from unit test to test exception
849      * handling.
850      */
851     protected static int createCorruptSession() {
852         final ApexEditorRestResource apexEditorRestResource = new ApexEditorRestResource();
853         final ApexApiResult result = apexEditorRestResource.createSession();
854         final int corruptSessionId = Integer.parseInt(result.getMessages().get(0));
855
856         SESSION_HANDLER.setCorruptSession(corruptSessionId);
857
858         return corruptSessionId;
859     }
860
861 }