83ca529f6f5063c6ef920e1f1434a926c168d22f
[policy/apex-pdp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
4  * ================================================================================
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.apex.client.editor.rest;
22
23 import com.google.gson.Gson;
24 import com.google.gson.GsonBuilder;
25 import com.google.gson.JsonObject;
26
27 import java.util.ArrayList;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Map.Entry;
31 import java.util.TreeMap;
32
33 import javax.ws.rs.Consumes;
34 import javax.ws.rs.DELETE;
35 import javax.ws.rs.GET;
36 import javax.ws.rs.POST;
37 import javax.ws.rs.PUT;
38 import javax.ws.rs.Path;
39 import javax.ws.rs.PathParam;
40 import javax.ws.rs.Produces;
41 import javax.ws.rs.QueryParam;
42 import javax.ws.rs.core.MediaType;
43
44 import org.onap.policy.apex.client.editor.rest.bean.BeanContextAlbum;
45 import org.onap.policy.apex.client.editor.rest.bean.BeanContextSchema;
46 import org.onap.policy.apex.client.editor.rest.bean.BeanEvent;
47 import org.onap.policy.apex.client.editor.rest.bean.BeanField;
48 import org.onap.policy.apex.client.editor.rest.bean.BeanKeyRef;
49 import org.onap.policy.apex.client.editor.rest.bean.BeanLogic;
50 import org.onap.policy.apex.client.editor.rest.bean.BeanModel;
51 import org.onap.policy.apex.client.editor.rest.bean.BeanPolicy;
52 import org.onap.policy.apex.client.editor.rest.bean.BeanState;
53 import org.onap.policy.apex.client.editor.rest.bean.BeanStateOutput;
54 import org.onap.policy.apex.client.editor.rest.bean.BeanStateTaskRef;
55 import org.onap.policy.apex.client.editor.rest.bean.BeanTask;
56 import org.onap.policy.apex.client.editor.rest.bean.BeanTaskParameter;
57 import org.onap.policy.apex.model.basicmodel.concepts.AxKey;
58 import org.onap.policy.apex.model.basicmodel.concepts.AxKeyInfo;
59 import org.onap.policy.apex.model.contextmodel.concepts.AxContextAlbum;
60 import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchema;
61 import org.onap.policy.apex.model.eventmodel.concepts.AxEvent;
62 import org.onap.policy.apex.model.modelapi.ApexAPIResult;
63 import org.onap.policy.apex.model.modelapi.ApexAPIResult.RESULT;
64 import org.onap.policy.apex.model.modelapi.ApexModel;
65 import org.onap.policy.apex.model.modelapi.ApexModelFactory;
66 import org.onap.policy.apex.model.policymodel.concepts.AxPolicy;
67 import org.onap.policy.apex.model.policymodel.concepts.AxPolicyModel;
68 import org.onap.policy.apex.model.policymodel.concepts.AxTask;
69 import org.slf4j.ext.XLogger;
70 import org.slf4j.ext.XLoggerFactory;
71
72 /**
73  * The class represents the root resource exposed at the base URL<br>
74  * The url to access this resource would be in the form {@code <baseURL>/rest/<session>/....} <br>
75  * For example: a PUT request to the following URL
76  * {@code http://localhost:8080/apex/rest/109/ContextSchema/Update}, with a JSON string payload
77  * containing the new {@code Schema} in the body, can be explained as:
78  * <ul>
79  * <li>The server or servlet is running at the base URL {@code http://localhost:8080/apex}
80  * <li>This resource {@code ApexRestEditorResource} is used because the path {@code rest/109}
81  * matches the {@code Path} filter specification for this Resource
82  * ({@code @Path("rest/{session}")}), where the {@code int} path parameter {@code session} is
83  * assigned the {@code int} value {@code 109}
84  * <li>The path {@code ContextSchema/Update} redirects this call to the method
85  * {@link #updateContextSchema(String)}, which should be a {@link javax.ws.rs.PUT}, with a single
86  * String in the body/payload which gets mapped to the single String parameter for the method.
87  * <li>So, in summary, the REST request updates a {@code ContextSchema} as specified in the payload
88  * for {@code session} number {@code 109}
89  * </ul>
90  *
91  * <b>Note:</b> An allocated {@code Session} identifier must be included in (almost) all requests.
92  * Models for different {@code Session} identifiers are completely isolated from one another.
93  *
94  * <b>Note:</b> To create a new {@code Session}, and have a new session ID allocated use
95  * {@link javax.ws.rs.GET} request to {@code <baseURL>/rest/-1/Session/Create} (for example:
96  * {@code http://localhost:8080/apex/rest/-1/Session/Create} )
97  *
98  */
99 @Path("editor/{session}")
100 @Produces({MediaType.APPLICATION_JSON})
101 @Consumes({MediaType.APPLICATION_JSON})
102
103 public class ApexEditorRestResource {
104     // Get a reference to the logger
105     private static final XLogger LOGGER = XLoggerFactory.getXLogger(ApexEditorRestResource.class);
106
107     // The next session will have this number, stating at 0
108     private static int nextSession = 0;
109
110     // All REST editor sessions being handled by the server
111     private static final Map<Integer, ApexModel> SESSIONMODELMAP = new TreeMap<>();
112
113     // The ID of this session. This gets injected from the URL.
114     @PathParam("session")
115     private int sessionID = -1;
116
117     // The Apex model for the session
118     private ApexModel sessionApexModel = null;
119
120     /**
121      * This method sets the Apex model for the current editor session. Don't forget to call
122      * {@link #commitChanges()} when finished! This makes requests atomic.
123      *
124      * @return the result of finding the session Apex model and setting it
125      */
126     private ApexAPIResult initialiseSessionForChanges() {
127         if (sessionID < 0) {
128             return new ApexAPIResult(RESULT.FAILED, "Session ID  \"" + sessionID + "\" is negative");
129         }
130
131         if (!SESSIONMODELMAP.containsKey(sessionID)) {
132             return new ApexAPIResult(RESULT.FAILED, "A session with session ID \"" + sessionID + "\" does not exist");
133         }
134
135         if (sessionApexModel == null) {
136             sessionApexModel = SESSIONMODELMAP.get(sessionID).clone();
137         }
138         return new ApexAPIResult();
139     }
140
141     /**
142      * This method sets the Apex model for the current editor session. Don't make any changes to the
143      * model.
144      *
145      * @return the result of finding the session Apex model and setting it
146      */
147     private ApexAPIResult initialiseSessionForReadOnly() {
148         if (sessionID < 0) {
149             return new ApexAPIResult(RESULT.FAILED, "Session ID  \"" + sessionID + "\" is negative");
150         }
151
152         if (!SESSIONMODELMAP.containsKey(sessionID)) {
153             return new ApexAPIResult(RESULT.FAILED, "A session with session ID \"" + sessionID + "\" does not exist");
154         }
155
156         if (sessionApexModel == null) {
157             sessionApexModel = SESSIONMODELMAP.get(sessionID);
158         }
159         return new ApexAPIResult();
160     }
161
162     /**
163      * This method commits changes to the Apex model for the current editor session. This should
164      * only be called once, at the end of a successful change to the model for this session
165      *
166      * @return the result of committing the session Apex model
167      */
168     private ApexAPIResult commitChanges() {
169
170         if (sessionApexModel == null) {
171             return new ApexAPIResult(RESULT.FAILED, "Cannot commit a changes for Session ID  \"" + sessionID
172                     + "\", because it has not been initialised / started");
173         }
174
175         SESSIONMODELMAP.put(sessionID, sessionApexModel);
176
177         return new ApexAPIResult();
178     }
179
180     /**
181      * Creates a new session. Always call this method with sessionID -1, whereby a new sessionID
182      * will be allocated. If successful the new sessionID will be available in the first message in
183      * the result.
184      *
185      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
186      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}.
187      *         This includes the session id for this session.
188      */
189     @GET
190     @Path("Session/Create")
191     public ApexAPIResult createSession() {
192         ApexAPIResult ret = null;
193         LOGGER.entry();
194         try {
195             if (sessionID != -1) {
196                 ret = new ApexAPIResult(RESULT.FAILED, "Session ID must be set to -1 to create sessions: " + sessionID);
197                 return ret;
198             }
199
200             final int newSessionID = nextSession;
201
202             if (SESSIONMODELMAP.containsKey(newSessionID)) {
203                 ret = new ApexAPIResult(RESULT.FAILED, "Session already exists for session: " + newSessionID);
204                 return ret;
205             }
206
207             SESSIONMODELMAP.put(newSessionID, new ApexModelFactory().createApexModel(null, true));
208             nextSession++;
209
210             ret = new ApexAPIResult(RESULT.SUCCESS, Integer.toString(newSessionID));
211             return ret;
212         } catch (final Exception e) {
213             LOGGER.catching(e);
214             throw e;
215         } finally {
216             LOGGER.exit((ret == null ? false : ret.isOK()));
217             LOGGER.info("Session/Create" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
218         }
219     }
220
221     /**
222      * Load the model from a JSON string for this session.
223      *
224      * @param jsonString the JSON string to be parsed. The returned value(s) will be similar to
225      *        {@link AxPolicyModel}, with merged {@linkplain AxKeyInfo} for the root object.
226      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
227      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
228      */
229     @PUT
230     @Path("/Model/Load")
231     public ApexAPIResult loadFromString(final String jsonString) {
232         ApexAPIResult ret = null;
233         LOGGER.entry(jsonString);
234         try {
235             ret = initialiseSessionForChanges();
236             if (ret.isNOK()) {
237                 return ret;
238             }
239
240             ret = sessionApexModel.loadFromString(jsonString);
241             if (ret.isOK()) {
242                 commitChanges();
243             }
244             return ret;
245         } catch (final Exception e) {
246             LOGGER.catching(e);
247             throw e;
248         } finally {
249             LOGGER.exit((ret == null ? false : ret.isOK()));
250             LOGGER.info("Model/Load" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
251         }
252     }
253
254     /**
255      * Analyse the model and return analysis results. If successful the analysis results will be
256      * available in the messages in the result.
257      *
258      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
259      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
260      */
261     @GET
262     @Path("Model/Analyse")
263     public ApexAPIResult analyse() {
264         ApexAPIResult ret = null;
265         LOGGER.entry();
266         try {
267             ret = initialiseSessionForReadOnly();
268             if (ret.isNOK()) {
269                 return ret;
270             }
271
272             ret = sessionApexModel.analyse();
273             return ret;
274         } catch (final Exception e) {
275             LOGGER.catching(e);
276             throw e;
277         } finally {
278             LOGGER.exit((ret == null ? false : ret.isOK()));
279             LOGGER.info("Model/Analyse" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
280         }
281     }
282
283     /**
284      * Validate the model and return validation results. If successful the validation results will
285      * be available in the messages in the result.
286      *
287      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
288      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
289      */
290     @GET
291     @Path("Model/Validate")
292     public ApexAPIResult validate() {
293         ApexAPIResult ret = null;
294         LOGGER.entry();
295         try {
296             ret = initialiseSessionForReadOnly();
297             if (ret.isNOK()) {
298                 return ret;
299             }
300
301             ret = sessionApexModel.validate();
302
303             ret = addKeyInfo2Messages(ret);
304             return ret;
305         } catch (final Exception e) {
306             LOGGER.catching(e);
307             throw e;
308         } finally {
309             LOGGER.exit((ret == null ? false : ret.isOK()));
310             LOGGER.info("Model/Validate" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
311         }
312     }
313
314     /**
315      * Creates the new model model for this session.
316      *
317      * @param jsonString the JSON string to be parsed containing the new model. See
318      *        {@linkplain BeanModel}
319      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
320      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
321      */
322     @POST
323     @Path("Model/Create")
324     public ApexAPIResult createModel(final String jsonString) {
325         ApexAPIResult ret = null;
326         LOGGER.entry(jsonString);
327         try {
328             ret = initialiseSessionForChanges();
329             if (ret.isNOK()) {
330                 return ret;
331             }
332
333             final BeanModel jsonbean = RestUtils.getJSONParameters(jsonString, BeanModel.class);
334             ret = sessionApexModel.createModel(jsonbean.getName(), jsonbean.getVersion(), jsonbean.getUuid(),
335                     jsonbean.getDescription());
336
337             if (ret.isOK()) {
338                 ret = addKeyInfo2Messages(ret);
339             }
340             if (ret.isOK()) {
341                 commitChanges();
342             }
343             return ret;
344         } catch (final Exception e) {
345             LOGGER.catching(e);
346             throw e;
347         } finally {
348             LOGGER.exit((ret == null ? false : ret.isOK()));
349             LOGGER.info("Model/Create" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
350         }
351     }
352
353     /**
354      * Update the model for this session.
355      *
356      * @param jsonString the JSON string to be parsed containing the updated model. See
357      *        {@linkplain BeanModel}
358      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
359      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
360      */
361     @PUT
362     @Path("Model/Update")
363     public ApexAPIResult updateModel(final String jsonString) {
364         ApexAPIResult ret = null;
365         LOGGER.entry(jsonString);
366         try {
367             ret = initialiseSessionForChanges();
368             if (ret.isNOK()) {
369                 return ret;
370             }
371
372             final BeanModel jsonbean = RestUtils.getJSONParameters(jsonString, BeanModel.class);
373             ret = sessionApexModel.updateModel(jsonbean.getName(), jsonbean.getVersion(), jsonbean.getUuid(),
374                     jsonbean.getDescription());
375             if (ret.isOK()) {
376                 commitChanges();
377             }
378             return ret;
379         } catch (final Exception e) {
380             LOGGER.catching(e);
381             throw e;
382         } finally {
383             LOGGER.exit((ret == null ? false : ret.isOK()));
384             LOGGER.info("Model/Update" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
385         }
386     }
387
388     /**
389      * Gets the key for the model for this session. If successful the model key will be available in
390      * the first message in the result. See {@linkplain AxKey}
391      *
392      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
393      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
394      */
395     @GET
396     @Path("Model/GetKey")
397     public ApexAPIResult getModelKey() {
398         ApexAPIResult ret = null;
399         LOGGER.entry();
400         try {
401             ret = initialiseSessionForReadOnly();
402             if (ret.isNOK()) {
403                 return ret;
404             }
405
406             ret = sessionApexModel.getModelKey();
407             return ret;
408         } catch (final Exception e) {
409             LOGGER.catching(e);
410             throw e;
411         } finally {
412             LOGGER.exit((ret == null ? false : ret.isOK()));
413             LOGGER.info("Model/GetKey" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
414         }
415     }
416
417     /**
418      * Retrieve the model for this session. If successful the model will be available in the first
419      * message in the result. The returned value will be similar to a {@link AxPolicyModel}, with
420      * merged {@linkplain AxKeyInfo} for the root object.
421      *
422      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
423      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
424      */
425     @GET
426     @Path("Model/Get")
427     public ApexAPIResult listModel() {
428         ApexAPIResult ret = null;
429         LOGGER.entry();
430         try {
431             ret = initialiseSessionForReadOnly();
432             if (ret.isNOK()) {
433                 return ret;
434             }
435
436             ret = sessionApexModel.listModel();
437             if (ret.isNOK()) {
438                 return ret;
439             }
440
441             ret = addKeyInfo2Messages(ret);
442             return ret;
443         } catch (final Exception e) {
444             LOGGER.catching(e);
445             throw e;
446         } finally {
447             LOGGER.exit((ret == null ? false : ret.isOK()));
448             LOGGER.info("Model/Get" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
449         }
450     }
451
452     /**
453      * Download the model for this session as a String.
454      *
455      * @return the model represented as a JSON string. See {@linkplain AxPolicyModel}
456      */
457     @GET
458     @Path("Model/Download")
459     public String downloadModel() {
460         ApexAPIResult ret = null;
461         LOGGER.entry();
462         try {
463
464             ret = initialiseSessionForReadOnly();
465             if (ret.isNOK()) {
466                 throw new IllegalStateException("Cannot download file: " + ret.getMessage());
467             }
468
469             ret = sessionApexModel.listModel();
470             if (ret.isNOK()) {
471                 throw new IllegalStateException("Cannot download file: " + ret.getMessage());
472             }
473
474             return ret.getMessage();
475         } catch (final Exception e) {
476             LOGGER.catching(e);
477             throw e;
478         } finally {
479             if (ret != null) {
480                 LOGGER.exit(ret.isOK());
481             }
482             LOGGER.info("Model/Download" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
483         }
484     }
485
486     /**
487      * Delete the model for this session.
488      *
489      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
490      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
491      */
492     @DELETE
493     @Path("Model/Delete")
494     public ApexAPIResult deleteModel() {
495         ApexAPIResult ret = null;
496         LOGGER.entry();
497         try {
498             ret = initialiseSessionForChanges();
499             if (ret.isNOK()) {
500                 return ret;
501             }
502
503             ret = sessionApexModel.deleteModel();
504             if (ret.isOK()) {
505                 commitChanges();
506             }
507             return ret;
508         } catch (final Exception e) {
509             LOGGER.catching(e);
510             throw e;
511         } finally {
512             LOGGER.exit((ret == null ? false : ret.isOK()));
513             LOGGER.info("Model/Delete" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
514         }
515     }
516
517     /**
518      * List key information with the given key names/versions. If successful the result(s) will be
519      * available in the result messages. See {@linkplain AxKeyInfo}
520      *
521      * @param name the name to search for. If null or empty, then all names will be queried
522      * @param version the version to search for. If null then all versions will be searched for.
523      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
524      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
525      */
526     @GET
527     @Path("KeyInformation/Get")
528     public ApexAPIResult listKeyInformation(@QueryParam("name") final String name,
529             @QueryParam("version") final String version) {
530         ApexAPIResult ret = null;
531         String name1 = name;
532         String version1 = version;
533         LOGGER.entry(name1, version1);
534         try {
535             ret = initialiseSessionForReadOnly();
536             if (ret.isNOK()) {
537                 return ret;
538             }
539
540             if (name1 == null || name1.equals("")) {
541                 name1 = null;
542             }
543             if (version1 == null || version1.equals("")) {
544                 version1 = null;
545             }
546
547             ret = sessionApexModel.listKeyInformation(name1, version1);
548             return ret;
549         } catch (final Exception e) {
550             LOGGER.catching(e);
551             throw e;
552         } finally {
553             LOGGER.exit((ret == null ? false : ret.isOK()));
554             LOGGER.info("KeyInformation/Get" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
555         }
556     }
557
558     /**
559      * Creates a context schema with the information in the JSON string passed.
560      *
561      * @param jsonString the JSON string to be parsed. See {@linkplain BeanContextSchema}
562      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
563      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
564      */
565     @POST
566     @Path("ContextSchema/Create")
567     public ApexAPIResult createContextSchema(final String jsonString) {
568         ApexAPIResult ret = null;
569         LOGGER.entry(jsonString);
570         try {
571             ret = initialiseSessionForChanges();
572             if (ret.isNOK()) {
573                 return ret;
574             }
575
576             final BeanContextSchema jsonbean = RestUtils.getJSONParameters(jsonString, BeanContextSchema.class);
577             ret = sessionApexModel.createContextSchema(jsonbean.getName(), jsonbean.getVersion(),
578                     jsonbean.getSchemaFlavour(), jsonbean.getSchemaDefinition(), jsonbean.getUuid(),
579                     jsonbean.getDescription());
580             if (ret.isOK()) {
581                 commitChanges();
582             }
583             return ret;
584         } catch (final Exception e) {
585             LOGGER.catching(e);
586             throw e;
587         } finally {
588             LOGGER.exit((ret == null ? false : ret.isOK()));
589             LOGGER.info("ContextSchema/Create" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
590         }
591     }
592
593     /**
594      * Update a context schema with the information in the JSON string passed.
595      *
596      * @param jsonString the JSON string to be parsed. See {@linkplain BeanContextSchema}
597      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
598      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
599      */
600     @PUT
601     @Path("ContextSchema/Update")
602     public ApexAPIResult updateContextSchema(final String jsonString) {
603         ApexAPIResult ret = null;
604         LOGGER.entry(jsonString);
605         try {
606             ret = initialiseSessionForChanges();
607             if (ret.isNOK()) {
608                 return ret;
609             }
610
611             final BeanContextSchema jsonbean = RestUtils.getJSONParameters(jsonString, BeanContextSchema.class);
612
613             ret = sessionApexModel.updateContextSchema(jsonbean.getName(), jsonbean.getVersion(),
614                     jsonbean.getSchemaFlavour(), jsonbean.getSchemaDefinition(), jsonbean.getUuid(),
615                     jsonbean.getDescription());
616             if (ret.isOK()) {
617                 commitChanges();
618             }
619             return ret;
620         } catch (final Exception e) {
621             LOGGER.catching(e);
622             throw e;
623         } finally {
624             LOGGER.exit((ret == null ? false : ret.isOK()));
625             LOGGER.info("ContextSchema/Update" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
626         }
627     }
628
629     /**
630      * List context schemas with the given key names/versions. If successful the result(s) will be
631      * available in the result messages. The returned value(s) will be similar to
632      * {@link AxContextSchema}, with merged {@linkplain AxKeyInfo} for the root object.
633      *
634      * @param name the name to search for. If null or empty, then all names will be queried
635      * @param version the version to search for. If null then all versions will be searched for.
636      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
637      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
638      */
639     @GET
640     @Path("ContextSchema/Get")
641     public ApexAPIResult listContextSchemas(@QueryParam("name") final String name,
642             @QueryParam("version") final String version) {
643         ApexAPIResult ret = null;
644         String name1 = name;
645         String version1 = version;
646         LOGGER.entry(name1, version1);
647         try {
648             ret = initialiseSessionForReadOnly();
649             if (ret.isNOK()) {
650                 return ret;
651             }
652
653             if (name1 == null || name1.equals("")) {
654                 name1 = null;
655             }
656             if (version1 == null || version1.equals("")) {
657                 version1 = null;
658             }
659
660             ret = sessionApexModel.listContextSchemas(name1, version1);
661             if (ret.isNOK()) {
662                 return ret;
663             }
664
665             ret = addKeyInfo2Messages(ret);
666             return ret;
667         } catch (final Exception e) {
668             LOGGER.catching(e);
669             throw e;
670         } finally {
671             LOGGER.exit((ret == null ? false : ret.isOK()));
672             LOGGER.info("ContextSchema/Get" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
673         }
674     }
675
676     /**
677      * Delete context schemas with the given key names/versions.
678      *
679      * @param name the name to search for. If null or empty, then all names will be queried
680      * @param version the version to search for. If null then all versions will be searched for.
681      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
682      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
683      */
684     @DELETE
685     @Path("ContextSchema/Delete")
686     public ApexAPIResult deleteContextSchema(@QueryParam("name") final String name,
687             @QueryParam("version") final String version) {
688         ApexAPIResult ret = null;
689         String name1 = name;
690         String version1 = version;
691         LOGGER.entry(name1, version1);
692         try {
693             ret = initialiseSessionForChanges();
694             if (ret.isNOK()) {
695                 return ret;
696             }
697
698             if (name1 == null || name1.equals("")) {
699                 name1 = null;
700             }
701             if (version1 == null || version1.equals("")) {
702                 version1 = null;
703             }
704
705             ret = sessionApexModel.deleteContextSchema(name1, version1);
706             if (ret.isOK()) {
707                 commitChanges();
708             }
709             return ret;
710         } catch (final Exception e) {
711             LOGGER.catching(e);
712             throw e;
713         } finally {
714             LOGGER.exit((ret == null ? false : ret.isOK()));
715             LOGGER.info("ContextSchema/Delete" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
716         }
717     }
718
719     /**
720      * Validate context schemas with the given key names/versions. The result(s) will be available
721      * in the result messages.
722      *
723      * @param name the name to search for. If null or empty, then all names will be queried
724      * @param version the version to search for. If null then all versions will be searched for.
725      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
726      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
727      */
728     @GET
729     @Path("Validate/ContextSchema")
730     public ApexAPIResult validateContextSchemas(@QueryParam("name") final String name,
731             @QueryParam("version") final String version) {
732         ApexAPIResult ret = null;
733         String name1 = name;
734         String version1 = version;
735         LOGGER.entry(name1, version1);
736         try {
737             if (name1 == null || name1.equals("")) {
738                 name1 = null;
739             }
740             if (version1 == null || version1.equals("")) {
741                 version1 = null;
742             }
743
744             ret = initialiseSessionForReadOnly();
745             if (ret.isNOK()) {
746                 return ret;
747             }
748
749             ret = sessionApexModel.validateContextSchemas(name1, version1);
750             if (ret.isNOK()) {
751                 return ret;
752             }
753
754             ret = addKeyInfo2Messages(ret);
755             return ret;
756         } catch (final Exception e) {
757             LOGGER.catching(e);
758             throw e;
759         } finally {
760             LOGGER.exit((ret == null ? false : ret.isOK()));
761             LOGGER.info("Validate/ContextSchema" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
762         }
763     }
764
765     /**
766      * Creates a context album with the information in the JSON string passed.
767      *
768      * @param jsonString the JSON string to be parsed. See {@linkplain BeanContextAlbum}
769      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
770      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
771      */
772     @POST
773     @Path("ContextAlbum/Create")
774     public ApexAPIResult createContextAlbum(final String jsonString) {
775         ApexAPIResult ret = null;
776         LOGGER.entry(jsonString);
777         try {
778             ret = initialiseSessionForChanges();
779             if (ret.isNOK()) {
780                 return ret;
781             }
782
783             final BeanContextAlbum jsonbean = RestUtils.getJSONParameters(jsonString, BeanContextAlbum.class);
784
785             ret = sessionApexModel.createContextAlbum(jsonbean.getName(), jsonbean.getVersion(), jsonbean.getScope(),
786                     Boolean.toString(jsonbean.getWriteable()), jsonbean.getItemSchema().getName(),
787                     jsonbean.getItemSchema().getVersion(), jsonbean.getUuid(), jsonbean.getDescription());
788             if (ret.isOK()) {
789                 commitChanges();
790             }
791             return ret;
792         } catch (final Exception e) {
793             LOGGER.catching(e);
794             throw e;
795         } finally {
796             LOGGER.exit((ret == null ? false : ret.isOK()));
797             LOGGER.info("ContextAlbum/Create" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
798         }
799     }
800
801     /**
802      * Update a context album with the information in the JSON string passed.
803      *
804      * @param jsonString the JSON string to be parsed. See {@linkplain BeanContextAlbum}
805      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
806      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
807      */
808     @PUT
809     @Path("ContextAlbum/Update")
810     public ApexAPIResult updateContextAlbum(final String jsonString) {
811         ApexAPIResult ret = null;
812         LOGGER.entry(jsonString);
813         try {
814             ret = initialiseSessionForChanges();
815             if (ret.isNOK()) {
816                 return ret;
817             }
818
819             final BeanContextAlbum jsonbean = RestUtils.getJSONParameters(jsonString, BeanContextAlbum.class);
820
821             ret = sessionApexModel.updateContextAlbum(jsonbean.getName(), jsonbean.getVersion(), jsonbean.getScope(),
822                     Boolean.toString(jsonbean.getWriteable()), jsonbean.getItemSchema().getName(),
823                     jsonbean.getItemSchema().getVersion(), jsonbean.getUuid(), jsonbean.getDescription());
824             if (ret.isOK()) {
825                 commitChanges();
826             }
827             return ret;
828         } catch (final Exception e) {
829             LOGGER.catching(e);
830             throw e;
831         } finally {
832             LOGGER.exit((ret == null ? false : ret.isOK()));
833             LOGGER.info("ContextAlbum/Update" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
834         }
835     }
836
837     /**
838      * List context albums with the given key names/versions. If successful the result(s) will be
839      * available in the result messages. The returned value(s) will be similar to
840      * {@link AxContextAlbum}, with merged {@linkplain AxKeyInfo} for the root object.
841      *
842      * @param name the name to search for. If null or empty, then all names will be queried
843      * @param version the version to search for. If null then all versions will be searched for.
844      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
845      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
846      */
847     @GET
848     @Path("ContextAlbum/Get")
849     public ApexAPIResult listContextAlbums(@QueryParam("name") final String name,
850             @QueryParam("version") final String version) {
851         ApexAPIResult ret = null;
852         String name1 = name;
853         String version1 = version;
854         LOGGER.entry(name1, version1);
855         try {
856             ret = initialiseSessionForReadOnly();
857             if (ret.isNOK()) {
858                 return ret;
859             }
860
861             if (name1 == null || name1.equals("")) {
862                 name1 = null;
863             }
864             if (version1 == null || version1.equals("")) {
865                 version1 = null;
866             }
867
868             ret = sessionApexModel.listContextAlbum(name1, version1);
869             if (ret.isNOK()) {
870                 return ret;
871             }
872
873             ret = addKeyInfo2Messages(ret);
874             return ret;
875         } catch (final Exception e) {
876             LOGGER.catching(e);
877             throw e;
878         } finally {
879             LOGGER.exit((ret == null ? false : ret.isOK()));
880             LOGGER.info("ContextAlbum/Get" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
881         }
882     }
883
884     /**
885      * Delete context albums with the given key names/versions.
886      *
887      * @param name the name to search for. If null or empty, then all names will be queried
888      * @param version the version to search for. If null then all versions will be searched for.
889      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
890      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
891      */
892     @DELETE
893     @Path("ContextAlbum/Delete")
894     public ApexAPIResult deleteContextAlbum(@QueryParam("name") final String name,
895             @QueryParam("version") final String version) {
896         ApexAPIResult ret = null;
897         String name1 = name;
898         String version1 = version;
899         LOGGER.entry(name1, version1);
900         try {
901             ret = initialiseSessionForChanges();
902             if (ret.isNOK()) {
903                 return ret;
904             }
905
906             if (name1 == null || name1.equals("")) {
907                 name1 = null;
908             }
909             if (version1 == null || version1.equals("")) {
910                 version1 = null;
911             }
912
913             ret = sessionApexModel.deleteContextAlbum(name1, version1);
914             if (ret.isOK()) {
915                 commitChanges();
916             }
917             return ret;
918         } catch (final Exception e) {
919             LOGGER.catching(e);
920             throw e;
921         } finally {
922             LOGGER.exit((ret == null ? false : ret.isOK()));
923             LOGGER.info("ContextAlbum/Delete" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
924         }
925     }
926
927     /**
928      * Validate context albums with the given key names/versions. The result(s) will be available in
929      * the result messages.
930      *
931      * @param name the name to search for. If null or empty, then all names will be queried
932      * @param version the version to search for. If null then all versions will be searched for.
933      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
934      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
935      */
936     @GET
937     @Path("Validate/ContextAlbum")
938     public ApexAPIResult validateContextAlbums(@QueryParam("name") final String name,
939             @QueryParam("version") final String version) {
940         ApexAPIResult ret = null;
941         String name1 = name;
942         String version1 = version;
943         LOGGER.entry(name1, version1);
944         try {
945             if (name1 == null || name1.equals("")) {
946                 name1 = null;
947             }
948             if (version1 == null || version1.equals("")) {
949                 version1 = null;
950             }
951
952             ret = initialiseSessionForReadOnly();
953             if (ret.isNOK()) {
954                 return ret;
955             }
956
957             ret = sessionApexModel.listContextAlbum(name1, version1);
958             if (ret.isNOK()) {
959                 return ret;
960             }
961
962             ret = addKeyInfo2Messages(ret);
963             return ret;
964         } catch (final Exception e) {
965             LOGGER.catching(e);
966             throw e;
967         } finally {
968             LOGGER.exit((ret == null ? false : ret.isOK()));
969             LOGGER.info("Validate/ContextAlbum" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
970         }
971     }
972
973     /**
974      * Creates an event with the information in the JSON string passed.
975      *
976      * @param jsonString the JSON string to be parsed. See {@linkplain BeanEvent}
977      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
978      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
979      */
980     @POST
981     @Path("Event/Create")
982     public ApexAPIResult createEvent(final String jsonString) {
983         ApexAPIResult ret = null;
984         LOGGER.entry(jsonString);
985         try {
986             ret = initialiseSessionForChanges();
987             if (ret.isNOK()) {
988                 return ret;
989             }
990
991             final BeanEvent jsonbean = RestUtils.getJSONParameters(jsonString, BeanEvent.class);
992
993             ret = sessionApexModel.createEvent(jsonbean.getName(), jsonbean.getVersion(), jsonbean.getNameSpace(),
994                     jsonbean.getSource(), jsonbean.getTarget(), jsonbean.getUuid(), jsonbean.getDescription());
995             if (ret.isNOK()) {
996                 return ret;
997             }
998             if (jsonbean.getParameters() != null) {
999                 for (final Entry<String, BeanField> p : jsonbean.getParameters().entrySet()) {
1000                     if (p.getValue() == null) {
1001                         ret = new ApexAPIResult(RESULT.FAILED, "Null event parameter information for parameter \""
1002                                 + p.getKey() + "\" in event " + jsonbean.getName() + ":" + jsonbean.getVersion()
1003                                 + ". The event was created, but there was an error adding the event parameters."
1004                                 + " The event has only been partially defined.");
1005                         return ret;
1006                     }
1007                     final ApexAPIResult rettmp =
1008                             sessionApexModel.createEventPar(jsonbean.getName(), jsonbean.getVersion(), p.getKey(),
1009                                     p.getValue().getName(), p.getValue().getVersion(), p.getValue().getOptional());
1010                     if (rettmp.isNOK()) {
1011                         rettmp.addMessage("Failed to add event parameter information for parameter \"" + p.getKey()
1012                                 + "\" in event " + jsonbean.getName() + ":" + jsonbean.getVersion()
1013                                 + ". The event was created, but there was an error adding the event parameters."
1014                                 + " The event has only been partially defined.");
1015                         ret = rettmp;
1016                         return ret;
1017                     }
1018                 }
1019             }
1020             if (ret.isOK()) {
1021                 commitChanges();
1022             }
1023             return ret;
1024         } catch (final Exception e) {
1025             LOGGER.catching(e);
1026             throw e;
1027         } finally {
1028             LOGGER.exit((ret == null ? false : ret.isOK()));
1029             LOGGER.info("Event/Create" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
1030         }
1031     }
1032
1033     /**
1034      * Update an event with the information in the JSON string passed.
1035      *
1036      * @param jsonString the JSON string to be parsed. See {@linkplain BeanEvent}
1037      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
1038      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
1039      */
1040     @PUT
1041     @Path("Event/Update")
1042     public ApexAPIResult updateEvent(final String jsonString) {
1043         ApexAPIResult ret = null;
1044         LOGGER.entry(jsonString);
1045         try {
1046             ret = initialiseSessionForChanges();
1047             if (ret.isNOK()) {
1048                 return ret;
1049             }
1050
1051             final BeanEvent jsonbean = RestUtils.getJSONParameters(jsonString, BeanEvent.class);
1052
1053             if (jsonbean.getName() == null || jsonbean.getName().equals("") || jsonbean.getVersion() == null
1054                     || jsonbean.getVersion().equals("")) {
1055                 ret = new ApexAPIResult(RESULT.FAILED, "Null/Empty event name/version (\"" + jsonbean.getName() + ":"
1056                         + jsonbean.getVersion() + "\" passed to UpdateEvent");
1057                 return ret;
1058             }
1059
1060             ret = sessionApexModel.deleteEvent(jsonbean.getName(), jsonbean.getVersion());
1061             if (ret.isNOK()) {
1062                 return ret;
1063             }
1064
1065             ret = createEvent(jsonString);
1066             if (ret.isOK()) {
1067                 commitChanges();
1068             }
1069             return ret;
1070         } catch (final Exception e) {
1071             LOGGER.catching(e);
1072             throw e;
1073         } finally {
1074             LOGGER.exit((ret == null ? false : ret.isOK()));
1075             LOGGER.info("Event/Update" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
1076         }
1077     }
1078
1079     /**
1080      * List events with the given key names/versions. If successful the result(s) will be available
1081      * in the result messages. The returned value(s) will be similar to {@link AxEvent}, with merged
1082      * {@linkplain AxKeyInfo} for the root object.
1083      *
1084      * @param name the name to search for. If null or empty, then all names will be queried
1085      * @param version the version to search for. If null then all versions will be searched for.
1086      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
1087      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
1088      */
1089     @GET
1090     @Path("Event/Get")
1091     public ApexAPIResult listEvent(@QueryParam("name") final String name, @QueryParam("version") final String version) {
1092         ApexAPIResult ret = null;
1093         String name1 = name;
1094         String version1 = version;
1095         LOGGER.entry(name1, version1);
1096         try {
1097             ret = initialiseSessionForReadOnly();
1098             if (ret.isNOK()) {
1099                 return ret;
1100             }
1101
1102             if (name1 == null || name1.equals("")) {
1103                 name1 = null;
1104             }
1105             if (version1 == null || version1.equals("")) {
1106                 version1 = null;
1107             }
1108
1109             ret = sessionApexModel.listEvent(name1, version1);
1110             if (ret.isNOK()) {
1111                 return ret;
1112             }
1113
1114             ret = addKeyInfo2Messages(ret);
1115             return ret;
1116         } catch (final Exception e) {
1117             LOGGER.catching(e);
1118             throw e;
1119         } finally {
1120             LOGGER.exit((ret == null ? false : ret.isOK()));
1121             LOGGER.info("Event/Get" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
1122         }
1123     }
1124
1125     /**
1126      * Delete events with the given key names/versions.
1127      *
1128      * @param name the name to search for. If null or empty, then all names will be queried
1129      * @param version the version to search for. If null then all versions will be searched for.
1130      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
1131      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
1132      */
1133     @DELETE
1134     @Path("Event/Delete")
1135     public ApexAPIResult deleteEvent(@QueryParam("name") final String name,
1136             @QueryParam("version") final String version) {
1137         ApexAPIResult ret = null;
1138         String name1 = name;
1139         String version1 = version;
1140         LOGGER.entry(name1, version1);
1141         try {
1142             if (name1 == null || name1.equals("")) {
1143                 name1 = null;
1144             }
1145             if (version1 == null || version1.equals("")) {
1146                 version1 = null;
1147             }
1148
1149             ret = initialiseSessionForChanges();
1150             if (ret.isNOK()) {
1151                 return ret;
1152             }
1153
1154             ret = sessionApexModel.deleteEvent(name1, version1);
1155             if (ret.isOK()) {
1156                 commitChanges();
1157             }
1158             return ret;
1159         } catch (final Exception e) {
1160             LOGGER.catching(e);
1161             throw e;
1162         } finally {
1163             LOGGER.exit((ret == null ? false : ret.isOK()));
1164             LOGGER.info("Event/Delete" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
1165         }
1166     }
1167
1168     /**
1169      * Validate events with the given key names/versions. The result(s) will be available in the
1170      * result messages.
1171      *
1172      * @param name the name to search for. If null or empty, then all names will be queried
1173      * @param version the version to search for. If null then all versions will be searched for.
1174      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
1175      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
1176      */
1177     @GET
1178     @Path("Validate/Event")
1179     public ApexAPIResult validateEvent(@QueryParam("name") final String name,
1180             @QueryParam("version") final String version) {
1181         ApexAPIResult ret = null;
1182         String name1 = name;
1183         String version1 = version;
1184         LOGGER.entry(name1, version1);
1185         try {
1186             ret = initialiseSessionForReadOnly();
1187             if (ret.isNOK()) {
1188                 return ret;
1189             }
1190
1191             if (name1 == null || name1.equals("")) {
1192                 name1 = null;
1193             }
1194             if (version1 == null || version1.equals("")) {
1195                 version1 = null;
1196             }
1197
1198             ret = sessionApexModel.listEvent(name1, version1);
1199             if (ret.isNOK()) {
1200                 return ret;
1201             }
1202
1203             ret = addKeyInfo2Messages(ret);
1204             return ret;
1205         } catch (final Exception e) {
1206             LOGGER.catching(e);
1207             throw e;
1208         } finally {
1209             LOGGER.exit((ret == null ? false : ret.isOK()));
1210             LOGGER.info("Validate/Event" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
1211         }
1212     }
1213
1214     /**
1215      * Creates a task with the information in the JSON string passed.
1216      *
1217      * @param jsonString the JSON string to be parsed. See {@linkplain BeanTask}
1218      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
1219      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
1220      */
1221     @POST
1222     @Path("Task/Create")
1223     public ApexAPIResult createTask(final String jsonString) {
1224         ApexAPIResult ret = null;
1225         ApexAPIResult tempres = null;
1226         LOGGER.entry(jsonString);
1227         try {
1228             ret = initialiseSessionForChanges();
1229             if (ret.isNOK()) {
1230                 return ret;
1231             }
1232
1233             final BeanTask jsonbean = RestUtils.getJSONParameters(jsonString, BeanTask.class);
1234
1235             ret = sessionApexModel.createTask(jsonbean.getName(), jsonbean.getVersion(), jsonbean.getUuid(),
1236                     jsonbean.getDescription());
1237             if (ret.isNOK()) {
1238                 return ret;
1239             }
1240             if (jsonbean.getInputFields() != null) {
1241                 for (final Entry<String, BeanField> fin : jsonbean.getInputFields().entrySet()) {
1242                     if (fin.getValue() == null) {
1243                         ret = new ApexAPIResult(RESULT.FAILED, "Null task input field information for field \""
1244                                 + fin.getKey() + "\" in task " + jsonbean.getName() + ":" + jsonbean.getVersion()
1245                                 + ". The task was created, but there was an error adding the input fields."
1246                                 + " The task has only been partially defined.");
1247                         return ret;
1248                     }
1249                     if (fin.getKey() == null || !fin.getKey().equals(fin.getValue().getLocalName())) {
1250                         ret = new ApexAPIResult(RESULT.FAILED, "Invalid task input field information for field \""
1251                                 + fin.getKey() + "\" in task " + jsonbean.getName() + ":" + jsonbean.getVersion()
1252                                 + ". The localName of the field (\"" + fin.getValue().getLocalName()
1253                                 + "\") is not the same as the field name. "
1254                                 + "The task was created, but there was an error adding the input fields."
1255                                 + " The task has only been partially defined.");
1256                         return ret;
1257                     }
1258                     tempres = sessionApexModel.createTaskInputField(jsonbean.getName(), jsonbean.getVersion(),
1259                             fin.getKey(), fin.getValue().getName(), fin.getValue().getVersion(),
1260                             fin.getValue().getOptional());
1261                     if (tempres.isNOK()) {
1262                         tempres.addMessage("Failed to add task input field information for field \"" + fin.getKey()
1263                                 + "\" in task " + jsonbean.getName() + ":" + jsonbean.getVersion()
1264                                 + ". The task was created, but there was an error adding the input fields."
1265                                 + " The task has only been partially defined.");
1266                         ret = tempres;
1267                         return ret;
1268                     }
1269                 }
1270             }
1271             if (jsonbean.getOutputFields() != null) {
1272                 for (final Entry<String, BeanField> fout : jsonbean.getOutputFields().entrySet()) {
1273                     if (fout.getValue() == null) {
1274                         ret = new ApexAPIResult(RESULT.FAILED, "Null task output field information for field \""
1275                                 + fout.getKey() + "\" in task " + jsonbean.getName() + ":" + jsonbean.getVersion()
1276                                 + ". The task was created, but there was an error adding the output fields."
1277                                 + " The task has only been partially defined.");
1278                         return ret;
1279                     }
1280                     if (fout.getKey() == null || !fout.getKey().equals(fout.getValue().getLocalName())) {
1281                         ret = new ApexAPIResult(RESULT.FAILED, "Invalid task output field information for field \""
1282                                 + fout.getKey() + "\" in task " + jsonbean.getName() + ":" + jsonbean.getVersion()
1283                                 + ". The localName of the field (\"" + fout.getValue().getLocalName()
1284                                 + "\") is not the same as the field name. "
1285                                 + "The task was created, but there was an error adding the output fields."
1286                                 + " The task has only been partially defined.");
1287                         return ret;
1288                     }
1289                     tempres = sessionApexModel.createTaskOutputField(jsonbean.getName(), jsonbean.getVersion(),
1290                             fout.getKey(), fout.getValue().getName(), fout.getValue().getVersion(),
1291                             fout.getValue().getOptional());
1292                     if (tempres.isNOK()) {
1293                         tempres.addMessage("Failed to add task output field information for field \"" + fout.getKey()
1294                                 + "\" in task " + jsonbean.getName() + ":" + jsonbean.getVersion()
1295                                 + ". The task was created, but there was an error adding the output fields."
1296                                 + " The task has only been partially defined.");
1297                         ret = tempres;
1298                         return ret;
1299                     }
1300                 }
1301             }
1302             if (jsonbean.getTaskLogic() != null) {
1303                 final BeanLogic logic = jsonbean.getTaskLogic();
1304                 tempres = sessionApexModel.createTaskLogic(jsonbean.getName(), jsonbean.getVersion(),
1305                         logic.getLogicFlavour(), logic.getLogic());
1306                 if (tempres.isNOK()) {
1307                     tempres.addMessage("Failed to add task logic in task " + jsonbean.getName() + ":"
1308                             + jsonbean.getVersion()
1309                             + ". The task was created, but there was an error adding the logic."
1310                             + " The task has only been partially defined.");
1311                     ret = tempres;
1312                     return ret;
1313                 }
1314             }
1315             if (jsonbean.getParameters() != null) {
1316                 for (final Entry<String, BeanTaskParameter> param : jsonbean.getParameters().entrySet()) {
1317                     if (param.getKey() == null || param.getValue() == null
1318                             || !param.getKey().equals(param.getValue().getParameterName())) {
1319                         ret = new ApexAPIResult(RESULT.FAILED,
1320                                 "Null or invalid task parameter information for parameter \"" + param.getKey()
1321                                         + "\" in task " + jsonbean.getName() + ":" + jsonbean.getVersion()
1322                                         + ". The task was created, but there was an error adding the parameters."
1323                                         + " The task has only been partially defined.");
1324                         return ret;
1325                     }
1326                     tempres = sessionApexModel.createTaskParameter(jsonbean.getName(), jsonbean.getVersion(),
1327                             param.getValue().getParameterName(), param.getValue().getDefaultValue());
1328                     if (tempres.isNOK()) {
1329                         tempres.addMessage("Failed to add task parameter \"" + param.getKey() + "\" in task "
1330                                 + jsonbean.getName() + ":" + jsonbean.getVersion()
1331                                 + ". The task was created, but there was an error adding the parameters."
1332                                 + " The task has only been partially defined.");
1333                         ret = tempres;
1334                         return ret;
1335                     }
1336                 }
1337             }
1338             if (jsonbean.getContexts() != null) {
1339                 for (final BeanKeyRef contextalbum : jsonbean.getContexts()) {
1340                     if (contextalbum.getName() == null || contextalbum.getVersion() == null) {
1341                         ret = new ApexAPIResult(RESULT.FAILED,
1342                                 "Null or invalid context album reference information in task " + jsonbean.getName()
1343                                         + ":" + jsonbean.getVersion()
1344                                         + ". The task was created, but there was an error adding the"
1345                                         + " context album reference. The task has only been partially defined.");
1346                         return ret;
1347                     }
1348                     tempres = sessionApexModel.createTaskContextRef(jsonbean.getName(), jsonbean.getVersion(),
1349                             contextalbum.getName(), contextalbum.getVersion());
1350                     if (tempres.isNOK()) {
1351                         ret = new ApexAPIResult(RESULT.FAILED,
1352                                 "Failed to add context album reference information in task " + jsonbean.getName() + ":"
1353                                         + jsonbean.getVersion()
1354                                         + ". The task was created, but there was an error adding the"
1355                                         + " context album reference. The task has only been partially defined.");
1356                         return ret;
1357                     }
1358                 }
1359             }
1360             if (ret.isOK()) {
1361                 commitChanges();
1362             }
1363             return ret;
1364         } catch (final Exception e) {
1365             LOGGER.catching(e);
1366             throw e;
1367         } finally {
1368             LOGGER.exit((ret == null ? false : ret.isOK()));
1369             LOGGER.info("Task/Create" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
1370         }
1371     }
1372
1373     /**
1374      * Update a task with the information in the JSON string passed.
1375      *
1376      * @param jsonString the JSON string to be parsed. See {@linkplain BeanTask}
1377      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
1378      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
1379      */
1380     @PUT
1381     @Path("Task/Update")
1382     public ApexAPIResult updateTask(final String jsonString) {
1383         ApexAPIResult ret = null;
1384         LOGGER.entry(jsonString);
1385         try {
1386             ret = initialiseSessionForChanges();
1387             if (ret.isNOK()) {
1388                 return ret;
1389             }
1390
1391             final BeanTask jsonbean = RestUtils.getJSONParameters(jsonString, BeanTask.class);
1392
1393             if (jsonbean.getName() == null || jsonbean.getName().equals("") || jsonbean.getVersion() == null
1394                     || jsonbean.getVersion().equals("")) {
1395                 ret = new ApexAPIResult(RESULT.FAILED, "Null/Empty task name/version (\"" + jsonbean.getName() + ":"
1396                         + jsonbean.getVersion() + "\" passed to UpdateTask");
1397                 return ret;
1398             }
1399
1400             ret = sessionApexModel.deleteTask(jsonbean.getName(), jsonbean.getVersion());
1401             if (ret.isNOK()) {
1402                 return ret;
1403             }
1404
1405             ret = createTask(jsonString);
1406             if (ret.isOK()) {
1407                 commitChanges();
1408             }
1409             return ret;
1410         } catch (final Exception e) {
1411             LOGGER.catching(e);
1412             throw e;
1413         } finally {
1414             LOGGER.exit((ret == null ? false : ret.isOK()));
1415             LOGGER.info("Task/Update" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
1416         }
1417     }
1418
1419     /**
1420      * List tasks with the given key names/versions. If successful the result(s) will be available
1421      * in the result messages. The returned value(s) will be similar to {@link AxTask}, with merged
1422      * {@linkplain AxKeyInfo} for the root object.
1423      *
1424      * @param name the name to search for. If null or empty, then all names will be queried
1425      * @param version the version to search for. If null then all versions will be searched for.
1426      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
1427      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
1428      */
1429     @GET
1430     @Path("Task/Get")
1431     public ApexAPIResult listTask(@QueryParam("name") final String name, @QueryParam("version") final String version) {
1432         ApexAPIResult ret = null;
1433         String name1 = name;
1434         String version1 = version;
1435         LOGGER.entry(name1, version1);
1436         try {
1437             ret = initialiseSessionForReadOnly();
1438             if (ret.isNOK()) {
1439                 return ret;
1440             }
1441
1442             if (name1 == null || name1.equals("")) {
1443                 name1 = null;
1444             }
1445             if (version1 == null || version1.equals("")) {
1446                 version1 = null;
1447             }
1448
1449             ret = sessionApexModel.listTask(name1, version1);
1450             if (ret.isNOK()) {
1451                 return ret;
1452             }
1453
1454             ret = addKeyInfo2Messages(ret);
1455             return ret;
1456         } catch (final Exception e) {
1457             LOGGER.catching(e);
1458             throw e;
1459         } finally {
1460             LOGGER.exit((ret == null ? false : ret.isOK()));
1461             LOGGER.info("Task/Get" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
1462         }
1463     }
1464
1465     /**
1466      * Delete tasks with the given key names/versions.
1467      *
1468      * @param name the name to search for. If null or empty, then all names will be queried
1469      * @param version the version to search for. If null then all versions will be searched for.
1470      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
1471      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
1472      */
1473     @DELETE
1474     @Path("Task/Delete")
1475     public ApexAPIResult deleteTask(@QueryParam("name") final String name,
1476             @QueryParam("version") final String version) {
1477         ApexAPIResult ret = null;
1478         String name1 = name;
1479         String version1 = version;
1480         LOGGER.entry(name1, version1);
1481         try {
1482             ret = initialiseSessionForChanges();
1483             if (ret.isNOK()) {
1484                 return ret;
1485             }
1486
1487             if (name1 == null || name1.equals("")) {
1488                 name1 = null;
1489             }
1490             if (version1 == null || version1.equals("")) {
1491                 version1 = null;
1492             }
1493
1494             // all input/output fields, parameters, logic, context references is "owned"/contained
1495             // in the task, so
1496             // deleting the task removes all of these
1497             ret = sessionApexModel.deleteTask(name1, version1);
1498             if (ret.isOK()) {
1499                 commitChanges();
1500             }
1501             return ret;
1502         } catch (final Exception e) {
1503             LOGGER.catching(e);
1504             throw e;
1505         } finally {
1506             LOGGER.exit((ret == null ? false : ret.isOK()));
1507             LOGGER.info("Task/Delete" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
1508         }
1509     }
1510
1511     /**
1512      * Validate tasks with the given key names/versions. The result(s) will be available in the
1513      * result messages.
1514      *
1515      * @param name the name to search for. If null or empty, then all names will be queried
1516      * @param version the version to search for. If null then all versions will be searched for.
1517      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
1518      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
1519      */
1520     @GET
1521     @Path("Validate/Task")
1522     public ApexAPIResult validateTask(@QueryParam("name") final String name,
1523             @QueryParam("version") final String version) {
1524         ApexAPIResult ret = null;
1525         String name1 = name;
1526         String version1 = version;
1527         LOGGER.entry(name1, version1);
1528         try {
1529             ret = initialiseSessionForReadOnly();
1530             if (ret.isNOK()) {
1531                 return ret;
1532             }
1533
1534             if (name1 == null || name1.equals("")) {
1535                 name1 = null;
1536             }
1537             if (version1 == null || version1.equals("")) {
1538                 version1 = null;
1539             }
1540
1541             ret = sessionApexModel.listTask(name1, version1);
1542             if (ret.isNOK()) {
1543                 return ret;
1544             }
1545
1546             ret = addKeyInfo2Messages(ret);
1547             return ret;
1548         } catch (final Exception e) {
1549             LOGGER.catching(e);
1550             throw e;
1551         } finally {
1552             LOGGER.exit((ret == null ? false : ret.isOK()));
1553             LOGGER.info("Validate/Task" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
1554         }
1555     }
1556
1557     // CHECKSTYLE:OFF: MethodLength
1558     /**
1559      * Creates a policy with the information in the JSON string passed.
1560      *
1561      * @param jsonString the JSON string to be parsed See {@linkplain BeanPolicy}
1562      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
1563      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
1564      */
1565     @POST
1566     @Path("Policy/Create")
1567     public ApexAPIResult createPolicy(final String jsonString) {
1568
1569         ApexAPIResult ret = null;
1570         ApexAPIResult tempres = null;
1571         LOGGER.entry(jsonString);
1572         try {
1573             ret = initialiseSessionForChanges();
1574             if (ret.isNOK()) {
1575                 return ret;
1576             }
1577
1578             final BeanPolicy jsonbean = RestUtils.getJSONParameters(jsonString, BeanPolicy.class);
1579             final String policyname = jsonbean.getName();
1580             final String policyversion = jsonbean.getVersion();
1581
1582             ret = sessionApexModel.createPolicy(policyname, policyversion, jsonbean.getTemplate(),
1583                     jsonbean.getFirstState(), jsonbean.getUuid(), jsonbean.getDescription());
1584             if (ret.isNOK()) {
1585                 return ret;
1586             }
1587
1588             if (jsonbean.getStates() == null || jsonbean.getStates().isEmpty()) {
1589                 ret = new ApexAPIResult(RESULT.FAILED, "Null or empty state map; no states defined for policy \""
1590                         + policyname + ":" + policyversion
1591                         + "\". The policy was created, but there was an error adding states."
1592                         + " The policy has only been partially defined.");
1593                 return ret;
1594             }
1595
1596             final Map<String, BeanState> statemap = jsonbean.getStates();
1597             // need to create all the states first, before populating them
1598             for (final Map.Entry<String, BeanState> e : statemap.entrySet()) {
1599                 final String statename = e.getKey();
1600                 final BeanState state = e.getValue();
1601                 if (state == null) {
1602                     ret = new ApexAPIResult(RESULT.FAILED, "Null or invalid state information for state \"" + statename
1603                             + "\" for policy \"" + policyname + ":" + policyversion
1604                             + "\". The policy was created, but there was an error adding the state."
1605                             + " The policy has only been partially defined.");
1606                     return ret;
1607                 }
1608                 if (state.getTrigger() == null) {
1609                     ret = new ApexAPIResult(RESULT.FAILED, "Null or invalid state trigger for state \"" + statename
1610                             + "\" for policy \"" + policyname + ":" + policyversion
1611                             + "\". The policy was created, but there was an error adding the state."
1612                             + " The policy has only been partially defined.");
1613                     return ret;
1614                 }
1615                 if (state.getDefaultTask() == null) {
1616                     ret = new ApexAPIResult(RESULT.FAILED, "Null or invalid default task for state \"" + statename
1617                             + "\" for policy \"" + policyname + ":" + policyversion
1618                             + "\". The policy was created, but there was an error adding the state."
1619                             + " The policy has only been partially defined.");
1620                     return ret;
1621                 }
1622                 tempres = sessionApexModel.createPolicyState(policyname, policyversion, statename,
1623                         state.getTrigger().getName(), state.getTrigger().getVersion(), state.getDefaultTask().getName(),
1624                         state.getDefaultTask().getVersion());
1625                 if (tempres.isNOK()) {
1626                     ret = tempres;
1627                     return ret;
1628                 }
1629             }
1630
1631             for (final Map.Entry<String, BeanState> e : statemap.entrySet()) {
1632                 final String statename = e.getKey();
1633                 final BeanState state = e.getValue();
1634
1635                 final BeanLogic tsl = state.getTaskSelectionLogic();
1636                 if (tsl != null) {
1637                     tempres = sessionApexModel.createPolicyStateTaskSelectionLogic(policyname, policyversion, statename,
1638                             tsl.getLogicFlavour(), tsl.getLogic());
1639                     if (tempres.isNOK()) {
1640                         tempres.addMessage("Failed to add task selection logic for state \"" + statename + "\" for"
1641                                 + " policy \"" + policyname + ":" + policyversion
1642                                 + "\". The policy was created, but there was an error adding the task selection logic "
1643                                 + "for the state. The policy has only been partially defined.");
1644                         ret = tempres;
1645                         return ret;
1646                     }
1647                 }
1648
1649                 final BeanKeyRef[] contexts = state.getContexts();
1650                 if (contexts != null) {
1651                     for (final BeanKeyRef c : contexts) {
1652                         if (c == null) {
1653                             ret = new ApexAPIResult(RESULT.FAILED,
1654                                     "Null or invalid context reference \"" + c + "\" for" + " state \"" + statename
1655                                             + "\" for policy \"" + policyname + ":" + policyversion
1656                                             + "\". The policy was created, but there was an error adding the context "
1657                                             + "reference for the state. The policy has only been partially defined.");
1658                             return ret;
1659                         }
1660                         tempres = sessionApexModel.createPolicyStateContextRef(policyname, policyversion, statename,
1661                                 c.getName(), c.getVersion());
1662                         if (tempres.isNOK()) {
1663                             tempres.addMessage("Failed to add context reference \"" + c + "\" for state \"" + statename
1664                                     + "\" for policy \"" + policyname + ":" + policyversion
1665                                     + "\". The policy was created, but there was an error adding the context reference "
1666                                     + "for the state. The policy has only been partially defined.");
1667                             ret = tempres;
1668                             return ret;
1669                         }
1670                     }
1671                 }
1672
1673                 final Map<String, BeanLogic> finalizers = state.getFinalizers();
1674                 if (finalizers != null) {
1675                     for (final Map.Entry<String, BeanLogic> f : finalizers.entrySet()) {
1676                         final String finalizername = f.getKey();
1677                         final BeanLogic finalizer = f.getValue();
1678                         if (finalizername == null || finalizer == null) {
1679                             ret = new ApexAPIResult(RESULT.FAILED,
1680                                     "Null or invalid finalizer information for finalizer " + "named \"" + finalizername
1681                                             + "\" in state \"" + statename + "\" for policy \"" + policyname + ":" 
1682                                             + policyversion
1683                                             + "\". The policy and state were created, but there was an error adding the"
1684                                             + " finalizer. The policy has only been partially defined.");
1685                             return ret;
1686                         }
1687                         tempres = sessionApexModel.createPolicyStateFinalizerLogic(policyname, policyversion, statename,
1688                                 finalizername, finalizer.getLogicFlavour(), finalizer.getLogic());
1689                         if (tempres.isNOK()) {
1690                             tempres.addMessage("Failed to add finalizer information for finalizer named \""
1691                                     + finalizername + "\" in" + " state \"" + statename + "\" for policy \""
1692                                     + policyname + ":" + policyversion
1693                                     + "\". The policy and state were created, but there was an error adding the"
1694                                     + " finalizer. The policy has only been partially defined.");
1695                             ret = tempres;
1696                             return ret;
1697                         }
1698                     }
1699                 }
1700                 final Map<String, BeanStateOutput> outputs = state.getStateOutputs();
1701                 if (outputs == null || outputs.isEmpty()) {
1702                     ret = new ApexAPIResult(RESULT.FAILED,
1703                             "No state outputs have been defined in state \"" + statename + "\" for policy \""
1704                                     + policyname + ":" + policyversion
1705                                     + "\". The policy and state were created, but there was an error adding state"
1706                                     + " outputs. The policy has only been partially defined.");
1707                     return ret;
1708                 }
1709                 for (final Map.Entry<String, BeanStateOutput> o : outputs.entrySet()) {
1710                     final String outputname = o.getKey();
1711                     final BeanStateOutput output = o.getValue();
1712                     if (outputname == null || output == null || output.getEvent() == null) {
1713                         ret = new ApexAPIResult(RESULT.FAILED,
1714                                 "Null or invalid output information for output named \"" + outputname + "\" in state \""
1715                                         + statename + "\" for policy \"" + policyname + ":" + policyversion
1716                                         + "\". The policy and state were created, but there was an error adding the"
1717                                         + " output. The policy has only been partially defined.");
1718                         return ret;
1719                     }
1720                     tempres = sessionApexModel.createPolicyStateOutput(policyname, policyversion, statename, outputname,
1721                             output.getEvent().getName(), output.getEvent().getVersion(), output.getNextState());
1722                     if (tempres.isNOK()) {
1723                         tempres.addMessage("Failed to add output information for output named \"" + outputname
1724                                 + "\" in state \"" + statename + "\" for policy \"" + policyname + ":" + policyversion
1725                                 + "\". The policy and state were created, but there was an error adding the output."
1726                                 + " The policy has only been partially defined.");
1727                         ret = tempres;
1728                         return ret;
1729                     }
1730                 }
1731
1732                 final Map<String, BeanStateTaskRef> taskmap = state.getTasks();
1733                 if (taskmap == null || taskmap.isEmpty()) {
1734                     ret = new ApexAPIResult(RESULT.FAILED,
1735                             "No tasks have been defined in state \"" + statename + "\" for policy \"" + policyname + ":"
1736                                     + policyversion
1737                                     + "\". The policy and state were created, but there was an error adding tasks."
1738                                     + " The policy has only been partially defined.");
1739                     return ret;
1740                 }
1741                 for (final Map.Entry<String, BeanStateTaskRef> t : taskmap.entrySet()) {
1742                     final String tasklocalname = t.getKey();
1743                     final BeanStateTaskRef taskref = t.getValue();
1744                     if (tasklocalname == null || taskref == null || taskref.getTask() == null) {
1745                         ret = new ApexAPIResult(RESULT.FAILED,
1746                                 "Null or invalid task information for task named \"" + tasklocalname + "\" in state \""
1747                                         + statename + "\" for for policy \"" + policyname + ":" + policyversion
1748                                         + "\". The policy and state were created, but there was an error adding the "
1749                                         + "task. The policy has only been partially defined.");
1750                         return ret;
1751                     }
1752                     tempres = sessionApexModel.createPolicyStateTaskRef(policyname, policyversion, statename,
1753                             tasklocalname, taskref.getTask().getName(), taskref.getTask().getVersion(),
1754                             taskref.getOutputType(), taskref.getOutputName());
1755                     if (tempres.isNOK()) {
1756                         tempres.addMessage("Failed to add task reference \"" + t + "\" for state \"" + statename
1757                                 + "\" for policy \"" + policyname + ":" + policyversion
1758                                 + "\". The policy was created, but there was an error adding the task reference for"
1759                                 + " the state. The policy has only been partially defined.");
1760                         ret = tempres;
1761                         return ret;
1762                     }
1763                 }
1764
1765             }
1766             if (ret.isOK()) {
1767                 commitChanges();
1768             }
1769             return ret;
1770         } catch (final Exception e) {
1771             LOGGER.catching(e);
1772             throw e;
1773         } finally {
1774             LOGGER.exit((ret == null ? false : ret.isOK()));
1775             LOGGER.info("Policy/Create" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
1776         }
1777     }
1778     // CHECKSTYLE:ON: MethodLength
1779
1780     /**
1781      * Update a policy with the information in the JSON string passed.
1782      *
1783      * @param firstStatePeriodic indicates if periodic event should be created and added to model
1784      * @param jsonString the JSON string to be parsed. See {@linkplain BeanPolicy}
1785      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
1786      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
1787      */
1788     @PUT
1789     @Path("Policy/Update")
1790     public ApexAPIResult updatePolicy(@QueryParam("firstStatePeriodic") final boolean firstStatePeriodic,
1791             final String jsonString) {
1792         ApexAPIResult ret = null;
1793         LOGGER.entry(jsonString);
1794         try {
1795             ret = initialiseSessionForChanges();
1796             if (ret.isNOK()) {
1797                 return ret;
1798             }
1799
1800             final BeanPolicy jsonbean = RestUtils.getJSONParameters(jsonString, BeanPolicy.class);
1801
1802             if (jsonbean.getName() == null || jsonbean.getName().equals("") || jsonbean.getVersion() == null
1803                     || jsonbean.getVersion().equals("")) {
1804                 ret = new ApexAPIResult(RESULT.FAILED, "Null/Empty Policy name/version (\"" + jsonbean.getName() + ":"
1805                         + jsonbean.getVersion() + "\" passed to UpdatePolicy");
1806                 return ret;
1807             }
1808
1809             ret = sessionApexModel.deletePolicy(jsonbean.getName(), jsonbean.getVersion());
1810             if (ret.isNOK()) {
1811                 return ret;
1812             }
1813             if (firstStatePeriodic) {
1814                 final ApexAPIResult existingPeriodicEvent = sessionApexModel.listEvent("PeriodicEvent", null);
1815                 if (existingPeriodicEvent.isNOK()) {
1816                     final String periodicEventString =
1817                             "{\"name\":\"PeriodicEvent\",\"version\":\"0.0.1\","
1818                             + "\"uuid\":\"44236da1-3d47-4988-8033-b6fee9d6a0f4\","
1819                             + "\"description\":\"Generated description for concept referred to by key "
1820                             + "'PeriodicEvent:0.0.1'\",\"source\":\"System\",\"target\":\"Apex\","
1821                             + "\"nameSpace\":\"org.onap.policy.apex.domains.aadm.events\",\"parameters\":{}}";
1822                     ret = createEvent(periodicEventString);
1823                     if (ret.isNOK()) {
1824                         return ret;
1825                     }
1826                 }
1827             }
1828             ret = createPolicy(jsonString);
1829             if (ret.isOK()) {
1830                 commitChanges();
1831             }
1832             return ret;
1833         } catch (final Exception e) {
1834             LOGGER.catching(e);
1835             throw e;
1836         } finally {
1837             LOGGER.exit((ret == null ? false : ret.isOK()));
1838             LOGGER.info("Policy/Update" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
1839         }
1840     }
1841
1842     /**
1843      * List policies with the given key names/versions. If successful the result(s) will be
1844      * available in the result messages. The returned value(s) will be similar to {@link AxPolicy},
1845      * with merged {@linkplain AxKey Info} for the root object.
1846      *
1847      * @param name the name to search for. If null or empty, then all names will be queried
1848      * @param version the version to search for. If null then all versions will be searched for.
1849      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
1850      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
1851      */
1852     @GET
1853     @Path("Policy/Get")
1854     public ApexAPIResult listPolicy(@QueryParam("name") final String name,
1855             @QueryParam("version") final String version) {
1856         ApexAPIResult ret = null;
1857         String name1 = name;
1858         String version1 = version;
1859         LOGGER.entry(name1, version1);
1860         try {
1861             ret = initialiseSessionForReadOnly();
1862             if (ret.isNOK()) {
1863                 return ret;
1864             }
1865
1866             if (name1 == null || name1.equals("")) {
1867                 name1 = null;
1868             }
1869             if (version1 == null || version1.equals("")) {
1870                 version1 = null;
1871             }
1872
1873             ret = sessionApexModel.listPolicy(name1, version1);
1874
1875             if (ret.isNOK()) {
1876                 return ret;
1877             }
1878
1879             ret = addKeyInfo2Messages(ret);
1880             return ret;
1881         } catch (final Exception e) {
1882             LOGGER.catching(e);
1883             throw e;
1884         } finally {
1885             LOGGER.exit((ret == null ? false : ret.isOK()));
1886             LOGGER.info("Policy/Get" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
1887         }
1888     }
1889
1890     /**
1891      * Delete policies with the given key names/versions.
1892      *
1893      * @param name the name to search for. If null or empty, then all names will be queried
1894      * @param version the version to search for. If null then all versions will be searched for.
1895      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
1896      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
1897      */
1898     @DELETE
1899     @Path("Policy/Delete")
1900     public ApexAPIResult deletePolicy(@QueryParam("name") final String name,
1901             @QueryParam("version") final String version) {
1902         ApexAPIResult ret = null;
1903         String name1 = name;
1904         String version1 = version;
1905         LOGGER.entry(name1, version1);
1906         try {
1907             ret = initialiseSessionForChanges();
1908             if (ret.isNOK()) {
1909                 return ret;
1910             }
1911
1912             if (name1 == null || name1.equals("")) {
1913                 name1 = null;
1914             }
1915             if (version1 == null || version1.equals("")) {
1916                 version1 = null;
1917             }
1918
1919             // all input/output fields, parameters, logic, context references is "owned"/contained
1920             // in the task, so
1921             // deleting the task removes all of these
1922             ret = sessionApexModel.deletePolicy(name1, version1);
1923             if (ret.isOK()) {
1924                 commitChanges();
1925             }
1926             return ret;
1927         } catch (final Exception e) {
1928             LOGGER.catching(e);
1929             throw e;
1930         } finally {
1931             LOGGER.exit((ret == null ? false : ret.isOK()));
1932             LOGGER.info("Policy/Delete" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
1933         }
1934     }
1935
1936     /**
1937      * The json strings representing the objects listed, stored in result.messages[], does not
1938      * contain the AxKeyInformation for that object. This utility method retrieves the AxKeyInfo for
1939      * each object and adds it to the json for the object.
1940      *
1941      * @param result The list result, containing json representations of objects stored in its
1942      *        "messages" array
1943      * @return The list result, containing json augmented representations of objects stored in its
1944      *         "messages" array
1945      */
1946     private ApexAPIResult addKeyInfo2Messages(final ApexAPIResult result) {
1947         if (result.isNOK()) {
1948             return result;
1949         }
1950
1951         final ApexAPIResult ret = new ApexAPIResult(result.getResult());
1952         ret.setMessages(result.getMessages());
1953
1954         final List<String> messages = result.getMessages();
1955         final List<String> augmessages = new ArrayList<>(messages.size());
1956         final GsonBuilder gb = new GsonBuilder();
1957         gb.serializeNulls().enableComplexMapKeySerialization();
1958         final Gson gson = gb.create();
1959         for (final String message : messages) {
1960             try {
1961                 final JsonObject jsonObject = gson.fromJson(message, JsonObject.class);
1962                 JsonObject objecttochange = jsonObject;
1963                 String name = null;
1964                 if (jsonObject != null && jsonObject.get("key") != null && jsonObject.get("key").isJsonObject()
1965                         && jsonObject.getAsJsonObject("key").get("name") != null) {
1966                     name = jsonObject.getAsJsonObject("key").get("name").getAsString();
1967                 } else if (jsonObject != null && jsonObject.get("policyKey") != null
1968                         && jsonObject.get("policyKey").isJsonObject()
1969                         && jsonObject.getAsJsonObject("policyKey").get("name") != null) {
1970                     name = jsonObject.getAsJsonObject("policyKey").get("name").getAsString();
1971                 }
1972                 String version = null;
1973                 if (jsonObject != null && jsonObject.get("key") != null && jsonObject.get("key").isJsonObject()
1974                         && jsonObject.getAsJsonObject("key").get("version") != null) {
1975                     version = jsonObject.getAsJsonObject("key").get("version").getAsString();
1976                 } else if (jsonObject != null && jsonObject.get("policyKey") != null
1977                         && jsonObject.get("policyKey").isJsonObject()
1978                         && jsonObject.getAsJsonObject("policyKey").get("version") != null) {
1979                     version = jsonObject.getAsJsonObject("policyKey").get("version").getAsString();
1980                 }
1981
1982                 if (name == null && version == null && jsonObject.entrySet() != null
1983                         && jsonObject.entrySet().size() > 0) {
1984                     objecttochange = (JsonObject) jsonObject.entrySet().iterator().next().getValue();
1985                     if (objecttochange != null && objecttochange.get("key") != null
1986                             && objecttochange.get("key").isJsonObject()
1987                             && objecttochange.getAsJsonObject("key").get("name") != null) {
1988                         name = objecttochange.getAsJsonObject("key").get("name").getAsString();
1989                     } else if (objecttochange != null && objecttochange.get("policyKey") != null
1990                             && objecttochange.get("policyKey").isJsonObject()
1991                             && objecttochange.getAsJsonObject("policyKey").get("name") != null) {
1992                         name = objecttochange.getAsJsonObject("policyKey").get("name").getAsString();
1993                     }
1994                     if (objecttochange != null && objecttochange.get("key") != null
1995                             && objecttochange.get("key").isJsonObject()
1996                             && objecttochange.getAsJsonObject("key").get("version") != null) {
1997                         version = objecttochange.getAsJsonObject("key").get("version").getAsString();
1998                     } else if (objecttochange != null && objecttochange.get("policyKey") != null
1999                             && objecttochange.get("policyKey").isJsonObject()
2000                             && objecttochange.getAsJsonObject("policyKey").get("version") != null) {
2001                         version = objecttochange.getAsJsonObject("policyKey").get("version").getAsString();
2002                     }
2003                 }
2004
2005                 String uuid = null;
2006                 String desc = null;
2007
2008                 if (name != null && version != null) {
2009                     final ApexAPIResult keyInfoResult = sessionApexModel.listKeyInformation(name, version);
2010                     final List<String> keyInfoMessages = keyInfoResult.getMessages();
2011                     if (keyInfoResult.isOK() && keyInfoMessages != null && keyInfoMessages.size() > 0) {
2012                         final String keyInfoJson = keyInfoMessages.get(0);
2013                         final JsonObject keyInfoJsonObject = gson.fromJson(keyInfoJson, JsonObject.class);
2014                         if (keyInfoJsonObject != null && keyInfoJsonObject.get("apexKeyInfo") != null
2015                                 && keyInfoJsonObject.get("apexKeyInfo").getAsJsonObject().get("UUID") != null) {
2016                             uuid = keyInfoJsonObject.get("apexKeyInfo").getAsJsonObject().get("UUID").getAsString();
2017                         }
2018                         if (keyInfoJsonObject != null && keyInfoJsonObject.get("apexKeyInfo") != null
2019                                 && keyInfoJsonObject.get("apexKeyInfo").getAsJsonObject().get("description") != null) {
2020                             desc = keyInfoJsonObject.get("apexKeyInfo").getAsJsonObject().get("description")
2021                                     .getAsString();
2022                         }
2023                     }
2024                 }
2025                 objecttochange.addProperty("uuid", uuid);
2026                 objecttochange.addProperty("description", desc);
2027                 augmessages.add(gson.toJson(jsonObject));
2028             } catch (final Exception e) {
2029                 augmessages.add(message);
2030             }
2031         }
2032         ret.setMessages(augmessages);
2033
2034         if (messages.size() != augmessages.size()) {
2035             ret.setResult(RESULT.OTHER_ERROR);
2036             ret.addMessage("Failed to add KeyInfo to all results. Results are not complete");
2037         }
2038
2039         return ret;
2040     }
2041
2042     /*
2043      * This method is used only for testing and is used to cause an exception on calls from unit
2044      * test to test exception handling.
2045      */
2046     protected static int createCorruptSession() {
2047         final ApexEditorRestResource apexEditorRestResource = new ApexEditorRestResource();
2048         final ApexAPIResult result = apexEditorRestResource.createSession();
2049         final int corruptSessionId = new Integer(result.getMessages().get(0));
2050
2051         SESSIONMODELMAP.put(corruptSessionId, null);
2052
2053         return corruptSessionId;
2054     }
2055 }