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