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