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