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