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