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