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