09b34ebe4125ff4cc11c9e8f231f0ab9e25e50cc
[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. The event has only been partially defined.");
1004                         return ret;
1005                     }
1006                     final ApexAPIResult rettmp =
1007                             sessionApexModel.createEventPar(jsonbean.getName(), jsonbean.getVersion(), p.getKey(),
1008                                     p.getValue().getName(), p.getValue().getVersion(), p.getValue().getOptional());
1009                     if (rettmp.isNOK()) {
1010                         rettmp.addMessage("Failed to add event parameter information for parameter \"" + p.getKey()
1011                                 + "\" in event " + jsonbean.getName() + ":" + jsonbean.getVersion()
1012                                 + ". The event was created, but there was an error adding the event parameters. The event has only been partially defined.");
1013                         ret = rettmp;
1014                         return ret;
1015                     }
1016                 }
1017             }
1018             if (ret.isOK()) {
1019                 commitChanges();
1020             }
1021             return ret;
1022         } catch (final Exception e) {
1023             LOGGER.catching(e);
1024             throw e;
1025         } finally {
1026             LOGGER.exit((ret == null ? false : ret.isOK()));
1027             LOGGER.info("Event/Create" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
1028         }
1029     }
1030
1031     /**
1032      * Update an event with the information in the JSON string passed.
1033      *
1034      * @param jsonString the JSON string to be parsed. See {@linkplain BeanEvent}
1035      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
1036      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
1037      */
1038     @PUT
1039     @Path("Event/Update")
1040     public ApexAPIResult updateEvent(final String jsonString) {
1041         ApexAPIResult ret = null;
1042         LOGGER.entry(jsonString);
1043         try {
1044             ret = initialiseSessionForChanges();
1045             if (ret.isNOK()) {
1046                 return ret;
1047             }
1048
1049             final BeanEvent jsonbean = RestUtils.getJSONParameters(jsonString, BeanEvent.class);
1050
1051             if (jsonbean.getName() == null || jsonbean.getName().equals("") || jsonbean.getVersion() == null
1052                     || jsonbean.getVersion().equals("")) {
1053                 ret = new ApexAPIResult(RESULT.FAILED, "Null/Empty event name/version (\"" + jsonbean.getName() + ":"
1054                         + jsonbean.getVersion() + "\" passed to UpdateEvent");
1055                 return ret;
1056             }
1057
1058             ret = sessionApexModel.deleteEvent(jsonbean.getName(), jsonbean.getVersion());
1059             if (ret.isNOK()) {
1060                 return ret;
1061             }
1062
1063             ret = createEvent(jsonString);
1064             if (ret.isOK()) {
1065                 commitChanges();
1066             }
1067             return ret;
1068         } catch (final Exception e) {
1069             LOGGER.catching(e);
1070             throw e;
1071         } finally {
1072             LOGGER.exit((ret == null ? false : ret.isOK()));
1073             LOGGER.info("Event/Update" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
1074         }
1075     }
1076
1077     /**
1078      * List events with the given key names/versions. If successful the result(s) will be available
1079      * in the result messages. The returned value(s) will be similar to {@link AxEvent}, with merged
1080      * {@linkplain AxKeyInfo} for the root object.
1081      *
1082      * @param name the name to search for. If null or empty, then all names will be queried
1083      * @param version the version to search for. If null then all versions will be searched for.
1084      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
1085      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
1086      */
1087     @GET
1088     @Path("Event/Get")
1089     public ApexAPIResult listEvent(@QueryParam("name") final String name, @QueryParam("version") final String version) {
1090         ApexAPIResult ret = null;
1091         String name1 = name;
1092         String version1 = version;
1093         LOGGER.entry(name1, version1);
1094         try {
1095             ret = initialiseSessionForReadOnly();
1096             if (ret.isNOK()) {
1097                 return ret;
1098             }
1099
1100             if (name1 == null || name1.equals("")) {
1101                 name1 = null;
1102             }
1103             if (version1 == null || version1.equals("")) {
1104                 version1 = null;
1105             }
1106
1107             ret = sessionApexModel.listEvent(name1, version1);
1108             if (ret.isNOK()) {
1109                 return ret;
1110             }
1111
1112             ret = addKeyInfo2Messages(ret);
1113             return ret;
1114         } catch (final Exception e) {
1115             LOGGER.catching(e);
1116             throw e;
1117         } finally {
1118             LOGGER.exit((ret == null ? false : ret.isOK()));
1119             LOGGER.info("Event/Get" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
1120         }
1121     }
1122
1123     /**
1124      * Delete events with the given key names/versions.
1125      *
1126      * @param name the name to search for. If null or empty, then all names will be queried
1127      * @param version the version to search for. If null then all versions will be searched for.
1128      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
1129      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
1130      */
1131     @DELETE
1132     @Path("Event/Delete")
1133     public ApexAPIResult deleteEvent(@QueryParam("name") final String name,
1134             @QueryParam("version") final String version) {
1135         ApexAPIResult ret = null;
1136         String name1 = name;
1137         String version1 = version;
1138         LOGGER.entry(name1, version1);
1139         try {
1140             if (name1 == null || name1.equals("")) {
1141                 name1 = null;
1142             }
1143             if (version1 == null || version1.equals("")) {
1144                 version1 = null;
1145             }
1146
1147             ret = initialiseSessionForChanges();
1148             if (ret.isNOK()) {
1149                 return ret;
1150             }
1151
1152             ret = sessionApexModel.deleteEvent(name1, version1);
1153             if (ret.isOK()) {
1154                 commitChanges();
1155             }
1156             return ret;
1157         } catch (final Exception e) {
1158             LOGGER.catching(e);
1159             throw e;
1160         } finally {
1161             LOGGER.exit((ret == null ? false : ret.isOK()));
1162             LOGGER.info("Event/Delete" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
1163         }
1164     }
1165
1166     /**
1167      * Validate events with the given key names/versions. The result(s) will be available in the
1168      * result messages.
1169      *
1170      * @param name the name to search for. If null or empty, then all names will be queried
1171      * @param version the version to search for. If null then all versions will be searched for.
1172      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
1173      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
1174      */
1175     @GET
1176     @Path("Validate/Event")
1177     public ApexAPIResult validateEvent(@QueryParam("name") final String name,
1178             @QueryParam("version") final String version) {
1179         ApexAPIResult ret = null;
1180         String name1 = name;
1181         String version1 = version;
1182         LOGGER.entry(name1, version1);
1183         try {
1184             ret = initialiseSessionForReadOnly();
1185             if (ret.isNOK()) {
1186                 return ret;
1187             }
1188
1189             if (name1 == null || name1.equals("")) {
1190                 name1 = null;
1191             }
1192             if (version1 == null || version1.equals("")) {
1193                 version1 = null;
1194             }
1195
1196             ret = sessionApexModel.listEvent(name1, version1);
1197             if (ret.isNOK()) {
1198                 return ret;
1199             }
1200
1201             ret = addKeyInfo2Messages(ret);
1202             return ret;
1203         } catch (final Exception e) {
1204             LOGGER.catching(e);
1205             throw e;
1206         } finally {
1207             LOGGER.exit((ret == null ? false : ret.isOK()));
1208             LOGGER.info("Validate/Event" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
1209         }
1210     }
1211
1212     /**
1213      * Creates a task with the information in the JSON string passed.
1214      *
1215      * @param jsonString the JSON string to be parsed. See {@linkplain BeanTask}
1216      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
1217      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
1218      */
1219     @POST
1220     @Path("Task/Create")
1221     public ApexAPIResult createTask(final String jsonString) {
1222         ApexAPIResult ret = null;
1223         ApexAPIResult tempres = null;
1224         LOGGER.entry(jsonString);
1225         try {
1226             ret = initialiseSessionForChanges();
1227             if (ret.isNOK()) {
1228                 return ret;
1229             }
1230
1231             final BeanTask jsonbean = RestUtils.getJSONParameters(jsonString, BeanTask.class);
1232
1233             ret = sessionApexModel.createTask(jsonbean.getName(), jsonbean.getVersion(), jsonbean.getUuid(),
1234                     jsonbean.getDescription());
1235             if (ret.isNOK()) {
1236                 return ret;
1237             }
1238             if (jsonbean.getInputFields() != null) {
1239                 for (final Entry<String, BeanField> fin : jsonbean.getInputFields().entrySet()) {
1240                     if (fin.getValue() == null) {
1241                         ret = new ApexAPIResult(RESULT.FAILED, "Null task input field information for field \""
1242                                 + fin.getKey() + "\" in task " + jsonbean.getName() + ":" + jsonbean.getVersion()
1243                                 + ". The task was created, but there was an error adding the input fields. The task has only been partially defined.");
1244                         return ret;
1245                     }
1246                     if (fin.getKey() == null || !fin.getKey().equals(fin.getValue().getLocalName())) {
1247                         ret = new ApexAPIResult(RESULT.FAILED, "Invalid task input field information for field \""
1248                                 + fin.getKey() + "\" in task " + jsonbean.getName() + ":" + jsonbean.getVersion()
1249                                 + ". The localName of the field (\"" + fin.getValue().getLocalName()
1250                                 + "\") is not the same as the field name. "
1251                                 + "The task was created, but there was an error adding the input fields. The task has only been partially defined.");
1252                         return ret;
1253                     }
1254                     tempres = sessionApexModel.createTaskInputField(jsonbean.getName(), jsonbean.getVersion(),
1255                             fin.getKey(), fin.getValue().getName(), fin.getValue().getVersion(),
1256                             fin.getValue().getOptional());
1257                     if (tempres.isNOK()) {
1258                         tempres.addMessage("Failed to add task input field information for field \"" + fin.getKey()
1259                                 + "\" in task " + jsonbean.getName() + ":" + jsonbean.getVersion()
1260                                 + ". The task was created, but there was an error adding the input fields. The task has only been partially defined.");
1261                         ret = tempres;
1262                         return ret;
1263                     }
1264                 }
1265             }
1266             if (jsonbean.getOutputFields() != null) {
1267                 for (final Entry<String, BeanField> fout : jsonbean.getOutputFields().entrySet()) {
1268                     if (fout.getValue() == null) {
1269                         ret = new ApexAPIResult(RESULT.FAILED, "Null task output field information for field \""
1270                                 + fout.getKey() + "\" in task " + jsonbean.getName() + ":" + jsonbean.getVersion()
1271                                 + ". The task was created, but there was an error adding the output fields. The task has only been partially defined.");
1272                         return ret;
1273                     }
1274                     if (fout.getKey() == null || !fout.getKey().equals(fout.getValue().getLocalName())) {
1275                         ret = new ApexAPIResult(RESULT.FAILED, "Invalid task output field information for field \""
1276                                 + fout.getKey() + "\" in task " + jsonbean.getName() + ":" + jsonbean.getVersion()
1277                                 + ". The localName of the field (\"" + fout.getValue().getLocalName()
1278                                 + "\") is not the same as the field name. "
1279                                 + "The task was created, but there was an error adding the output fields. The task has only been partially defined.");
1280                         return ret;
1281                     }
1282                     tempres = sessionApexModel.createTaskOutputField(jsonbean.getName(), jsonbean.getVersion(),
1283                             fout.getKey(), fout.getValue().getName(), fout.getValue().getVersion(),
1284                             fout.getValue().getOptional());
1285                     if (tempres.isNOK()) {
1286                         tempres.addMessage("Failed to add task output field information for field \"" + fout.getKey()
1287                                 + "\" in task " + jsonbean.getName() + ":" + jsonbean.getVersion()
1288                                 + ". The task was created, but there was an error adding the output fields. The task has only been partially defined.");
1289                         ret = tempres;
1290                         return ret;
1291                     }
1292                 }
1293             }
1294             if (jsonbean.getTaskLogic() != null) {
1295                 final BeanLogic logic = jsonbean.getTaskLogic();
1296                 tempres = sessionApexModel.createTaskLogic(jsonbean.getName(), jsonbean.getVersion(),
1297                         logic.getLogicFlavour(), logic.getLogic());
1298                 if (tempres.isNOK()) {
1299                     tempres.addMessage("Failed to add task logic in task " + jsonbean.getName() + ":"
1300                             + jsonbean.getVersion()
1301                             + ". The task was created, but there was an error adding the logic. The task has only been partially defined.");
1302                     ret = tempres;
1303                     return ret;
1304                 }
1305             }
1306             if (jsonbean.getParameters() != null) {
1307                 for (final Entry<String, BeanTaskParameter> param : jsonbean.getParameters().entrySet()) {
1308                     if (param.getKey() == null || param.getValue() == null
1309                             || !param.getKey().equals(param.getValue().getParameterName())) {
1310                         ret = new ApexAPIResult(RESULT.FAILED,
1311                                 "Null or invalid task parameter information for parameter \"" + param.getKey()
1312                                         + "\" in task " + jsonbean.getName() + ":" + jsonbean.getVersion()
1313                                         + ". The task was created, but there was an error adding the parameters. The task has only been partially defined.");
1314                         return ret;
1315                     }
1316                     tempres = sessionApexModel.createTaskParameter(jsonbean.getName(), jsonbean.getVersion(),
1317                             param.getValue().getParameterName(), param.getValue().getDefaultValue());
1318                     if (tempres.isNOK()) {
1319                         tempres.addMessage("Failed to add task parameter \"" + param.getKey() + "\" in task "
1320                                 + jsonbean.getName() + ":" + jsonbean.getVersion()
1321                                 + ". The task was created, but there was an error adding the parameters. The task has only been partially defined.");
1322                         ret = tempres;
1323                         return ret;
1324                     }
1325                 }
1326             }
1327             if (jsonbean.getContexts() != null) {
1328                 for (final BeanKeyRef contextalbum : jsonbean.getContexts()) {
1329                     if (contextalbum.getName() == null || contextalbum.getVersion() == null) {
1330                         ret = new ApexAPIResult(RESULT.FAILED,
1331                                 "Null or invalid context album reference information in task " + jsonbean.getName()
1332                                         + ":" + jsonbean.getVersion()
1333                                         + ". The task was created, but there was an error adding the"
1334                                         + " context album reference. The task has only been partially defined.");
1335                         return ret;
1336                     }
1337                     tempres = sessionApexModel.createTaskContextRef(jsonbean.getName(), jsonbean.getVersion(),
1338                             contextalbum.getName(), contextalbum.getVersion());
1339                     if (tempres.isNOK()) {
1340                         ret = new ApexAPIResult(RESULT.FAILED,
1341                                 "Failed to add context album reference information in task " + jsonbean.getName() + ":"
1342                                         + jsonbean.getVersion()
1343                                         + ". The task was created, but there was an error adding the"
1344                                         + " context album reference. The task has only been partially defined.");
1345                         return ret;
1346                     }
1347                 }
1348             }
1349             if (ret.isOK()) {
1350                 commitChanges();
1351             }
1352             return ret;
1353         } catch (final Exception e) {
1354             LOGGER.catching(e);
1355             throw e;
1356         } finally {
1357             LOGGER.exit((ret == null ? false : ret.isOK()));
1358             LOGGER.info("Task/Create" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
1359         }
1360     }
1361
1362     /**
1363      * Update a task with the information in the JSON string passed.
1364      *
1365      * @param jsonString the JSON string to be parsed. See {@linkplain BeanTask}
1366      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
1367      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
1368      */
1369     @PUT
1370     @Path("Task/Update")
1371     public ApexAPIResult updateTask(final String jsonString) {
1372         ApexAPIResult ret = null;
1373         LOGGER.entry(jsonString);
1374         try {
1375             ret = initialiseSessionForChanges();
1376             if (ret.isNOK()) {
1377                 return ret;
1378             }
1379
1380             final BeanTask jsonbean = RestUtils.getJSONParameters(jsonString, BeanTask.class);
1381
1382             if (jsonbean.getName() == null || jsonbean.getName().equals("") || jsonbean.getVersion() == null
1383                     || jsonbean.getVersion().equals("")) {
1384                 ret = new ApexAPIResult(RESULT.FAILED, "Null/Empty task name/version (\"" + jsonbean.getName() + ":"
1385                         + jsonbean.getVersion() + "\" passed to UpdateTask");
1386                 return ret;
1387             }
1388
1389             ret = sessionApexModel.deleteTask(jsonbean.getName(), jsonbean.getVersion());
1390             if (ret.isNOK()) {
1391                 return ret;
1392             }
1393
1394             ret = createTask(jsonString);
1395             if (ret.isOK()) {
1396                 commitChanges();
1397             }
1398             return ret;
1399         } catch (final Exception e) {
1400             LOGGER.catching(e);
1401             throw e;
1402         } finally {
1403             LOGGER.exit((ret == null ? false : ret.isOK()));
1404             LOGGER.info("Task/Update" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
1405         }
1406     }
1407
1408     /**
1409      * List tasks with the given key names/versions. If successful the result(s) will be available
1410      * in the result messages. The returned value(s) will be similar to {@link AxTask}, with merged
1411      * {@linkplain AxKeyInfo} for the root object.
1412      *
1413      * @param name the name to search for. If null or empty, then all names will be queried
1414      * @param version the version to search for. If null then all versions will be searched for.
1415      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
1416      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
1417      */
1418     @GET
1419     @Path("Task/Get")
1420     public ApexAPIResult listTask(@QueryParam("name") final String name, @QueryParam("version") final String version) {
1421         ApexAPIResult ret = null;
1422         String name1 = name;
1423         String version1 = version;
1424         LOGGER.entry(name1, version1);
1425         try {
1426             ret = initialiseSessionForReadOnly();
1427             if (ret.isNOK()) {
1428                 return ret;
1429             }
1430
1431             if (name1 == null || name1.equals("")) {
1432                 name1 = null;
1433             }
1434             if (version1 == null || version1.equals("")) {
1435                 version1 = null;
1436             }
1437
1438             ret = sessionApexModel.listTask(name1, version1);
1439             if (ret.isNOK()) {
1440                 return ret;
1441             }
1442
1443             ret = addKeyInfo2Messages(ret);
1444             return ret;
1445         } catch (final Exception e) {
1446             LOGGER.catching(e);
1447             throw e;
1448         } finally {
1449             LOGGER.exit((ret == null ? false : ret.isOK()));
1450             LOGGER.info("Task/Get" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
1451         }
1452     }
1453
1454     /**
1455      * Delete tasks with the given key names/versions.
1456      *
1457      * @param name the name to search for. If null or empty, then all names will be queried
1458      * @param version the version to search for. If null then all versions will be searched for.
1459      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
1460      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
1461      */
1462     @DELETE
1463     @Path("Task/Delete")
1464     public ApexAPIResult deleteTask(@QueryParam("name") final String name,
1465             @QueryParam("version") final String version) {
1466         ApexAPIResult ret = null;
1467         String name1 = name;
1468         String version1 = version;
1469         LOGGER.entry(name1, version1);
1470         try {
1471             ret = initialiseSessionForChanges();
1472             if (ret.isNOK()) {
1473                 return ret;
1474             }
1475
1476             if (name1 == null || name1.equals("")) {
1477                 name1 = null;
1478             }
1479             if (version1 == null || version1.equals("")) {
1480                 version1 = null;
1481             }
1482
1483             // all input/output fields, parameters, logic, context references is "owned"/contained
1484             // in the task, so
1485             // deleting the task removes all of these
1486             ret = sessionApexModel.deleteTask(name1, version1);
1487             if (ret.isOK()) {
1488                 commitChanges();
1489             }
1490             return ret;
1491         } catch (final Exception e) {
1492             LOGGER.catching(e);
1493             throw e;
1494         } finally {
1495             LOGGER.exit((ret == null ? false : ret.isOK()));
1496             LOGGER.info("Task/Delete" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
1497         }
1498     }
1499
1500     /**
1501      * Validate tasks with the given key names/versions. The result(s) will be available in the
1502      * result messages.
1503      *
1504      * @param name the name to search for. If null or empty, then all names will be queried
1505      * @param version the version to search for. If null then all versions will be searched for.
1506      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
1507      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
1508      */
1509     @GET
1510     @Path("Validate/Task")
1511     public ApexAPIResult validateTask(@QueryParam("name") final String name,
1512             @QueryParam("version") final String version) {
1513         ApexAPIResult ret = null;
1514         String name1 = name;
1515         String version1 = version;
1516         LOGGER.entry(name1, version1);
1517         try {
1518             ret = initialiseSessionForReadOnly();
1519             if (ret.isNOK()) {
1520                 return ret;
1521             }
1522
1523             if (name1 == null || name1.equals("")) {
1524                 name1 = null;
1525             }
1526             if (version1 == null || version1.equals("")) {
1527                 version1 = null;
1528             }
1529
1530             ret = sessionApexModel.listTask(name1, version1);
1531             if (ret.isNOK()) {
1532                 return ret;
1533             }
1534
1535             ret = addKeyInfo2Messages(ret);
1536             return ret;
1537         } catch (final Exception e) {
1538             LOGGER.catching(e);
1539             throw e;
1540         } finally {
1541             LOGGER.exit((ret == null ? false : ret.isOK()));
1542             LOGGER.info("Validate/Task" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
1543         }
1544     }
1545
1546     // CHECKSTYLE:OFF: MethodLength
1547     /**
1548      * Creates a policy with the information in the JSON string passed.
1549      *
1550      * @param jsonString the JSON string to be parsed See {@linkplain BeanPolicy}
1551      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
1552      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
1553      */
1554     @POST
1555     @Path("Policy/Create")
1556     public ApexAPIResult createPolicy(final String jsonString) {
1557
1558         ApexAPIResult ret = null;
1559         ApexAPIResult tempres = null;
1560         LOGGER.entry(jsonString);
1561         try {
1562             ret = initialiseSessionForChanges();
1563             if (ret.isNOK()) {
1564                 return ret;
1565             }
1566
1567             final BeanPolicy jsonbean = RestUtils.getJSONParameters(jsonString, BeanPolicy.class);
1568             final String policyname = jsonbean.getName();
1569             final String policyversion = jsonbean.getVersion();
1570
1571             ret = sessionApexModel.createPolicy(policyname, policyversion, jsonbean.getTemplate(),
1572                     jsonbean.getFirstState(), jsonbean.getUuid(), jsonbean.getDescription());
1573             if (ret.isNOK()) {
1574                 return ret;
1575             }
1576
1577             if (jsonbean.getStates() == null || jsonbean.getStates().isEmpty()) {
1578                 ret = new ApexAPIResult(RESULT.FAILED, "Null or empty state map; no states defined for policy \""
1579                         + policyname + ":" + policyversion
1580                         + "\". The policy was created, but there was an error adding states. The policy has only been partially defined.");
1581                 return ret;
1582             }
1583
1584             final Map<String, BeanState> statemap = jsonbean.getStates();
1585             // need to create all the states first, before populating them
1586             for (final Map.Entry<String, BeanState> e : statemap.entrySet()) {
1587                 final String statename = e.getKey();
1588                 final BeanState state = e.getValue();
1589                 if (state == null) {
1590                     ret = new ApexAPIResult(RESULT.FAILED, "Null or invalid state information for state \"" + statename
1591                             + "\" for policy \"" + policyname + ":" + policyversion
1592                             + "\". The policy was created, but there was an error adding the state. The policy has only been partially defined.");
1593                     return ret;
1594                 }
1595                 if (state.getTrigger() == null) {
1596                     ret = new ApexAPIResult(RESULT.FAILED, "Null or invalid state trigger for state \"" + statename
1597                             + "\" for policy \"" + policyname + ":" + policyversion
1598                             + "\". The policy was created, but there was an error adding the state. The policy has only been partially defined.");
1599                     return ret;
1600                 }
1601                 if (state.getDefaultTask() == null) {
1602                     ret = new ApexAPIResult(RESULT.FAILED, "Null or invalid default task for state \"" + statename
1603                             + "\" for policy \"" + policyname + ":" + policyversion
1604                             + "\". The policy was created, but there was an error adding the state. The policy has only been partially defined.");
1605                     return ret;
1606                 }
1607                 tempres = sessionApexModel.createPolicyState(policyname, policyversion, statename,
1608                         state.getTrigger().getName(), state.getTrigger().getVersion(), state.getDefaultTask().getName(),
1609                         state.getDefaultTask().getVersion());
1610                 if (tempres.isNOK()) {
1611                     ret = tempres;
1612                     return ret;
1613                 }
1614             }
1615
1616             for (final Map.Entry<String, BeanState> e : statemap.entrySet()) {
1617                 final String statename = e.getKey();
1618                 final BeanState state = e.getValue();
1619
1620                 final BeanLogic tsl = state.getTaskSelectionLogic();
1621                 if (tsl != null) {
1622                     tempres = sessionApexModel.createPolicyStateTaskSelectionLogic(policyname, policyversion, statename,
1623                             tsl.getLogicFlavour(), tsl.getLogic());
1624                     if (tempres.isNOK()) {
1625                         tempres.addMessage("Failed to add task selection logic for state \"" + statename + "\" for"
1626                                 + " policy \"" + policyname + ":" + policyversion
1627                                 + "\". The policy was created, but there was an error adding the task selection logic for "
1628                                 + "the state. The policy has only been partially defined.");
1629                         ret = tempres;
1630                         return ret;
1631                     }
1632                 }
1633
1634                 final BeanKeyRef[] contexts = state.getContexts();
1635                 if (contexts != null) {
1636                     for (final BeanKeyRef c : contexts) {
1637                         if (c == null) {
1638                             ret = new ApexAPIResult(RESULT.FAILED,
1639                                     "Null or invalid context reference \"" + c + "\" for" + " state \"" + statename
1640                                             + "\" for policy \"" + policyname + ":" + policyversion
1641                                             + "\". The policy was created, but there was an error adding the context reference for the state."
1642                                             + " The policy has only been partially defined.");
1643                             return ret;
1644                         }
1645                         tempres = sessionApexModel.createPolicyStateContextRef(policyname, policyversion, statename,
1646                                 c.getName(), c.getVersion());
1647                         if (tempres.isNOK()) {
1648                             tempres.addMessage("Failed to add context reference \"" + c + "\" for state \"" + statename
1649                                     + "\" for policy \"" + policyname + ":" + policyversion
1650                                     + "\". The policy was created, but there was an error adding the context reference for the state."
1651                                     + " The policy has only been partially defined.");
1652                             ret = tempres;
1653                             return ret;
1654                         }
1655                     }
1656                 }
1657
1658                 final Map<String, BeanLogic> finalizers = state.getFinalizers();
1659                 if (finalizers != null) {
1660                     for (final Map.Entry<String, BeanLogic> f : finalizers.entrySet()) {
1661                         final String finalizername = f.getKey();
1662                         final BeanLogic finalizer = f.getValue();
1663                         if (finalizername == null || finalizer == null) {
1664                             ret = new ApexAPIResult(RESULT.FAILED,
1665                                     "Null or invalid finalizer information for finalizer " + "named \"" + finalizername
1666                                             + "\" in state \"" + statename + "\" for policy \"" + policyname + ":"
1667                                             + policyversion
1668                                             + "\". The policy and state were created, but there was an error adding the finalizer."
1669                                             + " The policy has only been partially defined.");
1670                             return ret;
1671                         }
1672                         tempres = sessionApexModel.createPolicyStateFinalizerLogic(policyname, policyversion, statename,
1673                                 finalizername, finalizer.getLogicFlavour(), finalizer.getLogic());
1674                         if (tempres.isNOK()) {
1675                             tempres.addMessage("Failed to add finalizer information for finalizer named \""
1676                                     + finalizername + "\" in" + " state \"" + statename + "\" for policy \""
1677                                     + policyname + ":" + policyversion
1678                                     + "\". The policy and state were created, but there was an error adding the finalizer."
1679                                     + " The policy has only been partially defined.");
1680                             ret = tempres;
1681                             return ret;
1682                         }
1683                     }
1684                 }
1685                 final Map<String, BeanStateOutput> outputs = state.getStateOutputs();
1686                 if (outputs == null || outputs.isEmpty()) {
1687                     ret = new ApexAPIResult(RESULT.FAILED,
1688                             "No state outputs have been defined in state \"" + statename + "\" for policy \""
1689                                     + policyname + ":" + policyversion
1690                                     + "\". The policy and state were created, but there was an error adding state outputs."
1691                                     + " The policy has only been partially defined.");
1692                     return ret;
1693                 }
1694                 for (final Map.Entry<String, BeanStateOutput> o : outputs.entrySet()) {
1695                     final String outputname = o.getKey();
1696                     final BeanStateOutput output = o.getValue();
1697                     if (outputname == null || output == null || output.getEvent() == null) {
1698                         ret = new ApexAPIResult(RESULT.FAILED,
1699                                 "Null or invalid output information for output named \"" + outputname + "\" in state \""
1700                                         + statename + "\" for policy \"" + policyname + ":" + policyversion
1701                                         + "\". The policy and state were created, but there was an error adding the output."
1702                                         + " The policy has only been partially defined.");
1703                         return ret;
1704                     }
1705                     tempres = sessionApexModel.createPolicyStateOutput(policyname, policyversion, statename, outputname,
1706                             output.getEvent().getName(), output.getEvent().getVersion(), output.getNextState());
1707                     if (tempres.isNOK()) {
1708                         tempres.addMessage("Failed to add output information for output named \"" + outputname
1709                                 + "\" in state \"" + statename + "\" for policy \"" + policyname + ":" + policyversion
1710                                 + "\". The policy and state were created, but there was an error adding the output."
1711                                 + " The policy has only been partially defined.");
1712                         ret = tempres;
1713                         return ret;
1714                     }
1715                 }
1716
1717                 final Map<String, BeanStateTaskRef> taskmap = state.getTasks();
1718                 if (taskmap == null || taskmap.isEmpty()) {
1719                     ret = new ApexAPIResult(RESULT.FAILED,
1720                             "No tasks have been defined in state \"" + statename + "\" for policy \"" + policyname + ":"
1721                                     + policyversion
1722                                     + "\". The policy and state were created, but there was an error adding tasks."
1723                                     + " The policy has only been partially defined.");
1724                     return ret;
1725                 }
1726                 for (final Map.Entry<String, BeanStateTaskRef> t : taskmap.entrySet()) {
1727                     final String tasklocalname = t.getKey();
1728                     final BeanStateTaskRef taskref = t.getValue();
1729                     if (tasklocalname == null || taskref == null || taskref.getTask() == null) {
1730                         ret = new ApexAPIResult(RESULT.FAILED,
1731                                 "Null or invalid task information for task named \"" + tasklocalname + "\" in state \""
1732                                         + statename + "\" for for policy \"" + policyname + ":" + policyversion
1733                                         + "\". The policy and state were created, but there was an error adding the task. "
1734                                         + "The policy has only been partially defined.");
1735                         return ret;
1736                     }
1737                     tempres = sessionApexModel.createPolicyStateTaskRef(policyname, policyversion, statename,
1738                             tasklocalname, taskref.getTask().getName(), taskref.getTask().getVersion(),
1739                             taskref.getOutputType(), taskref.getOutputName());
1740                     if (tempres.isNOK()) {
1741                         tempres.addMessage("Failed to add task reference \"" + t + "\" for state \"" + statename
1742                                 + "\" for policy \"" + policyname + ":" + policyversion
1743                                 + "\". The policy was created, but there was an error adding the task reference for the state."
1744                                 + " The policy has only been partially defined.");
1745                         ret = tempres;
1746                         return ret;
1747                     }
1748                 }
1749
1750             }
1751             if (ret.isOK()) {
1752                 commitChanges();
1753             }
1754             return ret;
1755         } catch (final Exception e) {
1756             LOGGER.catching(e);
1757             throw e;
1758         } finally {
1759             LOGGER.exit((ret == null ? false : ret.isOK()));
1760             LOGGER.info("Policy/Create" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
1761         }
1762     }
1763     // CHECKSTYLE:ON: MethodLength
1764
1765     /**
1766      * Update a policy with the information in the JSON string passed.
1767      *
1768      * @param firstStatePeriodic indicates if periodic event should be created and added to model
1769      * @param jsonString the JSON string to be parsed. See {@linkplain BeanPolicy}
1770      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
1771      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
1772      */
1773     @PUT
1774     @Path("Policy/Update")
1775     public ApexAPIResult updatePolicy(@QueryParam("firstStatePeriodic") final boolean firstStatePeriodic,
1776             final String jsonString) {
1777         ApexAPIResult ret = null;
1778         LOGGER.entry(jsonString);
1779         try {
1780             ret = initialiseSessionForChanges();
1781             if (ret.isNOK()) {
1782                 return ret;
1783             }
1784
1785             final BeanPolicy jsonbean = RestUtils.getJSONParameters(jsonString, BeanPolicy.class);
1786
1787             if (jsonbean.getName() == null || jsonbean.getName().equals("") || jsonbean.getVersion() == null
1788                     || jsonbean.getVersion().equals("")) {
1789                 ret = new ApexAPIResult(RESULT.FAILED, "Null/Empty Policy name/version (\"" + jsonbean.getName() + ":"
1790                         + jsonbean.getVersion() + "\" passed to UpdatePolicy");
1791                 return ret;
1792             }
1793
1794             ret = sessionApexModel.deletePolicy(jsonbean.getName(), jsonbean.getVersion());
1795             if (ret.isNOK()) {
1796                 return ret;
1797             }
1798             if (firstStatePeriodic) {
1799                 final ApexAPIResult existingPeriodicEvent = sessionApexModel.listEvent("PeriodicEvent", null);
1800                 if (existingPeriodicEvent.isNOK()) {
1801                     final String periodicEventString =
1802                             "{\"name\":\"PeriodicEvent\",\"version\":\"0.0.1\",\"uuid\":\"44236da1-3d47-4988-8033-b6fee9d6a0f4\",\"description\":\"Generated description for concept referred to by key 'PeriodicEvent:0.0.1'\",\"source\":\"System\",\"target\":\"Apex\",\"nameSpace\":\"org.onap.policy.apex.domains.aadm.events\",\"parameters\":{}}";
1803                     ret = createEvent(periodicEventString);
1804                     if (ret.isNOK()) {
1805                         return ret;
1806                     }
1807                 }
1808             }
1809             ret = createPolicy(jsonString);
1810             if (ret.isOK()) {
1811                 commitChanges();
1812             }
1813             return ret;
1814         } catch (final Exception e) {
1815             LOGGER.catching(e);
1816             throw e;
1817         } finally {
1818             LOGGER.exit((ret == null ? false : ret.isOK()));
1819             LOGGER.info("Policy/Update" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
1820         }
1821     }
1822
1823     /**
1824      * List policies with the given key names/versions. If successful the result(s) will be
1825      * available in the result messages. The returned value(s) will be similar to {@link AxPolicy},
1826      * with merged {@linkplain AxKey Info} for the root object.
1827      *
1828      * @param name the name to search for. If null or empty, then all names will be queried
1829      * @param version the version to search for. If null then all versions will be searched for.
1830      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
1831      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
1832      */
1833     @GET
1834     @Path("Policy/Get")
1835     public ApexAPIResult listPolicy(@QueryParam("name") final String name,
1836             @QueryParam("version") final String version) {
1837         ApexAPIResult ret = null;
1838         String name1 = name;
1839         String version1 = version;
1840         LOGGER.entry(name1, version1);
1841         try {
1842             ret = initialiseSessionForReadOnly();
1843             if (ret.isNOK()) {
1844                 return ret;
1845             }
1846
1847             if (name1 == null || name1.equals("")) {
1848                 name1 = null;
1849             }
1850             if (version1 == null || version1.equals("")) {
1851                 version1 = null;
1852             }
1853
1854             ret = sessionApexModel.listPolicy(name1, version1);
1855
1856             if (ret.isNOK()) {
1857                 return ret;
1858             }
1859
1860             ret = addKeyInfo2Messages(ret);
1861             return ret;
1862         } catch (final Exception e) {
1863             LOGGER.catching(e);
1864             throw e;
1865         } finally {
1866             LOGGER.exit((ret == null ? false : ret.isOK()));
1867             LOGGER.info("Policy/Get" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
1868         }
1869     }
1870
1871     /**
1872      * Delete policies with the given key names/versions.
1873      *
1874      * @param name the name to search for. If null or empty, then all names will be queried
1875      * @param version the version to search for. If null then all versions will be searched for.
1876      * @return an ApexAPIResult object. If successful then {@link ApexAPIResult#isOK()} will return
1877      *         true. Any messages/errors can be retrieved using {@link ApexAPIResult#getMessages()}
1878      */
1879     @DELETE
1880     @Path("Policy/Delete")
1881     public ApexAPIResult deletePolicy(@QueryParam("name") final String name,
1882             @QueryParam("version") final String version) {
1883         ApexAPIResult ret = null;
1884         String name1 = name;
1885         String version1 = version;
1886         LOGGER.entry(name1, version1);
1887         try {
1888             ret = initialiseSessionForChanges();
1889             if (ret.isNOK()) {
1890                 return ret;
1891             }
1892
1893             if (name1 == null || name1.equals("")) {
1894                 name1 = null;
1895             }
1896             if (version1 == null || version1.equals("")) {
1897                 version1 = null;
1898             }
1899
1900             // all input/output fields, parameters, logic, context references is "owned"/contained
1901             // in the task, so
1902             // deleting the task removes all of these
1903             ret = sessionApexModel.deletePolicy(name1, version1);
1904             if (ret.isOK()) {
1905                 commitChanges();
1906             }
1907             return ret;
1908         } catch (final Exception e) {
1909             LOGGER.catching(e);
1910             throw e;
1911         } finally {
1912             LOGGER.exit((ret == null ? false : ret.isOK()));
1913             LOGGER.info("Policy/Delete" + (ret != null && ret.isOK() ? ": OK" : ": Not OK"));
1914         }
1915     }
1916
1917     /**
1918      * The json strings representing the objects listed, stored in result.messages[], does not
1919      * contain the AxKeyInformation for that object. This utility method retrieves the AxKeyInfo for
1920      * each object and adds it to the json for the object.
1921      *
1922      * @param result The list result, containing json representations of objects stored in its
1923      *        "messages" array
1924      * @return The list result, containing json augmented representations of objects stored in its
1925      *         "messages" array
1926      */
1927     private ApexAPIResult addKeyInfo2Messages(final ApexAPIResult result) {
1928         if (result.isNOK()) {
1929             return result;
1930         }
1931
1932         final ApexAPIResult ret = new ApexAPIResult(result.getResult());
1933         ret.setMessages(result.getMessages());
1934
1935         final List<String> messages = result.getMessages();
1936         final List<String> augmessages = new ArrayList<>(messages.size());
1937         final GsonBuilder gb = new GsonBuilder();
1938         gb.serializeNulls().enableComplexMapKeySerialization();
1939         final Gson gson = gb.create();
1940         for (final String message : messages) {
1941             try {
1942                 final JsonObject jsonObject = gson.fromJson(message, JsonObject.class);
1943                 JsonObject objecttochange = jsonObject;
1944                 String name = null;
1945                 if (jsonObject != null && jsonObject.get("key") != null && jsonObject.get("key").isJsonObject()
1946                         && jsonObject.getAsJsonObject("key").get("name") != null) {
1947                     name = jsonObject.getAsJsonObject("key").get("name").getAsString();
1948                 } else if (jsonObject != null && jsonObject.get("policyKey") != null
1949                         && jsonObject.get("policyKey").isJsonObject()
1950                         && jsonObject.getAsJsonObject("policyKey").get("name") != null) {
1951                     name = jsonObject.getAsJsonObject("policyKey").get("name").getAsString();
1952                 }
1953                 String version = null;
1954                 if (jsonObject != null && jsonObject.get("key") != null && jsonObject.get("key").isJsonObject()
1955                         && jsonObject.getAsJsonObject("key").get("version") != null) {
1956                     version = jsonObject.getAsJsonObject("key").get("version").getAsString();
1957                 } else if (jsonObject != null && jsonObject.get("policyKey") != null
1958                         && jsonObject.get("policyKey").isJsonObject()
1959                         && jsonObject.getAsJsonObject("policyKey").get("version") != null) {
1960                     version = jsonObject.getAsJsonObject("policyKey").get("version").getAsString();
1961                 }
1962
1963                 if (name == null && version == null && jsonObject.entrySet() != null
1964                         && jsonObject.entrySet().size() > 0) {
1965                     objecttochange = (JsonObject) jsonObject.entrySet().iterator().next().getValue();
1966                     if (objecttochange != null && objecttochange.get("key") != null
1967                             && objecttochange.get("key").isJsonObject()
1968                             && objecttochange.getAsJsonObject("key").get("name") != null) {
1969                         name = objecttochange.getAsJsonObject("key").get("name").getAsString();
1970                     } else if (objecttochange != null && objecttochange.get("policyKey") != null
1971                             && objecttochange.get("policyKey").isJsonObject()
1972                             && objecttochange.getAsJsonObject("policyKey").get("name") != null) {
1973                         name = objecttochange.getAsJsonObject("policyKey").get("name").getAsString();
1974                     }
1975                     if (objecttochange != null && objecttochange.get("key") != null
1976                             && objecttochange.get("key").isJsonObject()
1977                             && objecttochange.getAsJsonObject("key").get("version") != null) {
1978                         version = objecttochange.getAsJsonObject("key").get("version").getAsString();
1979                     } else if (objecttochange != null && objecttochange.get("policyKey") != null
1980                             && objecttochange.get("policyKey").isJsonObject()
1981                             && objecttochange.getAsJsonObject("policyKey").get("version") != null) {
1982                         version = objecttochange.getAsJsonObject("policyKey").get("version").getAsString();
1983                     }
1984                 }
1985
1986                 String uuid = null;
1987                 String desc = null;
1988
1989                 if (name != null && version != null) {
1990                     final ApexAPIResult keyInfoResult = sessionApexModel.listKeyInformation(name, version);
1991                     final List<String> keyInfoMessages = keyInfoResult.getMessages();
1992                     if (keyInfoResult.isOK() && keyInfoMessages != null && keyInfoMessages.size() > 0) {
1993                         final String keyInfoJson = keyInfoMessages.get(0);
1994                         final JsonObject keyInfoJsonObject = gson.fromJson(keyInfoJson, JsonObject.class);
1995                         if (keyInfoJsonObject != null && keyInfoJsonObject.get("apexKeyInfo") != null
1996                                 && keyInfoJsonObject.get("apexKeyInfo").getAsJsonObject().get("UUID") != null) {
1997                             uuid = keyInfoJsonObject.get("apexKeyInfo").getAsJsonObject().get("UUID").getAsString();
1998                         }
1999                         if (keyInfoJsonObject != null && keyInfoJsonObject.get("apexKeyInfo") != null
2000                                 && keyInfoJsonObject.get("apexKeyInfo").getAsJsonObject().get("description") != null) {
2001                             desc = keyInfoJsonObject.get("apexKeyInfo").getAsJsonObject().get("description")
2002                                     .getAsString();
2003                         }
2004                     }
2005                 }
2006                 objecttochange.addProperty("uuid", uuid);
2007                 objecttochange.addProperty("description", desc);
2008                 augmessages.add(gson.toJson(jsonObject));
2009             } catch (final Exception e) {
2010                 augmessages.add(message);
2011             }
2012         }
2013         ret.setMessages(augmessages);
2014
2015         if (messages.size() != augmessages.size()) {
2016             ret.setResult(RESULT.OTHER_ERROR);
2017             ret.addMessage("Failed to add KeyInfo to all results. Results are not complete");
2018         }
2019
2020         return ret;
2021     }
2022
2023     /*
2024      * This method is used only for testing and is used to cause an exception on calls from unit
2025      * test to test exception handling.
2026      */
2027     protected static int createCorruptSession() {
2028         final ApexEditorRestResource apexEditorRestResource = new ApexEditorRestResource();
2029         final ApexAPIResult result = apexEditorRestResource.createSession();
2030         final int corruptSessionId = new Integer(result.getMessages().get(0));
2031
2032         SESSIONMODELMAP.put(corruptSessionId, null);
2033
2034         return corruptSessionId;
2035     }
2036 }