48eedfa515170236af071cd8ef10fc12105374cb
[policy/drools-pdp.git] / policy-management / src / main / java / org / onap / policy / drools / server / restful / RestManager.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * policy-management
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.drools.server.restful;
22
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Properties;
29 import java.util.UUID;
30 import java.util.regex.Pattern;
31
32 import javax.ws.rs.Consumes;
33 import javax.ws.rs.DELETE;
34 import javax.ws.rs.DefaultValue;
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 import javax.ws.rs.core.Response;
44 import javax.ws.rs.core.Response.Status;
45
46 import org.onap.policy.drools.controller.DroolsController;
47 import org.onap.policy.drools.event.comm.TopicEndpoint;
48 import org.onap.policy.drools.event.comm.TopicSink;
49 import org.onap.policy.drools.event.comm.TopicSource;
50 import org.onap.policy.drools.event.comm.bus.DmaapTopicSink;
51 import org.onap.policy.drools.event.comm.bus.DmaapTopicSource;
52 import org.onap.policy.drools.event.comm.bus.NoopTopicSink;
53 import org.onap.policy.drools.event.comm.bus.UebTopicSink;
54 import org.onap.policy.drools.event.comm.bus.UebTopicSource;
55 import org.onap.policy.drools.features.PolicyControllerFeatureAPI;
56 import org.onap.policy.drools.features.PolicyEngineFeatureAPI;
57 import org.onap.policy.drools.properties.PolicyProperties;
58 import org.onap.policy.drools.protocol.coders.EventProtocolCoder;
59 import org.onap.policy.drools.protocol.coders.EventProtocolCoder.CoderFilters;
60 import org.onap.policy.drools.protocol.coders.JsonProtocolFilter;
61 import org.onap.policy.drools.protocol.coders.JsonProtocolFilter.FilterRule;
62 import org.onap.policy.drools.protocol.coders.ProtocolCoderToolset;
63 import org.onap.policy.drools.protocol.configuration.ControllerConfiguration;
64 import org.onap.policy.drools.protocol.configuration.PdpdConfiguration;
65 import org.onap.policy.drools.system.PolicyController;
66 import org.onap.policy.drools.system.PolicyEngine;
67 import org.onap.policy.drools.utils.LoggerUtil;
68 import org.slf4j.Logger;
69 import org.slf4j.LoggerFactory;
70
71 import ch.qos.logback.classic.LoggerContext;
72 import io.swagger.annotations.Api;
73 import io.swagger.annotations.ApiOperation;
74 import io.swagger.annotations.ApiParam;
75 import io.swagger.annotations.ApiResponse;
76 import io.swagger.annotations.ApiResponses;
77 import io.swagger.annotations.Info;
78 import io.swagger.annotations.SwaggerDefinition;
79 import io.swagger.annotations.Tag;
80
81
82 /**
83  * Telemetry JAX-RS Interface to the PDP-D
84  */
85
86 @Path("/policy/pdp")
87 @Produces(MediaType.APPLICATION_JSON)
88 @Consumes(MediaType.APPLICATION_JSON)
89 @Api
90 @SwaggerDefinition(
91     info = @Info(description = "PDP-D Telemetry Services", version = "v1.0",
92         title = "PDP-D Telemetry"),
93     consumes = {MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN},
94     produces = {MediaType.APPLICATION_JSON}, schemes = {SwaggerDefinition.Scheme.HTTP},
95     tags = {@Tag(name = "pdp-d-telemetry", description = "Drools PDP Telemetry Operations")})
96 public class RestManager {
97   /**
98    * Logger
99    */
100   private static Logger logger = LoggerFactory.getLogger(RestManager.class);
101
102   @GET
103   @Path("engine")
104   @ApiOperation(value = "Retrieves the Engine Operational Status",
105       notes = "Top-level abstraction.  Provides a global view of resources",
106       response = PolicyEngine.class)
107   public Response engine() {
108     return Response.status(Response.Status.OK).entity(PolicyEngine.manager).build();
109   }
110
111   @DELETE
112   @Path("engine")
113   @ApiOperation(value = "Shuts down the Engine",
114       notes = "Deleting the engine, the top-level abstraction, equivalenty shuts it down",
115       response = PolicyEngine.class)
116   public Response engineShutdown() {
117     try {
118       PolicyEngine.manager.shutdown();
119     } catch (final IllegalStateException e) {
120       logger.error("{}: cannot shutdown {} because of {}", this, PolicyEngine.manager,
121           e.getMessage(), e);
122       return Response.status(Response.Status.BAD_REQUEST).entity(PolicyEngine.manager).build();
123     }
124
125     return Response.status(Response.Status.OK).entity(PolicyEngine.manager).build();
126   }
127
128   @GET
129   @Path("engine/features")
130   @ApiOperation(value = "Engine Features",
131       notes = "Provides the list of loaded features using the PolicyEngineFeatureAPI",
132       responseContainer = "List")
133   public Response engineFeatures() {
134     return Response.status(Response.Status.OK).entity(PolicyEngine.manager.getFeatures()).build();
135   }
136
137   @GET
138   @Path("engine/features/inventory")
139   @ApiOperation(value = "Engine Detailed Feature Inventory",
140       notes = "Provides detailed list of loaded features using the PolicyEngineFeatureAPI",
141       responseContainer = "List", response = PolicyEngineFeatureAPI.class)
142   public Response engineFeaturesInventory() {
143     return Response.status(Response.Status.OK).entity(PolicyEngine.manager.getFeatureProviders())
144         .build();
145   }
146
147   @GET
148   @Path("engine/features/{featureName}")
149   @ApiOperation(value = "Engine Feature",
150       notes = "Provides Details for a given feature Engine Provider",
151       response = PolicyEngineFeatureAPI.class)
152   @ApiResponses(value = {@ApiResponse(code = 404, message = "The feature cannot be found")})
153   public Response engineFeature(@ApiParam(value = "Feature Name",
154       required = true) @PathParam("featureName") String featureName) {
155     try {
156       return Response.status(Response.Status.OK)
157           .entity(PolicyEngine.manager.getFeatureProvider(featureName)).build();
158     } catch (final IllegalArgumentException iae) {
159       logger.debug("feature unavailable: {}", featureName, iae);
160       return Response.status(Response.Status.NOT_FOUND).entity(new Error(iae.getMessage())).build();
161     }
162   }
163
164   @GET
165   @Path("engine/inputs")
166   @ApiOperation(value = "Engine Input Ports", notes = "List of input ports",
167       responseContainer = "List")
168   public Response engineInputs() {
169     return Response.status(Response.Status.OK).entity(Arrays.asList(Inputs.values())).build();
170   }
171
172   @POST
173   @Path("engine/inputs/configuration")
174   @ApiOperation(value = "Engine Input Configuration Requests",
175       notes = "Feeds a configuration request input into the Engine")
176   @ApiResponses(
177       value = {@ApiResponse(code = 406, message = "The configuration request cannot be honored")})
178   public Response engineUpdate(@ApiParam(value = "Configuration to apply",
179       required = true) PdpdConfiguration configuration) {
180     final PolicyController controller = null;
181     boolean success = true;
182     try {
183       success = PolicyEngine.manager.configure(configuration);
184     } catch (final Exception e) {
185       success = false;
186       logger.info("{}: cannot configure {} because of {}", this, PolicyEngine.manager,
187           e.getMessage(), e);
188     }
189
190     if (!success)
191       return Response.status(Response.Status.NOT_ACCEPTABLE)
192           .entity(new Error("cannot perform operation")).build();
193     else
194       return Response.status(Response.Status.OK).entity(controller).build();
195   }
196
197   @GET
198   @Path("engine/properties")
199   @ApiOperation(value = "Engine Configuration Properties",
200       notes = "Used for booststrapping the engine", response = Properties.class)
201   public Response engineProperties() {
202     return Response.status(Response.Status.OK).entity(PolicyEngine.manager.getProperties()).build();
203   }
204
205   @GET
206   @Path("engine/environment")
207   @ApiOperation(value = "Engine Environment Properties",
208       notes = "Installation and OS environment properties used by the engine",
209       response = Properties.class)
210   public Response engineEnvironment() {
211     return Response.status(Response.Status.OK).entity(PolicyEngine.manager.getEnvironment())
212         .build();
213   }
214
215   @GET
216   @Path("engine/environment/{envProperty}")
217   @Consumes(MediaType.TEXT_PLAIN)
218   @ApiOperation(value = "Gets an environment variable", response = String.class)
219   public Response engineEnvironment(@ApiParam(value = "Environment Property",
220       required = true) @PathParam("envProperty") String envProperty) {
221     return Response.status(Response.Status.OK)
222         .entity(PolicyEngine.manager.getEnvironmentProperty(envProperty)).build();
223   }
224
225   @PUT
226   @Path("engine/environment/{envProperty}")
227   @Consumes(MediaType.TEXT_PLAIN)
228   @Produces(MediaType.TEXT_PLAIN)
229   @ApiOperation(value = "Adds a new environment value to the engine", response = String.class)
230   public Response engineEnvironmentAdd(
231       @ApiParam(value = "Environment Property",
232           required = true) @PathParam("envProperty") String envProperty,
233       @ApiParam(value = "Environment Value", required = true) String envValue) {
234     final String previousValue = PolicyEngine.manager.setEnvironmentProperty(envProperty, envValue);
235     return Response.status(Response.Status.OK).entity(previousValue).build();
236   }
237
238   @GET
239   @Path("engine/switches")
240   @ApiOperation(value = "Engine Control Switches", notes = "List of the Engine Control Switches",
241       responseContainer = "List")
242   public Response engineSwitches() {
243     return Response.status(Response.Status.OK).entity(Arrays.asList(Switches.values())).build();
244   }
245
246   @PUT
247   @Path("engine/switches/activation")
248   @ApiOperation(value = "Switches on the Engine Activation Switch",
249       notes = "Turns on Activation Switch on the Engine. This order entails that the engine "
250           + "and controllers are unlocked and started",
251       response = PolicyEngine.class)
252   public Response engineActivation() {
253     boolean success = true;
254     try {
255       PolicyEngine.manager.activate();
256     } catch (final Exception e) {
257       success = false;
258       logger.info("{}: cannot activate {} because of {}", this, PolicyEngine.manager,
259           e.getMessage(), e);
260     }
261
262     if (!success)
263       return Response.status(Response.Status.NOT_ACCEPTABLE)
264           .entity(new Error("cannot perform operation")).build();
265     else
266       return Response.status(Response.Status.OK).entity(PolicyEngine.manager).build();
267   }
268
269   @DELETE
270   @Path("engine/switches/activation")
271   @ApiOperation(value = "Switches off Engine Activation Switch",
272       notes = "Turns off the Activation Switch on the Engine. This order entails that the engine "
273           + "and controllers are locked (with the exception of those resources defined as unmanaged)",
274       response = PolicyEngine.class)
275   public Response engineDeactivation() {
276     boolean success = true;
277     try {
278       PolicyEngine.manager.deactivate();
279     } catch (final Exception e) {
280       success = false;
281       logger.info("{}: cannot deactivate {} because of {}", this, PolicyEngine.manager,
282           e.getMessage(), e);
283     }
284
285     if (!success)
286       return Response.status(Response.Status.NOT_ACCEPTABLE)
287           .entity(new Error("cannot perform operation")).build();
288     else
289       return Response.status(Response.Status.OK).entity(PolicyEngine.manager).build();
290   }
291
292   @PUT
293   @Path("engine/switches/lock")
294   @ApiOperation(value = "Switches on the Engine Lock Control",
295       notes = "This switch locks all the engine resources as a whole, except those that are defined unmanaged",
296       response = PolicyEngine.class)
297   @ApiResponses(value = {
298       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
299           + "this request to be fulfilled")})
300   public Response engineLock() {
301     final boolean success = PolicyEngine.manager.lock();
302     if (success)
303       return Response.status(Status.OK).entity(PolicyEngine.manager).build();
304     else
305       return Response.status(Status.NOT_ACCEPTABLE).entity(new Error("cannot perform operation"))
306           .build();
307   }
308
309   @DELETE
310   @Path("engine/switches/lock")
311   @ApiOperation(value = "Switches off the Lock control",
312       notes = "This switch locks all the engine resources as a whole, except those that are defined unmanaged",
313       response = PolicyEngine.class)
314   @ApiResponses(value = {
315       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
316           + "this request to be fulfilled")})
317   public Response engineUnlock() {
318     final boolean success = PolicyEngine.manager.unlock();
319     if (success)
320       return Response.status(Status.OK).entity(PolicyEngine.manager).build();
321     else
322       return Response.status(Status.NOT_ACCEPTABLE).entity(new Error("cannot perform operation"))
323           .build();
324   }
325
326   @GET
327   @Path("engine/controllers")
328   @ApiOperation(value = "Lists the Policy Controllers Names",
329       notes = "Unique Policy Controller Identifiers", responseContainer = "List")
330   public Response controllers() {
331     return Response.status(Response.Status.OK).entity(PolicyEngine.manager.getPolicyControllerIds())
332         .build();
333   }
334
335   @GET
336   @Path("engine/controllers/inventory")
337   @ApiOperation(value = "Lists the Policy Controllers",
338       notes = "Detailed list of Policy Controllers", responseContainer = "List",
339       response = PolicyController.class)
340   public Response controllerInventory() {
341     return Response.status(Response.Status.OK).entity(PolicyEngine.manager.getPolicyControllers())
342         .build();
343   }
344
345   @POST
346   @Path("engine/controllers")
347   @ApiOperation(value = "Creates and starts a new Policy Controller",
348       notes = "Controller creation based on properties", response = PolicyController.class)
349   @ApiResponses(value = {
350       @ApiResponse(code = 400, message = "Invalid configuration information has been provided"),
351       @ApiResponse(code = 304, message = "The controller already exists"),
352       @ApiResponse(code = 406,
353           message = "The administrative state of the system prevents it "
354               + "from processing this request"),
355       @ApiResponse(code = 206,
356           message = "The controller has been created " + "but cannot be started"),
357       @ApiResponse(code = 201,
358           message = "The controller has been succesfully created and started")})
359   public Response controllerAdd(
360       @ApiParam(value = "Configuration Properties to apply", required = true) Properties config) {
361     if (config == null)
362       return Response.status(Response.Status.BAD_REQUEST)
363           .entity(new Error("A configuration must be provided")).build();
364
365     final String controllerName = config.getProperty(PolicyProperties.PROPERTY_CONTROLLER_NAME);
366     if (controllerName == null || controllerName.isEmpty())
367       return Response.status(Response.Status.BAD_REQUEST)
368           .entity(new Error(
369               "Configuration must have an entry for " + PolicyProperties.PROPERTY_CONTROLLER_NAME))
370           .build();
371
372     PolicyController controller;
373     try {
374       controller = PolicyController.factory.get(controllerName);
375       if (controller != null)
376         return Response.status(Response.Status.NOT_MODIFIED).entity(controller).build();
377     } catch (final IllegalArgumentException e) {
378       // This is OK
379     } catch (final IllegalStateException e) {
380       logger.info("{}: cannot get policy-controller because of {}", this, e.getMessage(), e);
381       return Response.status(Response.Status.NOT_ACCEPTABLE)
382           .entity(new Error(controllerName + " not found")).build();
383     }
384
385     try {
386       controller = PolicyEngine.manager.createPolicyController(
387           config.getProperty(PolicyProperties.PROPERTY_CONTROLLER_NAME), config);
388     } catch (IllegalArgumentException | IllegalStateException e) {
389       logger.warn("{}: cannot create policy-controller because of {}", this, e.getMessage(), e);
390       return Response.status(Response.Status.BAD_REQUEST).entity(new Error(e.getMessage())).build();
391     }
392
393     try {
394       final boolean success = controller.start();
395       if (!success) {
396         logger.info("{}: cannot start {}", this, controller);
397         return Response.status(Response.Status.PARTIAL_CONTENT)
398             .entity(new Error(controllerName + " can't be started")).build();
399       }
400     } catch (final IllegalStateException e) {
401       logger.info("{}: cannot start {} because of {}", this, controller, e.getMessage(), e);;
402       return Response.status(Response.Status.PARTIAL_CONTENT).entity(controller).build();
403     }
404
405     return Response.status(Response.Status.CREATED).entity(controller).build();
406   }
407
408   @GET
409   @Path("engine/controllers/features")
410   @ApiOperation(value = "Lists of Feature Providers Identifiers",
411       notes = "Unique Policy Controller Identifiers", responseContainer = "List")
412   public Response controllerFeatures() {
413     return Response.status(Response.Status.OK).entity(PolicyEngine.manager.getFeatures()).build();
414   }
415
416   @GET
417   @Path("engine/controllers/features/inventory")
418   @ApiOperation(value = "Detailed Controllers Feature Inventory",
419       notes = "Provides detailed list of loaded features using the PolicyControllerFeatureAPI",
420       responseContainer = "List", response = PolicyControllerFeatureAPI.class)
421   public Response controllerFeaturesInventory() {
422     return Response.status(Response.Status.OK)
423         .entity(PolicyController.factory.getFeatureProviders()).build();
424   }
425
426   @GET
427   @Path("engine/controllers/features/{featureName}")
428   @ApiOperation(value = "Controller Feature",
429       notes = "Provides Details for a given Policy Controller feature provider",
430       response = PolicyControllerFeatureAPI.class)
431   @ApiResponses(value = {@ApiResponse(code = 404, message = "The feature cannot be found")})
432   public Response controllerFeature(@ApiParam(value = "Feature Name",
433       required = true) @PathParam("featureName") String featureName) {
434     try {
435       return Response.status(Response.Status.OK)
436           .entity(PolicyController.factory.getFeatureProvider(featureName)).build();
437     } catch (final IllegalArgumentException iae) {
438       logger.debug("{}: cannot feature {} because of {}", this, featureName, iae.getMessage(), iae);
439       return Response.status(Response.Status.NOT_FOUND).entity(new Error(iae.getMessage())).build();
440     }
441   }
442
443   @GET
444   @Path("engine/controllers/{controller}")
445   @ApiOperation(value = "Retrieves a Policy Controller",
446       notes = "A Policy Controller is a concrete drools application abstraction.  "
447           + "It aggregates networking, drools, and other resources,"
448           + "as provides operational controls over drools applications",
449       response = PolicyController.class)
450   @ApiResponses(value = {@ApiResponse(code = 404, message = "The controller cannot be found"),
451       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
452           + "this request to be fulfilled")})
453   public Response controller(@ApiParam(value = "Policy Controller Name",
454       required = true) @PathParam("controller") String controllerName) {
455     try {
456       return Response.status(Response.Status.OK)
457           .entity(PolicyController.factory.get(controllerName)).build();
458     } catch (final IllegalArgumentException e) {
459       logger.debug("{}: cannot get policy-controller {} because of {}", this, controllerName,
460           e.getMessage(), e);
461       return Response.status(Response.Status.NOT_FOUND)
462           .entity(new Error(controllerName + " not found")).build();
463     } catch (final IllegalStateException e) {
464       logger.debug("{}: cannot get policy-controller {} because of {}", this, controllerName,
465           e.getMessage(), e);
466       return Response.status(Response.Status.NOT_ACCEPTABLE)
467           .entity(new Error(controllerName + " not acceptable")).build();
468     }
469   }
470
471   @DELETE
472   @Path("engine/controllers/{controller}")
473   @ApiOperation(value = "Deletes a Policy Controller",
474       notes = "A Policy Controller is a concrete drools application abstraction.  "
475           + "It aggregates networking, drools, and other resources,"
476           + "as provides operational controls over drools applications",
477       response = PolicyController.class)
478   @ApiResponses(value = {@ApiResponse(code = 404, message = "The controller cannot be found"),
479       @ApiResponse(code = 406,
480           message = "The system is an administrative state that prevents "
481               + "this request to be fulfilled"),
482       @ApiResponse(code = 500,
483           message = "A problem has occurred while deleting the Policy Controller")})
484   public Response controllerDelete(@ApiParam(value = "Policy Controller Name",
485       required = true) @PathParam("controller") String controllerName) {
486
487     PolicyController controller;
488     try {
489       controller = PolicyController.factory.get(controllerName);
490       if (controller == null)
491         return Response.status(Response.Status.BAD_REQUEST)
492             .entity(new Error(controllerName + "  does not exist")).build();
493     } catch (final IllegalArgumentException e) {
494       logger.debug("{}: cannot get policy-controller {} because of {}", this, controllerName,
495           e.getMessage(), e);
496       return Response.status(Response.Status.BAD_REQUEST)
497           .entity(new Error(controllerName + " not found: " + e.getMessage())).build();
498     } catch (final IllegalStateException e) {
499       logger.debug("{}: cannot get policy-controller {} because of {}", this, controllerName,
500           e.getMessage(), e);
501       return Response.status(Response.Status.NOT_ACCEPTABLE)
502           .entity(new Error(controllerName + " not acceptable")).build();
503     }
504
505     try {
506       PolicyEngine.manager.removePolicyController(controllerName);
507     } catch (IllegalArgumentException | IllegalStateException e) {
508       logger.debug("{}: cannot remove policy-controller {} because of {}", this, controllerName,
509           e.getMessage(), e);
510       return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
511           .entity(new Error(e.getMessage())).build();
512     }
513
514     return Response.status(Response.Status.OK).entity(controller).build();
515   }
516
517   @GET
518   @Path("engine/controllers/{controller}/properties")
519   @ApiOperation(value = "Retrieves the configuration properties of a Policy Controller",
520       notes = "Configuration resources used by the controller if Properties format",
521       response = PolicyController.class)
522   @ApiResponses(value = {@ApiResponse(code = 404, message = "The controller cannot be found"),
523       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
524           + "this request to be fulfilled")})
525   public Response controllerProperties(@ApiParam(value = "Policy Controller Name",
526       required = true) @PathParam("controller") String controllerName) {
527     try {
528       final PolicyController controller = PolicyController.factory.get(controllerName);
529       return Response.status(Response.Status.OK).entity(controller.getProperties()).build();
530     } catch (final IllegalArgumentException e) {
531       logger.debug("{}: cannot get policy-controller {} because of {}", this, controllerName,
532           e.getMessage(), e);
533       return Response.status(Response.Status.NOT_FOUND)
534           .entity(new Error(controllerName + " not found")).build();
535     } catch (final IllegalStateException e) {
536       logger.debug("{}: cannot get policy-controller {} because of {}", this, controllerName,
537           e.getMessage(), e);
538       return Response.status(Response.Status.NOT_ACCEPTABLE)
539           .entity(new Error(controllerName + " not acceptable")).build();
540     }
541   }
542
543   @GET
544   @Path("engine/controllers/{controller}/inputs")
545   @ApiOperation(value = "Policy Controller Input Ports", notes = "List of input ports",
546       responseContainer = "List")
547   public Response controllerInputs() {
548     return Response.status(Response.Status.OK).entity(Arrays.asList(Inputs.values())).build();
549   }
550
551   @POST
552   @Path("engine/controllers/{controller}/inputs/configuration")
553   @ApiOperation(value = "Policy Controller Input Configuration Requests",
554       notes = "Feeds a configuration request input into the given Policy Controller")
555   @ApiResponses(value = {@ApiResponse(code = 400, message = "The configuration request is invalid"),
556       @ApiResponse(code = 406, message = "The configuration request cannot be honored")})
557   public Response controllerUpdate(
558       @ApiParam(value = "Policy Controller Name",
559           required = true) @PathParam("controller") String controllerName,
560       @ApiParam(value = "Configuration to apply",
561           required = true) ControllerConfiguration controllerConfiguration) {
562
563     if (controllerName == null || controllerName.isEmpty() || controllerConfiguration == null
564         || controllerConfiguration.getName().intern() != controllerName)
565       return Response.status(Response.Status.BAD_REQUEST)
566           .entity("A valid or matching controller names must be provided").build();
567
568     PolicyController controller;
569     try {
570       controller = PolicyEngine.manager.updatePolicyController(controllerConfiguration);
571       if (controller == null)
572         return Response.status(Response.Status.BAD_REQUEST)
573             .entity(new Error(controllerName + "  does not exist")).build();
574     } catch (final IllegalArgumentException e) {
575       logger.info("{}: cannot update policy-controller {} because of {}", this, controllerName,
576           e.getMessage(), e);
577       return Response.status(Response.Status.BAD_REQUEST)
578           .entity(new Error(controllerName + " not found: " + e.getMessage())).build();
579     } catch (final Exception e) {
580       logger.info("{}: cannot update policy-controller {} because of {}", this, controllerName,
581           e.getMessage(), e);
582       return Response.status(Response.Status.NOT_ACCEPTABLE)
583           .entity(new Error(controllerName + " not acceptable")).build();
584     }
585
586     return Response.status(Response.Status.OK).entity(controller).build();
587   }
588
589   @GET
590   @Path("engine/controllers/{controller}/switches")
591   @ApiOperation(value = "Policy Controller Switches",
592       notes = "List of the Policy Controller Switches", responseContainer = "List")
593   public Response controllerSwitches() {
594     return Response.status(Response.Status.OK).entity(Arrays.asList(Switches.values())).build();
595   }
596
597   @PUT
598   @Path("engine/controllers/{controller}/switches/lock")
599   @ApiOperation(value = "Switches on the Policy Controller Lock Control",
600       notes = "This action on the switch locks the Policy Controller",
601       response = PolicyController.class)
602   @ApiResponses(value = {
603       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
604           + "this request to be fulfilled")})
605   public Response controllerLock(@ApiParam(value = "Policy Controller Name",
606       required = true) @PathParam("controller") String controllerName) {
607     final PolicyController policyController = PolicyController.factory.get(controllerName);
608     final boolean success = policyController.lock();
609     if (success)
610       return Response.status(Status.OK).entity(policyController).build();
611     else
612       return Response.status(Status.NOT_ACCEPTABLE)
613           .entity(new Error("Controller " + controllerName + " cannot be locked")).build();
614   }
615
616   @DELETE
617   @Path("engine/controllers/{controller}/switches/lock")
618   @ApiOperation(value = "Switches off the Policy Controller Lock Control",
619       notes = "This action on the switch unlocks the Policy Controller",
620       response = PolicyController.class)
621   @ApiResponses(value = {
622       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
623           + "this request to be fulfilled")})
624   public Response controllerUnlock(@ApiParam(value = "Policy Controller Name",
625       required = true) @PathParam("controller") String controllerName) {
626     final PolicyController policyController = PolicyController.factory.get(controllerName);
627     final boolean success = policyController.unlock();
628     if (success)
629       return Response.status(Status.OK).entity(policyController).build();
630     else
631       return Response.status(Status.NOT_ACCEPTABLE)
632           .entity(new Error("Controller " + controllerName + " cannot be unlocked")).build();
633   }
634
635   @GET
636   @Path("engine/controllers/{controller}/drools")
637   @ApiOperation(value = "Retrieves the Drools Controller subcomponent of the Policy Controller",
638       notes = "The Drools Controller provides an abstraction over the Drools subsystem",
639       response = DroolsController.class)
640   @ApiResponses(value = {@ApiResponse(code = 404, message = "The controller cannot be found"),
641       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
642           + "this request to be fulfilled")})
643   public Response drools(@ApiParam(value = "Policy Controller Name",
644       required = true) @PathParam("controller") String controllerName) {
645     try {
646       final DroolsController drools = this.getDroolsController(controllerName);
647       return Response.status(Response.Status.OK).entity(drools).build();
648     } catch (final IllegalArgumentException e) {
649       logger.debug("{}: cannot get drools-controller {} because of {}", this, controllerName,
650           e.getMessage(), e);
651       return Response.status(Response.Status.NOT_FOUND)
652           .entity(new Error(controllerName + " not found")).build();
653     } catch (final IllegalStateException e) {
654       logger.debug("{}: cannot get drools-controller {} because of {}", this, controllerName,
655           e.getMessage(), e);
656       return Response.status(Response.Status.NOT_ACCEPTABLE)
657           .entity(new Error(controllerName + " not acceptable")).build();
658     }
659   }
660
661   @GET
662   @Path("engine/controllers/{controller}/drools/facts")
663   @ApiOperation(value = "Retrieves Facts Summary information for a given controller",
664       notes = "Provides the session names, and a count of fact object in the drools working memory",
665       responseContainer = "Map")
666   @ApiResponses(value = {@ApiResponse(code = 404, message = "The controller cannot be found"),
667       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
668           + "this request to be fulfilled")})
669   public Response droolsFacts(@ApiParam(value = "Policy Controller Name",
670       required = true) @PathParam("controller") String controllerName) {
671     try {
672       final Map<String, Long> sessionCounts = new HashMap<>();
673       final DroolsController drools = this.getDroolsController(controllerName);
674       for (final String session : drools.getSessionNames()) {
675         sessionCounts.put(session, drools.factCount(session));
676       }
677       return Response.status(Response.Status.OK).entity(sessionCounts).build();
678     } catch (final IllegalArgumentException e) {
679       logger.debug("{}: cannot get policy-controller {} because of {}", this, controllerName,
680           e.getMessage(), e);
681       return Response.status(Response.Status.NOT_FOUND)
682           .entity(new Error(controllerName + " not found")).build();
683     } catch (final IllegalStateException e) {
684       logger.debug("{}: cannot get policy-controller {} because of {}", this, controllerName,
685           e.getMessage(), e);
686       return Response.status(Response.Status.NOT_ACCEPTABLE)
687           .entity(new Error(controllerName + " not acceptable")).build();
688     }
689   }
690
691   @GET
692   @Path("engine/controllers/{controller}/drools/facts/{session}")
693   @ApiOperation(value = "Retrieves Fact Types (classnames) for a given controller and its count",
694       notes = "The fact types are the classnames of the objects inserted in the drools working memory",
695       responseContainer = "Map")
696   @ApiResponses(
697       value = {@ApiResponse(code = 404, message = "The controller or session cannot be found"),
698           @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
699               + "this request to be fulfilled")})
700   public Response droolsFacts(
701       @ApiParam(value = "Policy Controller Name",
702           required = true) @PathParam("controller") String controllerName,
703       @ApiParam(value = "Drools Session Name",
704           required = true) @PathParam("session") String sessionName) {
705     try {
706       final DroolsController drools = this.getDroolsController(controllerName);
707       return Response.status(Response.Status.OK).entity(drools.factClassNames(sessionName)).build();
708     } catch (final IllegalArgumentException e) {
709       logger.debug("{}: cannot get drools-controller {} because of {}", this, controllerName,
710           e.getMessage(), e);
711       return Response.status(Response.Status.NOT_FOUND).entity(new Error("entity not found"))
712           .build();
713     } catch (final IllegalStateException e) {
714       logger.debug("{}: cannot get drools-controller {} because of {}", this, controllerName,
715           e.getMessage(), e);
716       return Response.status(Response.Status.NOT_ACCEPTABLE)
717           .entity(new Error(controllerName + ":" + sessionName + " not acceptable")).build();
718     }
719   }
720
721   @GET
722   @Path("engine/controllers/{controller}/drools/facts/{session}/{factType}")
723   @ApiOperation(
724       value = "Retrieves fact objects of a given type in the drools working memory"
725           + "for a given controller and session",
726       notes = "The fact types are the classnames of the objects inserted in the drools working memory",
727       responseContainer = "List")
728   @ApiResponses(value = {
729       @ApiResponse(code = 404, message = "The controller, session, or fact type cannot be found"),
730       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
731           + "this request to be fulfilled")})
732   public Response droolsFacts(
733       @ApiParam(value = "Fact count",
734           required = false) @DefaultValue("false") @QueryParam("count") boolean count,
735       @ApiParam(value = "Policy Controller Name",
736           required = true) @PathParam("controller") String controllerName,
737       @ApiParam(value = "Drools Session Name",
738           required = true) @PathParam("session") String sessionName,
739       @ApiParam(value = "Drools Fact Type",
740           required = true) @PathParam("factType") String factType) {
741     try {
742       final DroolsController drools = this.getDroolsController(controllerName);
743       final List<Object> facts = drools.facts(sessionName, factType, false);
744       if (!count)
745         return Response.status(Response.Status.OK).entity(facts).build();
746       else
747         return Response.status(Response.Status.OK).entity(facts.size()).build();
748     } catch (final IllegalArgumentException e) {
749       logger.debug("{}: cannot get policy-controller {} because of {}", this, controllerName,
750           e.getMessage(), e);
751       return Response.status(Response.Status.NOT_FOUND)
752           .entity(new Error(controllerName + ":" + sessionName + ":" + factType + " not found"))
753           .build();
754     } catch (final IllegalStateException e) {
755       logger.debug("{}: cannot get policy-controller {} because of {}", this, controllerName,
756           e.getMessage(), e);
757       return Response.status(Response.Status.NOT_ACCEPTABLE)
758           .entity(
759               new Error(controllerName + ":" + sessionName + ":" + factType + " not acceptable"))
760           .build();
761     }
762   }
763
764   @DELETE
765   @Path("engine/controllers/{controller}/drools/facts/{session}/{factType}")
766   @ApiOperation(
767       value = "Deletes all the fact objects of a given type from the drools working memory"
768           + "for a given controller and session.   The objects retracted from the working "
769           + "memory are provided in the response.",
770       notes = "The fact types are the classnames of the objects inserted in the drools working memory",
771       responseContainer = "List")
772   @ApiResponses(value = {
773       @ApiResponse(code = 404, message = "The controller, session, or fact type, cannot be found"),
774       @ApiResponse(code = 406,
775           message = "The system is an administrative state that prevents "
776               + "this request to be fulfilled"),
777       @ApiResponse(code = 500, message = "A server error has occurred processing this request")})
778   public Response droolsFactsDelete(
779       @ApiParam(value = "Policy Controller Name",
780           required = true) @PathParam("controller") String controllerName,
781       @ApiParam(value = "Drools Session Name",
782           required = true) @PathParam("session") String sessionName,
783       @ApiParam(value = "Drools Fact Type",
784           required = true) @PathParam("factType") String factType) {
785     try {
786       final DroolsController drools = this.getDroolsController(controllerName);
787       final List<Object> facts = drools.facts(sessionName, factType, true);
788       return Response.status(Response.Status.OK).entity(facts).build();
789     } catch (final IllegalArgumentException e) {
790       logger.debug("{}: cannot get: drools-controller {}, session {}, factType {}, because of {}",
791           this, controllerName, sessionName, factType, e.getMessage(), e);
792       return Response.status(Response.Status.NOT_FOUND)
793           .entity(new Error(controllerName + ":" + sessionName + ":" + factType + " not found"))
794           .build();
795     } catch (final IllegalStateException e) {
796       logger.debug("{}: cannot get: drools-controller {}, session {}, factType {}, because of {}",
797           this, controllerName, sessionName, factType, e.getMessage(), e);
798       return Response.status(Response.Status.NOT_ACCEPTABLE)
799           .entity(
800               new Error(controllerName + ":" + sessionName + ":" + factType + " not acceptable"))
801           .build();
802     } catch (final Exception e) {
803       logger.debug("{}: cannot get: drools-controller {}, session {}, factType {}, because of {}",
804           this, controllerName, sessionName, factType, e.getMessage(), e);
805       return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
806           .entity(new Error(e.getMessage())).build();
807     }
808   }
809
810   @GET
811   @Path("engine/controllers/{controller}/drools/facts/{session}/{query}/{queriedEntity}")
812   @ApiOperation(
813       value = "Gets all the fact objects returned by a DRL query with no parameters from the drools working memory"
814           + "for a given controller and session",
815       notes = "The DRL query must be defined in the DRL file", responseContainer = "List")
816   @ApiResponses(value = {
817       @ApiResponse(code = 404,
818           message = "The controller, session, or query information, cannot be found"),
819       @ApiResponse(code = 406,
820           message = "The system is an administrative state that prevents "
821               + "this request to be fulfilled"),
822       @ApiResponse(code = 500, message = "A server error has occurred processing this request")})
823   public Response droolsFacts(
824       @ApiParam(value = "Fact count",
825           required = false) @DefaultValue("false") @QueryParam("count") boolean count,
826       @ApiParam(value = "Policy Controller Name",
827           required = true) @PathParam("controller") String controllerName,
828       @ApiParam(value = "Drools Session Name",
829           required = true) @PathParam("session") String sessionName,
830       @ApiParam(value = "Query Name Present in DRL",
831           required = true) @PathParam("query") String queryName,
832       @ApiParam(value = "Query Identifier Present in the DRL Query",
833           required = true) @PathParam("queriedEntity") String queriedEntity) {
834     try {
835       final DroolsController drools = this.getDroolsController(controllerName);
836       final List<Object> facts = drools.factQuery(sessionName, queryName, queriedEntity, false);
837       if (!count)
838         return Response.status(Response.Status.OK).entity(facts).build();
839       else
840         return Response.status(Response.Status.OK).entity(facts.size()).build();
841     } catch (final IllegalArgumentException e) {
842       logger.debug(
843           "{}: cannot get: drools-controller {}, session {}, query {}, entity {} because of {}",
844           this, controllerName, sessionName, queryName, queriedEntity, e.getMessage(), e);
845       return Response.status(Response.Status.NOT_FOUND)
846           .entity(new Error(
847               controllerName + ":" + sessionName + ":" + queryName + queriedEntity + " not found"))
848           .build();
849     } catch (final IllegalStateException e) {
850       logger.debug(
851           "{}: cannot get: drools-controller {}, session {}, query {}, entity {} because of {}",
852           this, controllerName, sessionName, queryName, queriedEntity, e.getMessage(), e);
853       return Response.status(Response.Status.NOT_ACCEPTABLE).entity(new Error(
854           controllerName + ":" + sessionName + ":" + queryName + queriedEntity + " not acceptable"))
855           .build();
856     } catch (final Exception e) {
857       logger.debug(
858           "{}: cannot get: drools-controller {}, session {}, query {}, entity {} because of {}",
859           this, controllerName, sessionName, queryName, queriedEntity, e.getMessage(), e);
860       return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
861           .entity(new Error(e.getMessage())).build();
862     }
863   }
864
865   @POST
866   @Path("engine/controllers/{controller}/drools/facts/{session}/{query}/{queriedEntity}")
867   @ApiOperation(
868       value = "Gets all the fact objects returned by a DRL query with parameters from the drools working memory"
869           + "for a given controller and session",
870       notes = "The DRL query with parameters must be defined in the DRL file",
871       responseContainer = "List")
872   @ApiResponses(value = {
873       @ApiResponse(code = 404,
874           message = "The controller, session, or query information, cannot be found"),
875       @ApiResponse(code = 406,
876           message = "The system is an administrative state that prevents "
877               + "this request to be fulfilled"),
878       @ApiResponse(code = 500, message = "A server error has occurred processing this request")})
879   public Response droolsFacts(
880       @ApiParam(value = "Policy Controller Name",
881           required = true) @PathParam("controller") String controllerName,
882       @ApiParam(value = "Drools Session Name",
883           required = true) @PathParam("session") String sessionName,
884       @ApiParam(value = "Query Name Present in DRL",
885           required = true) @PathParam("query") String queryName,
886       @ApiParam(value = "Query Identifier Present in the DRL Query",
887           required = true) @PathParam("queriedEntity") String queriedEntity,
888       @ApiParam(value = "Query Parameter Values to pass in the DRL Query",
889           required = false) List<Object> queryParameters) {
890     try {
891       final DroolsController drools = this.getDroolsController(controllerName);
892       List<Object> facts;
893       if (queryParameters == null || queryParameters.isEmpty())
894         facts = drools.factQuery(sessionName, queryName, queriedEntity, false);
895       else
896         facts = drools.factQuery(sessionName, queryName, queriedEntity, false,
897             queryParameters.toArray());
898       return Response.status(Response.Status.OK).entity(facts).build();
899     } catch (final IllegalArgumentException e) {
900       logger.debug(
901           "{}: cannot get: drools-controller {}, session {}, query {}, entity {}, params {} because of {}",
902           this, controllerName, sessionName, queryName, queriedEntity, queryParameters,
903           e.getMessage(), e);
904       return Response.status(Response.Status.NOT_FOUND)
905           .entity(new Error(
906               controllerName + ":" + sessionName + ":" + queryName + queriedEntity + " not found"))
907           .build();
908     } catch (final IllegalStateException e) {
909       logger.debug(
910           "{}: cannot get: drools-controller {}, session {}, query {}, entity {}, params {} because of {}",
911           this, controllerName, sessionName, queryName, queriedEntity, queryParameters,
912           e.getMessage(), e);
913       return Response.status(Response.Status.NOT_ACCEPTABLE).entity(new Error(
914           controllerName + ":" + sessionName + ":" + queryName + queriedEntity + " not acceptable"))
915           .build();
916     } catch (final Exception e) {
917       logger.debug(
918           "{}: cannot get: drools-controller {}, session {}, query {}, entity {}, params {} because of {}",
919           this, controllerName, sessionName, queryName, queriedEntity, queryParameters,
920           e.getMessage(), e);
921       return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
922           .entity(new Error(e.getMessage())).build();
923     }
924   }
925
926   @DELETE
927   @Path("engine/controllers/{controller}/drools/facts/{session}/{query}/{queriedEntity}")
928   @ApiOperation(
929       value = "Deletes all the fact objects returned by a DRL query with parameters from the drools working memory"
930           + "for a given controller and session",
931       notes = "The DRL query with parameters must be defined in the DRL file",
932       responseContainer = "List")
933   @ApiResponses(value = {
934       @ApiResponse(code = 404,
935           message = "The controller, session, or query information, cannot be found"),
936       @ApiResponse(code = 406,
937           message = "The system is an administrative state that prevents "
938               + "this request to be fulfilled"),
939       @ApiResponse(code = 500, message = "A server error has occurred processing this request")})
940   public Response droolsFactsDelete(
941       @ApiParam(value = "Policy Controller Name",
942           required = true) @PathParam("controller") String controllerName,
943       @ApiParam(value = "Drools Session Name",
944           required = true) @PathParam("session") String sessionName,
945       @ApiParam(value = "Query Name Present in DRL",
946           required = true) @PathParam("query") String queryName,
947       @ApiParam(value = "Query Identifier Present in the DRL Query",
948           required = true) @PathParam("queriedEntity") String queriedEntity,
949       @ApiParam(value = "Query Parameter Values to pass in the DRL Query",
950           required = false) List<Object> queryParameters) {
951     try {
952       final DroolsController drools = this.getDroolsController(controllerName);
953       List<Object> facts;
954       if (queryParameters == null || queryParameters.isEmpty())
955         facts = drools.factQuery(sessionName, queryName, queriedEntity, true);
956       else
957         facts = drools.factQuery(sessionName, queryName, queriedEntity, true,
958             queryParameters.toArray());
959       return Response.status(Response.Status.OK).entity(facts).build();
960     } catch (final IllegalArgumentException e) {
961       logger.debug(
962           "{}: cannot get: drools-controller {}, session {}, query {}, entity {}, params {} because of {}",
963           this, controllerName, sessionName, queryName, queriedEntity, queryParameters,
964           e.getMessage(), e);
965       return Response.status(Response.Status.NOT_FOUND)
966           .entity(new Error(
967               controllerName + ":" + sessionName + ":" + queryName + queriedEntity + " not found"))
968           .build();
969     } catch (final IllegalStateException e) {
970       logger.debug(
971           "{}: cannot get: drools-controller {}, session {}, query {}, entity {}, params {} because of {}",
972           this, controllerName, sessionName, queryName, queriedEntity, queryParameters,
973           e.getMessage(), e);
974       return Response.status(Response.Status.NOT_ACCEPTABLE).entity(new Error(
975           controllerName + ":" + sessionName + ":" + queryName + queriedEntity + " not acceptable"))
976           .build();
977     } catch (final Exception e) {
978       logger.debug(
979           "{}: cannot get: drools-controller {}, session {}, query {}, entity {}, params {} because of {}",
980           this, controllerName, sessionName, queryName, queriedEntity, queryParameters,
981           e.getMessage(), e);
982       return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
983           .entity(new Error(e.getMessage())).build();
984     }
985   }
986
987   @POST
988   @Path("engine/controllers/tools/coders/decoders/filters/rules/{ruleName}")
989   @ApiOperation(
990       value = "Produces a Decoder Rule Filter in a format that the Policy Controller can understand",
991       notes = "The result can be used with other APIs to attach a filter to a decoder")
992   public Response rules(
993       @ApiParam(value = "Negate regex?",
994           required = true) @DefaultValue("false") @QueryParam("negate") boolean negate,
995       @ApiParam(value = "Rule Name", required = true) @PathParam("ruleName") String name,
996       @ApiParam(value = "Regex expression", required = true) String regex) {
997     String literalRegex = Pattern.quote(regex);
998     if (negate)
999       literalRegex = "^(?!" + literalRegex + "$).*";
1000
1001     return Response.status(Status.OK).entity(new JsonProtocolFilter.FilterRule(name, literalRegex))
1002         .build();
1003   }
1004
1005   @GET
1006   @Path("engine/controllers/{controller}/decoders")
1007   @ApiOperation(value = "Gets all the decoders used by a controller",
1008       notes = "A Policy Controller uses decoders to deserialize incoming network messages from "
1009           + "subscribed network topics into specific (fact) objects. "
1010           + "The deserialized (fact) object will typically be inserted in the drools working "
1011           + " memory of the controlled drools application.",
1012       responseContainer = "List", response = ProtocolCoderToolset.class)
1013   @ApiResponses(value = {@ApiResponse(code = 404, message = "The controller cannot be found"),
1014       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1015           + "this request to be fulfilled")})
1016   public Response decoders(@ApiParam(value = "Policy Controller Name",
1017       required = true) @PathParam("controller") String controllerName) {
1018     try {
1019       final DroolsController drools = this.getDroolsController(controllerName);
1020       final List<ProtocolCoderToolset> decoders =
1021           EventProtocolCoder.manager.getDecoders(drools.getGroupId(), drools.getArtifactId());
1022       return Response.status(Response.Status.OK).entity(decoders).build();
1023     } catch (final IllegalArgumentException e) {
1024       logger.debug("{}: cannot get decoders for policy-controller {} because of {}", this,
1025           controllerName, e.getMessage(), e);
1026       return Response.status(Response.Status.NOT_FOUND)
1027           .entity(new Error(controllerName + " not found")).build();
1028     } catch (final IllegalStateException e) {
1029       logger.debug("{}: cannot get decoders for policy-controller {} because of {}", this,
1030           controllerName, e.getMessage(), e);
1031       return Response.status(Response.Status.NOT_ACCEPTABLE)
1032           .entity(new Error(controllerName + " not acceptable")).build();
1033     }
1034   }
1035
1036   @GET
1037   @Path("engine/controllers/{controller}/decoders/filters")
1038   @ApiOperation(value = "Gets all the filters used by a controller",
1039       notes = "A Policy Controller uses decoders to deserialize incoming network messages from "
1040           + "subscribed network topics into specific (fact) objects. "
1041           + "The deserialized (fact) object will typically be inserted in the drools working "
1042           + " memory of the controlled drools application."
1043           + "Acceptance filters are used to filter out undesired network messages for the given controller",
1044       responseContainer = "List", response = CoderFilters.class)
1045   @ApiResponses(value = {@ApiResponse(code = 404, message = "The controller cannot be found"),
1046       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1047           + "this request to be fulfilled")})
1048   public Response decoderFilters(@ApiParam(value = "Policy Controller Name",
1049       required = true) @PathParam("controller") String controllerName) {
1050     try {
1051       final DroolsController drools = this.getDroolsController(controllerName);
1052       final List<CoderFilters> filters =
1053           EventProtocolCoder.manager.getDecoderFilters(drools.getGroupId(), drools.getArtifactId());
1054       return Response.status(Response.Status.OK).entity(filters).build();
1055     } catch (final IllegalArgumentException e) {
1056       logger.debug("{}: cannot get decoders for policy-controller {} because of {}", this,
1057           controllerName, e.getMessage(), e);
1058       return Response.status(Response.Status.NOT_FOUND)
1059           .entity(new Error(controllerName + " not found")).build();
1060     } catch (final IllegalStateException e) {
1061       logger.debug("{}: cannot get decoders for policy-controller {} because of {}", this,
1062           controllerName, e.getMessage(), e);
1063       return Response.status(Response.Status.NOT_ACCEPTABLE)
1064           .entity(new Error(controllerName + " not acceptable")).build();
1065     }
1066   }
1067
1068   @GET
1069   @Path("engine/controllers/{controller}/decoders/{topic}")
1070   @ApiOperation(value = "Gets all the decoders in use by a controller for a networked topic",
1071       notes = "A Policy Controller uses decoders to deserialize incoming network messages from "
1072           + "subscribed network topics into specific (fact) objects. "
1073           + "The deserialized (fact) object will typically be inserted in the drools working "
1074           + " memory of the controlled drools application.",
1075       responseContainer = "List", response = ProtocolCoderToolset.class)
1076   @ApiResponses(
1077       value = {@ApiResponse(code = 404, message = "The controller or topic cannot be found"),
1078           @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1079               + "this request to be fulfilled")})
1080   public Response decoder(
1081       @ApiParam(value = "Policy Controller Name",
1082           required = true) @PathParam("controller") String controllerName,
1083       @ApiParam(value = "Networked Topic Name", required = true) @PathParam("topic") String topic) {
1084     try {
1085       final DroolsController drools = this.getDroolsController(controllerName);
1086       final ProtocolCoderToolset decoder = EventProtocolCoder.manager
1087           .getDecoders(drools.getGroupId(), drools.getArtifactId(), topic);
1088       return Response.status(Response.Status.OK).entity(decoder).build();
1089     } catch (final IllegalArgumentException e) {
1090       logger.debug("{}: cannot get decoders for policy-controller {} topic {} because of {}", this,
1091           controllerName, topic, e.getMessage(), e);
1092       return Response.status(Response.Status.NOT_FOUND)
1093           .entity(new Error(controllerName + ":" + topic + " not found")).build();
1094     } catch (final IllegalStateException e) {
1095       logger.debug("{}: cannot get decoders for policy-controller {} topic {} because of {}", this,
1096           controllerName, topic, e.getMessage(), e);
1097       return Response.status(Response.Status.NOT_ACCEPTABLE)
1098           .entity(new Error(controllerName + ":" + topic + " not acceptable")).build();
1099     }
1100   }
1101
1102   @GET
1103   @Path("engine/controllers/{controller}/decoders/{topic}/filters")
1104   @ApiOperation(
1105       value = "Gets all filters attached to decoders for a given networked topic in use by a controller",
1106       notes = "A Policy Controller uses decoders to deserialize incoming network messages from "
1107           + "subscribed network topics into specific (fact) objects. "
1108           + "The deserialized (fact) object will typically be inserted in the drools working "
1109           + " memory of the controlled drools application."
1110           + "Acceptance filters are used to filter out undesired network messages for the given controller",
1111       responseContainer = "List", response = CoderFilters.class)
1112   @ApiResponses(
1113       value = {@ApiResponse(code = 404, message = "The controller or topic cannot be found"),
1114           @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1115               + "this request to be fulfilled")})
1116   public Response decoderFilter(
1117       @ApiParam(value = "Policy Controller Name",
1118           required = true) @PathParam("controller") String controllerName,
1119       @ApiParam(value = "Networked Topic Name", required = true) @PathParam("topic") String topic) {
1120     try {
1121       final DroolsController drools = this.getDroolsController(controllerName);
1122       final ProtocolCoderToolset decoder = EventProtocolCoder.manager
1123           .getDecoders(drools.getGroupId(), drools.getArtifactId(), topic);
1124       if (decoder == null)
1125         return Response.status(Response.Status.BAD_REQUEST)
1126             .entity(new Error(topic + "  does not exist")).build();
1127       else
1128         return Response.status(Response.Status.OK).entity(decoder.getCoders()).build();
1129     } catch (final IllegalArgumentException e) {
1130       logger.debug("{}: cannot get decoders for policy-controller {} topic {} because of {}", this,
1131           controllerName, topic, e.getMessage(), e);
1132       return Response.status(Response.Status.NOT_FOUND)
1133           .entity(new Error(controllerName + ":" + topic + " not found")).build();
1134     } catch (final IllegalStateException e) {
1135       logger.debug("{}: cannot get decoders for policy-controller {} topic {} because of {}", this,
1136           controllerName, topic, e.getMessage(), e);
1137       return Response.status(Response.Status.NOT_ACCEPTABLE)
1138           .entity(new Error(controllerName + ":" + topic + " not acceptable")).build();
1139     }
1140   }
1141
1142   @GET
1143   @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}")
1144   @ApiOperation(
1145       value = "Gets all filters attached to decoders for a given subscribed networked topic "
1146           + "and fact type",
1147       notes = "Decoders are associated with networked topics. A Policy Controller manages "
1148           + "multiple topics and therefore its attached decoders. "
1149           + "A Policy Controller uses filters to further specify the fact mapping.  "
1150           + "Filters are applied on a per fact type (classname).",
1151       responseContainer = "List", response = CoderFilters.class)
1152   @ApiResponses(value = {
1153       @ApiResponse(code = 404, message = "The controller, topic, or fact type cannot be found"),
1154       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1155           + "this request to be fulfilled")})
1156   public Response decoderFilter(
1157       @ApiParam(value = "Policy Controller Name",
1158           required = true) @PathParam("controller") String controllerName,
1159       @ApiParam(value = "Networked Topic Name", required = true) @PathParam("topic") String topic,
1160       @ApiParam(value = "Fact Type", required = true) @PathParam("factType") String factClass) {
1161     try {
1162       final DroolsController drools = this.getDroolsController(controllerName);
1163       final ProtocolCoderToolset decoder = EventProtocolCoder.manager
1164           .getDecoders(drools.getGroupId(), drools.getArtifactId(), topic);
1165       final CoderFilters filters = decoder.getCoder(factClass);
1166       if (filters == null)
1167         return Response.status(Response.Status.BAD_REQUEST)
1168             .entity(new Error(topic + ":" + factClass + "  does not exist")).build();
1169       else
1170         return Response.status(Response.Status.OK).entity(filters).build();
1171     } catch (final IllegalArgumentException e) {
1172       logger.debug(
1173           "{}: cannot get decoder filters for policy-controller {} topic {} type {} because of {}",
1174           this, controllerName, topic, factClass, e.getMessage(), e);
1175       return Response.status(Response.Status.NOT_FOUND)
1176           .entity(new Error(controllerName + ":" + topic + ":" + factClass + " not found")).build();
1177     } catch (final IllegalStateException e) {
1178       logger.debug(
1179           "{}: cannot get decoder filters for policy-controller {} topic {} type {} because of {}",
1180           this, controllerName, topic, factClass, e.getMessage(), e);
1181       return Response.status(Response.Status.NOT_ACCEPTABLE)
1182           .entity(new Error(controllerName + ":" + topic + ":" + factClass + " not acceptable"))
1183           .build();
1184     }
1185   }
1186
1187   @PUT
1188   @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}")
1189   @ApiOperation(
1190       value = "Attaches filters to the decoder for a given networked topic " + "and fact type",
1191       notes = "Decoders are associated with networked topics. A Policy Controller manages "
1192           + "multiple topics and therefore its attached decoders. "
1193           + "A Policy Controller uses filters to further specify the fact mapping.  "
1194           + "Filters are applied on a per fact type (classname).",
1195       responseContainer = "List", response = CoderFilters.class)
1196   @ApiResponses(value = {
1197       @ApiResponse(code = 404,
1198           message = "The controller, topic, fact type, cannot be found, "
1199               + "or a filter has not been provided"),
1200       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1201           + "this request to be fulfilled")})
1202   public Response decoderFilter(
1203       @ApiParam(value = "Policy Controller Name",
1204           required = true) @PathParam("controller") String controllerName,
1205       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic,
1206       @ApiParam(value = "Fact Type", required = true) @PathParam("factType") String factClass,
1207       @ApiParam(value = "Configuration Filter", required = true) JsonProtocolFilter configFilters) {
1208
1209     if (configFilters == null) {
1210       return Response.status(Response.Status.BAD_REQUEST)
1211           .entity(new Error("Configuration Filters not provided")).build();
1212     }
1213
1214     try {
1215       final DroolsController drools = this.getDroolsController(controllerName);
1216       final ProtocolCoderToolset decoder = EventProtocolCoder.manager
1217           .getDecoders(drools.getGroupId(), drools.getArtifactId(), topic);
1218       final CoderFilters filters = decoder.getCoder(factClass);
1219       if (filters == null)
1220         return Response.status(Response.Status.BAD_REQUEST)
1221             .entity(new Error(topic + ":" + factClass + "  does not exist")).build();
1222       filters.setFilter(configFilters);
1223       return Response.status(Response.Status.OK).entity(filters).build();
1224     } catch (final IllegalArgumentException e) {
1225       logger.debug(
1226           "{}: cannot get decoder filters for policy-controller {} topic {} type {} filters {} because of {}",
1227           this, controllerName, topic, factClass, configFilters, e.getMessage(), e);
1228       return Response.status(Response.Status.NOT_FOUND)
1229           .entity(new Error(controllerName + ":" + topic + ":" + factClass + " not found")).build();
1230     } catch (final IllegalStateException e) {
1231       logger.debug(
1232           "{}: cannot get decoder filters for policy-controller {} topic {} type {} filters {} because of {}",
1233           this, controllerName, topic, factClass, configFilters, e.getMessage(), e);
1234       return Response.status(Response.Status.NOT_ACCEPTABLE)
1235           .entity(new Error(controllerName + ":" + topic + ":" + factClass + " not acceptable"))
1236           .build();
1237     }
1238   }
1239
1240   @GET
1241   @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}/rules")
1242   @ApiOperation(value = "Gets the filter rules attached to a topic decoder of a controller",
1243       notes = "Decoders are associated with networked topics. A Policy Controller manages "
1244           + "multiple topics and therefore its attached decoders. "
1245           + "A Policy Controller uses filters to further specify the fact mapping.  "
1246           + "Filters are applied on a per fact type and are composed of field matching rules. ",
1247       responseContainer = "List", response = FilterRule.class)
1248   @ApiResponses(value = {
1249       @ApiResponse(code = 404, message = "The controller, topic, or fact type cannot be found"),
1250       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1251           + "this request to be fulfilled")})
1252   public Response decoderFilterRules(
1253       @ApiParam(value = "Policy Controller Name",
1254           required = true) @PathParam("controller") String controllerName,
1255       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic,
1256       @ApiParam(value = "Fact Type", required = true) @PathParam("factType") String factClass) {
1257     try {
1258       final DroolsController drools = this.getDroolsController(controllerName);
1259       final ProtocolCoderToolset decoder = EventProtocolCoder.manager
1260           .getDecoders(drools.getGroupId(), drools.getArtifactId(), topic);
1261
1262       final CoderFilters filters = decoder.getCoder(factClass);
1263       if (filters == null)
1264         return Response.status(Response.Status.BAD_REQUEST)
1265             .entity(new Error(controllerName + ":" + topic + ":" + factClass + "  does not exist"))
1266             .build();
1267
1268       final JsonProtocolFilter filter = filters.getFilter();
1269       if (filter == null)
1270         return Response.status(Response.Status.BAD_REQUEST)
1271             .entity(new Error(controllerName + ":" + topic + ":" + factClass + "  no filters"))
1272             .build();
1273
1274       return Response.status(Response.Status.OK).entity(filter.getRules()).build();
1275     } catch (final IllegalArgumentException e) {
1276       logger.debug(
1277           "{}: cannot get decoder filters for policy-controller {} topic {} type {} because of {}",
1278           this, controllerName, topic, factClass, e.getMessage(), e);
1279       return Response.status(Response.Status.NOT_FOUND)
1280           .entity(new Error(controllerName + ":" + topic + ":" + factClass + " not found")).build();
1281     } catch (final IllegalStateException e) {
1282       logger.debug(
1283           "{}: cannot get decoder filters for policy-controller {} topic {} type {} because of {}",
1284           this, controllerName, topic, factClass, e.getMessage(), e);
1285       return Response.status(Response.Status.NOT_ACCEPTABLE)
1286           .entity(new Error(controllerName + ":" + topic + ":" + factClass + " not acceptable"))
1287           .build();
1288     }
1289   }
1290
1291   @GET
1292   @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}/rules/{ruleName}")
1293   @ApiOperation(value = "Gets a filter rule by name attached to a topic decoder of a controller",
1294       notes = "Decoders are associated with networked topics. A Policy Controller manages "
1295           + "multiple topics and therefore its attached decoders. "
1296           + "A Policy Controller uses filters to further specify the fact mapping.  "
1297           + "Filters are applied on a per fact type and are composed of field matching rules. ",
1298       responseContainer = "List", response = FilterRule.class)
1299   @ApiResponses(value = {
1300       @ApiResponse(code = 404,
1301           message = "The controller, topic, fact type, or rule name cannot be found"),
1302       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1303           + "this request to be fulfilled")})
1304   public Response decoderFilterRules(
1305       @ApiParam(value = "Policy Controller Name",
1306           required = true) @PathParam("controller") String controllerName,
1307       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic,
1308       @ApiParam(value = "Fact Type", required = true) @PathParam("factType") String factClass,
1309       @ApiParam(value = "Rule Name", required = true) @PathParam("ruleName") String ruleName) {
1310     try {
1311       final DroolsController drools = this.getDroolsController(controllerName);
1312       final ProtocolCoderToolset decoder = EventProtocolCoder.manager
1313           .getDecoders(drools.getGroupId(), drools.getArtifactId(), topic);
1314
1315       final CoderFilters filters = decoder.getCoder(factClass);
1316       if (filters == null)
1317         return Response.status(Response.Status.BAD_REQUEST)
1318             .entity(new Error(controllerName + ":" + topic + ":" + factClass + "  does not exist"))
1319             .build();
1320
1321       final JsonProtocolFilter filter = filters.getFilter();
1322       if (filter == null)
1323         return Response.status(Response.Status.BAD_REQUEST)
1324             .entity(new Error(controllerName + ":" + topic + ":" + factClass + "  no filters"))
1325             .build();
1326
1327       return Response.status(Response.Status.OK).entity(filter.getRules(ruleName)).build();
1328     } catch (final IllegalArgumentException e) {
1329       logger.debug(
1330           "{}: cannot get decoder filters for policy-controller {} topic {} type {} rule {} because of {}",
1331           this, controllerName, topic, factClass, ruleName, e.getMessage(), e);
1332       return Response.status(Response.Status.NOT_FOUND)
1333           .entity(new Error(
1334               controllerName + ":" + topic + ":" + factClass + ": " + ruleName + " not found"))
1335           .build();
1336     } catch (final IllegalStateException e) {
1337       logger.debug(
1338           "{}: cannot get decoder filters for policy-controller {} topic {} type {} rule {} because of {}",
1339           this, controllerName, topic, factClass, ruleName, e.getMessage(), e);
1340       return Response.status(Response.Status.NOT_ACCEPTABLE)
1341           .entity(new Error(
1342               controllerName + ":" + topic + ":" + factClass + ":" + ruleName + " not acceptable"))
1343           .build();
1344     }
1345   }
1346
1347   @DELETE
1348   @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}/rules/{ruleName}")
1349   @ApiOperation(value = "Deletes a filter rule by name attached to a topic decoder of a controller",
1350       notes = "Decoders are associated with networked topics. A Policy Controller manages "
1351           + "multiple topics and therefore its attached decoders. "
1352           + "A Policy Controller uses filters to further specify the fact mapping.  "
1353           + "Filters are applied on a per fact type and are composed of field matching rules. ",
1354       responseContainer = "List", response = FilterRule.class)
1355   @ApiResponses(value = {
1356       @ApiResponse(code = 404,
1357           message = "The controller, topic, fact type, or rule name cannot be found"),
1358       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1359           + "this request to be fulfilled")})
1360   public Response decoderFilterRuleDelete(
1361       @ApiParam(value = "Policy Controller Name",
1362           required = true) @PathParam("controller") String controllerName,
1363       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic,
1364       @ApiParam(value = "Fact Type", required = true) @PathParam("factType") String factClass,
1365       @ApiParam(value = "Rule Name", required = true) @PathParam("ruleName") String ruleName,
1366       @ApiParam(value = "Filter Rule", required = true) FilterRule rule) {
1367
1368     try {
1369       final DroolsController drools = this.getDroolsController(controllerName);
1370       final ProtocolCoderToolset decoder = EventProtocolCoder.manager
1371           .getDecoders(drools.getGroupId(), drools.getArtifactId(), topic);
1372
1373       final CoderFilters filters = decoder.getCoder(factClass);
1374       if (filters == null)
1375         return Response.status(Response.Status.BAD_REQUEST)
1376             .entity(new Error(controllerName + ":" + topic + ":" + factClass + "  does not exist"))
1377             .build();
1378
1379       final JsonProtocolFilter filter = filters.getFilter();
1380       if (filter == null)
1381         return Response.status(Response.Status.BAD_REQUEST)
1382             .entity(new Error(controllerName + ":" + topic + ":" + factClass + "  no filters"))
1383             .build();
1384
1385       if (rule == null) {
1386         filter.deleteRules(ruleName);
1387         return Response.status(Response.Status.OK).entity(filter.getRules()).build();
1388       }
1389
1390       if (rule.getName() == null || !rule.getName().equals(ruleName))
1391         return Response.status(Response.Status.BAD_REQUEST)
1392             .entity(new Error(controllerName + ":" + topic + ":" + factClass + ":" + ruleName
1393                 + " rule name request inconsistencies (" + rule.getName() + ")"))
1394             .build();
1395
1396       filter.deleteRule(ruleName, rule.getRegex());
1397       return Response.status(Response.Status.OK).entity(filter.getRules()).build();
1398     } catch (final IllegalArgumentException e) {
1399       logger.debug(
1400           "{}: cannot get decoder filters for policy-controller {} topic {} type {} rule {} because of {}",
1401           this, controllerName, topic, factClass, ruleName, e.getMessage(), e);
1402       return Response.status(Response.Status.NOT_FOUND)
1403           .entity(new Error(
1404               controllerName + ":" + topic + ":" + factClass + ": " + ruleName + " not found"))
1405           .build();
1406     } catch (final IllegalStateException e) {
1407       logger.debug(
1408           "{}: cannot get decoder filters for policy-controller {} topic {} type {} rule {} because of {}",
1409           this, controllerName, topic, factClass, ruleName, e.getMessage(), e);
1410       return Response.status(Response.Status.NOT_ACCEPTABLE)
1411           .entity(new Error(
1412               controllerName + ":" + topic + ":" + factClass + ":" + ruleName + " not acceptable"))
1413           .build();
1414     }
1415   }
1416
1417   @PUT
1418   @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}/rules")
1419   @ApiOperation(value = "Places a new filter rule in a topic decoder",
1420       notes = "Decoders are associated with networked topics. A Policy Controller manages "
1421           + "multiple topics and therefore its attached decoders. "
1422           + "A Policy Controller uses filters to further specify the fact mapping.  "
1423           + "Filters are applied on a per fact type and are composed of field matching rules. ",
1424       responseContainer = "List", response = FilterRule.class)
1425   @ApiResponses(value = {
1426       @ApiResponse(code = 404, message = "The controller, topic, or fact type cannot be found"),
1427       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1428           + "this request to be fulfilled")})
1429   public Response decoderFilterRule(
1430       @ApiParam(value = "Policy Controller Name",
1431           required = true) @PathParam("controller") String controllerName,
1432       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic,
1433       @ApiParam(value = "Fact Type", required = true) @PathParam("factType") String factClass,
1434       @ApiParam(value = "Rule Name", required = true) @PathParam("ruleName") String ruleName,
1435       @ApiParam(value = "Filter Rule", required = true) FilterRule rule) {
1436
1437     try {
1438       final DroolsController drools = this.getDroolsController(controllerName);
1439       final ProtocolCoderToolset decoder = EventProtocolCoder.manager
1440           .getDecoders(drools.getGroupId(), drools.getArtifactId(), topic);
1441
1442       final CoderFilters filters = decoder.getCoder(factClass);
1443       if (filters == null)
1444         return Response.status(Response.Status.BAD_REQUEST)
1445             .entity(new Error(controllerName + ":" + topic + ":" + factClass + "  does not exist"))
1446             .build();
1447
1448       final JsonProtocolFilter filter = filters.getFilter();
1449       if (filter == null)
1450         return Response.status(Response.Status.BAD_REQUEST)
1451             .entity(new Error(controllerName + ":" + topic + ":" + factClass + "  no filters"))
1452             .build();
1453
1454       if (rule.getName() == null)
1455         return Response
1456             .status(Response.Status.BAD_REQUEST).entity(new Error(controllerName + ":" + topic + ":"
1457                 + factClass + " rule name request inconsistencies (" + rule.getName() + ")"))
1458             .build();
1459
1460       filter.addRule(rule.getName(), rule.getRegex());
1461       return Response.status(Response.Status.OK).entity(filter.getRules()).build();
1462     } catch (final IllegalArgumentException e) {
1463       logger.debug(
1464           "{}: cannot access decoder filter rules for policy-controller {} topic {} type {} rule {} because of {}",
1465           this, controllerName, topic, factClass, ruleName, e.getMessage(), e);
1466       return Response.status(Response.Status.NOT_FOUND)
1467           .entity(new Error(controllerName + ":" + topic + ":" + factClass + " not found")).build();
1468     } catch (final IllegalStateException e) {
1469       logger.debug(
1470           "{}: cannot access decoder filter rules for policy-controller {} topic {} type {} rule {} because of {}",
1471           this, controllerName, topic, factClass, ruleName, e.getMessage(), e);
1472       return Response.status(Response.Status.NOT_ACCEPTABLE)
1473           .entity(new Error(controllerName + ":" + topic + ":" + factClass + " not acceptable"))
1474           .build();
1475     }
1476   }
1477
1478   @POST
1479   @Path("engine/controllers/{controller}/decoders/{topic}")
1480   @Consumes(MediaType.TEXT_PLAIN)
1481   @ApiOperation(value = "Decodes a string into a fact object, and encodes it back into a string",
1482       notes = "Tests the decode/encode functions of a controller", response = CodingResult.class)
1483   @ApiResponses(value = {@ApiResponse(code = 400, message = "Bad input has been provided"),
1484       @ApiResponse(code = 404, message = "The controller cannot be found"),
1485       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1486           + "this request to be fulfilled")})
1487   public Response decode(
1488       @ApiParam(value = "Policy Controller Name",
1489           required = true) @PathParam("controller") String controllerName,
1490       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic,
1491       @ApiParam(value = "JSON String to decode", required = true) String json) {
1492
1493     PolicyController policyController;
1494     try {
1495       policyController = PolicyController.factory.get(controllerName);
1496     } catch (final IllegalArgumentException e) {
1497       logger.debug("{}: cannot get decoders for policy-controller {} topic {} because of {}", this,
1498           controllerName, topic, e.getMessage(), e);
1499       return Response.status(Response.Status.NOT_FOUND)
1500           .entity(new Error(controllerName + ":" + topic + ":" + " not found")).build();
1501     } catch (final IllegalStateException e) {
1502       logger.debug("{}: cannot get decoders for policy-controller {} topic {} because of {}", this,
1503           controllerName, topic, e.getMessage(), e);
1504       return Response.status(Response.Status.NOT_ACCEPTABLE)
1505           .entity(new Error(controllerName + ":" + topic + ":" + " not acceptable")).build();
1506     }
1507
1508     final CodingResult result = new CodingResult();
1509     result.decoding = false;
1510     result.encoding = false;
1511     result.jsonEncoding = null;
1512
1513     Object event;
1514     try {
1515       event = EventProtocolCoder.manager.decode(policyController.getDrools().getGroupId(),
1516           policyController.getDrools().getArtifactId(), topic, json);
1517       result.decoding = true;
1518     } catch (final Exception e) {
1519       logger.debug("{}: cannot get policy-controller {} topic {} because of {}", this,
1520           controllerName, topic, e.getMessage(), e);
1521       return Response.status(Response.Status.BAD_REQUEST).entity(new Error(e.getMessage())).build();
1522     }
1523
1524     try {
1525       result.jsonEncoding = EventProtocolCoder.manager.encode(topic, event);
1526       result.encoding = true;
1527     } catch (final Exception e) {
1528       // continue so to propagate decoding results ..
1529       logger.debug("{}: cannot encode for policy-controller {} topic {} because of {}", this,
1530           controllerName, topic, e.getMessage(), e);
1531     }
1532
1533     return Response.status(Response.Status.OK).entity(result).build();
1534   }
1535
1536   @GET
1537   @Path("engine/controllers/{controller}/encoders")
1538   @ApiOperation(value = "Retrieves the encoder filters of a controller",
1539       notes = "The encoders serializes a fact object, typically for network transmission",
1540       responseContainer = "List", response = CoderFilters.class)
1541   @ApiResponses(value = {@ApiResponse(code = 400, message = "Bad input has been provided"),
1542       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1543           + "this request to be fulfilled")})
1544   public Response encoderFilters(@ApiParam(value = "Policy Controller Name",
1545       required = true) @PathParam("controller") String controllerName) {
1546     List<CoderFilters> encoders;
1547     try {
1548       final PolicyController controller = PolicyController.factory.get(controllerName);
1549       final DroolsController drools = controller.getDrools();
1550       encoders =
1551           EventProtocolCoder.manager.getEncoderFilters(drools.getGroupId(), drools.getArtifactId());
1552     } catch (final IllegalArgumentException e) {
1553       logger.debug("{}: cannot get encoder filters for policy-controller {} because of {}", this,
1554           controllerName, e.getMessage(), e);
1555       return Response.status(Response.Status.BAD_REQUEST)
1556           .entity(new Error(controllerName + " not found: " + e.getMessage())).build();
1557     } catch (final IllegalStateException e) {
1558       logger.debug("{}: cannot get encoder filters for policy-controller {} because of {}", this,
1559           controllerName, e.getMessage(), e);
1560       return Response.status(Response.Status.NOT_ACCEPTABLE)
1561           .entity(new Error(controllerName + " is not accepting the request")).build();
1562     }
1563
1564     return Response.status(Response.Status.OK).entity(encoders).build();
1565   }
1566
1567   @GET
1568   @Path("engine/topics")
1569   @ApiOperation(value = "Retrieves the managed topics", notes = "Network Topics Aggregation",
1570       response = TopicEndpoint.class)
1571   public Response topics() {
1572     return Response.status(Response.Status.OK).entity(TopicEndpoint.manager).build();
1573   }
1574
1575   @GET
1576   @Path("engine/topics/switches")
1577   @ApiOperation(value = "Topics Control Switches", notes = "List of the Topic Control Switches",
1578       responseContainer = "List")
1579   public Response topicSwitches() {
1580     return Response.status(Response.Status.OK).entity(Arrays.asList(Switches.values())).build();
1581   }
1582
1583   @PUT
1584   @Path("engine/topics/switches/lock")
1585   @ApiOperation(value = "Locks all the managed topics",
1586       notes = "The operation affects all managed sources and sinks", response = TopicEndpoint.class)
1587   @ApiResponses(value = {
1588       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1589           + "this request to be fulfilled")})
1590   public Response topicsLock() {
1591     final boolean success = TopicEndpoint.manager.lock();
1592     if (success)
1593       return Response.status(Status.OK).entity(TopicEndpoint.manager).build();
1594     else
1595       return Response.status(Status.NOT_ACCEPTABLE).entity(new Error("cannot perform operation"))
1596           .build();
1597   }
1598
1599   @DELETE
1600   @Path("engine/topics/switches/lock")
1601   @ApiOperation(value = "Unlocks all the managed topics",
1602       notes = "The operation affects all managed sources and sinks", response = TopicEndpoint.class)
1603   @ApiResponses(value = {
1604       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1605           + "this request to be fulfilled")})
1606   public Response topicsUnlock() {
1607     final boolean success = TopicEndpoint.manager.unlock();
1608     if (success)
1609       return Response.status(Status.OK).entity(TopicEndpoint.manager).build();
1610     else
1611       return Response.status(Status.NOT_ACCEPTABLE).entity(new Error("cannot perform operation"))
1612           .build();
1613   }
1614
1615   @GET
1616   @Path("engine/topics/sources")
1617   @ApiOperation(value = "Retrieves the managed topic sources",
1618       notes = "Network Topic Sources Agregation", responseContainer = "List",
1619       response = TopicSource.class)
1620   public Response sources() {
1621     return Response.status(Response.Status.OK).entity(TopicEndpoint.manager.getTopicSources())
1622         .build();
1623   }
1624
1625   @GET
1626   @Path("engine/topics/sinks")
1627   @ApiOperation(value = "Retrieves the managed topic sinks",
1628       notes = "Network Topic Sinks Agregation", responseContainer = "List",
1629       response = TopicSink.class)
1630   public Response sinks() {
1631     return Response.status(Response.Status.OK).entity(TopicEndpoint.manager.getTopicSinks())
1632         .build();
1633   }
1634
1635   @GET
1636   @Path("engine/topics/sources/ueb")
1637   @ApiOperation(value = "Retrieves the UEB managed topic sources",
1638       notes = "UEB Topic Sources Agregation", responseContainer = "List",
1639       response = UebTopicSource.class)
1640   public Response uebSources() {
1641     return Response.status(Response.Status.OK).entity(TopicEndpoint.manager.getUebTopicSources())
1642         .build();
1643   }
1644
1645   @GET
1646   @Path("engine/topics/sinks/ueb")
1647   @ApiOperation(value = "Retrieves the UEB managed topic sinks",
1648       notes = "UEB Topic Sinks Agregation", responseContainer = "List",
1649       response = UebTopicSink.class)
1650   public Response uebSinks() {
1651     return Response.status(Response.Status.OK).entity(TopicEndpoint.manager.getUebTopicSinks())
1652         .build();
1653   }
1654
1655   @GET
1656   @Path("engine/topics/sources/dmaap")
1657   @ApiOperation(value = "Retrieves the DMaaP managed topic sources",
1658       notes = "DMaaP Topic Sources Agregation", responseContainer = "List",
1659       response = DmaapTopicSource.class)
1660   public Response dmaapSources() {
1661     return Response.status(Response.Status.OK).entity(TopicEndpoint.manager.getDmaapTopicSources())
1662         .build();
1663   }
1664
1665   @GET
1666   @Path("engine/topics/sinks/dmaap")
1667   @ApiOperation(value = "Retrieves the DMaaP managed topic sinks",
1668       notes = "DMaaP Topic Sinks Agregation", responseContainer = "List",
1669       response = DmaapTopicSink.class)
1670   public Response dmaapSinks() {
1671     return Response.status(Response.Status.OK).entity(TopicEndpoint.manager.getDmaapTopicSinks())
1672         .build();
1673   }
1674
1675   @GET
1676   @Path("engine/topics/sources/ueb/{topic}")
1677   @ApiOperation(value = "Retrieves an UEB managed topic source",
1678       notes = "This is an UEB Network Communicaton Endpoint source of messages for the Engine",
1679       response = UebTopicSource.class)
1680   public Response uebSourceTopic(
1681       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic) {
1682     return Response.status(Response.Status.OK)
1683         .entity(TopicEndpoint.manager.getUebTopicSource(topic)).build();
1684   }
1685
1686   @GET
1687   @Path("engine/topics/sinks/ueb/{topic}")
1688   @ApiOperation(value = "Retrieves an UEB managed topic sink",
1689       notes = "This is an UEB Network Communicaton Endpoint destination of messages from the Engine",
1690       response = UebTopicSink.class)
1691   public Response uebSinkTopic(
1692       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic) {
1693     return Response.status(Response.Status.OK).entity(TopicEndpoint.manager.getUebTopicSink(topic))
1694         .build();
1695   }
1696
1697   @GET
1698   @Path("engine/topics/sources/dmaap/{topic}")
1699   @ApiOperation(value = "Retrieves a DMaaP managed topic source",
1700       notes = "This is a DMaaP Network Communicaton Endpoint source of messages for the Engine",
1701       response = DmaapTopicSource.class)
1702   public Response dmaapSourceTopic(
1703       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic) {
1704     return Response.status(Response.Status.OK)
1705         .entity(TopicEndpoint.manager.getDmaapTopicSource(topic)).build();
1706   }
1707
1708   @GET
1709   @Path("engine/topics/sinks/dmaap/{topic}")
1710   @ApiOperation(value = "Retrieves a DMaaP managed topic sink",
1711       notes = "This is a DMaaP Network Communicaton Endpoint destination of messages from the Engine",
1712       response = DmaapTopicSink.class)
1713   public Response dmaapSinkTopic(
1714       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic) {
1715     return Response.status(Response.Status.OK)
1716         .entity(TopicEndpoint.manager.getDmaapTopicSink(topic)).build();
1717   }
1718
1719   @GET
1720   @Path("engine/topics/sources/ueb/{topic}/events")
1721   @ApiOperation(value = "Retrieves the latest events received by an UEB topic",
1722       notes = "This is a UEB Network Communicaton Endpoint source of messages for the Engine",
1723       responseContainer = "List")
1724   public Response uebSourceEvents(
1725       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic) {
1726     return Response.status(Status.OK)
1727         .entity(Arrays.asList(TopicEndpoint.manager.getUebTopicSource(topic).getRecentEvents()))
1728         .build();
1729   }
1730
1731   @GET
1732   @Path("engine/topics/sinks/ueb/{topic}/events")
1733   @ApiOperation(value = "Retrieves the latest events sent from a topic",
1734       notes = "This is a UEB Network Communicaton Endpoint sink of messages from the Engine",
1735       responseContainer = "List")
1736   public Response uebSinkEvents(
1737       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic) {
1738     return Response.status(Status.OK)
1739         .entity(Arrays.asList(TopicEndpoint.manager.getUebTopicSink(topic).getRecentEvents()))
1740         .build();
1741   }
1742
1743   @GET
1744   @Path("engine/topics/sources/dmaap/{topic}/events")
1745   @ApiOperation(value = "Retrieves the latest events received by a DMaaP topic",
1746       notes = "This is a DMaaP Network Communicaton Endpoint source of messages for the Engine",
1747       responseContainer = "List")
1748   public Response dmaapSourceEvents(
1749       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic) {
1750     return Response.status(Status.OK)
1751         .entity(Arrays.asList(TopicEndpoint.manager.getDmaapTopicSource(topic).getRecentEvents()))
1752         .build();
1753   }
1754
1755   @GET
1756   @Path("engine/topics/sinks/dmaap/{topic}/events")
1757   @ApiOperation(value = "Retrieves the latest events send through a DMaaP topic",
1758       notes = "This is a DMaaP Network Communicaton Endpoint destination of messages from the Engine",
1759       responseContainer = "List")
1760   public Response dmaapSinkEvents(@PathParam("topic") String topic) {
1761     return Response.status(Status.OK)
1762         .entity(Arrays.asList(TopicEndpoint.manager.getDmaapTopicSink(topic).getRecentEvents()))
1763         .build();
1764   }
1765
1766   @GET
1767   @Path("engine/topics/sinks/noop")
1768   @ApiOperation(value = "Retrieves the NOOP managed topic sinks",
1769       notes = "NOOP Topic Sinks Agregation", responseContainer = "List",
1770       response = NoopTopicSink.class)
1771   public Response noopSinks() {
1772     return Response.status(Response.Status.OK).entity(TopicEndpoint.manager.getNoopTopicSinks())
1773         .build();
1774   }
1775
1776   @GET
1777   @Path("engine/topics/sinks/noop/{topic}")
1778   @ApiOperation(value = "Retrieves a NOOP managed topic sink",
1779       notes = "NOOP is an dev/null Network Communicaton Sink", response = NoopTopicSink.class)
1780   public Response noopSinkTopic(
1781       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic) {
1782     return Response.status(Response.Status.OK).entity(TopicEndpoint.manager.getNoopTopicSink(topic))
1783         .build();
1784   }
1785
1786   @GET
1787   @Path("engine/topics/sinks/noop/{topic}/events")
1788   @ApiOperation(value = "Retrieves the latest events send through a NOOP topic",
1789       notes = "NOOP is an dev/null Network Communicaton Sink", responseContainer = "List")
1790   public Response noopSinkEvents(@PathParam("topic") String topic) {
1791     return Response.status(Status.OK)
1792         .entity(Arrays.asList(TopicEndpoint.manager.getNoopTopicSink(topic).getRecentEvents()))
1793         .build();
1794   }
1795
1796   @GET
1797   @Path("engine/topics/sources/ueb/{topic}/switches")
1798   @ApiOperation(value = "UEB Topic Control Switches",
1799       notes = "List of the UEB Topic Control Switches", responseContainer = "List")
1800   public Response uebTopicSwitches() {
1801     return Response.status(Response.Status.OK).entity(Arrays.asList(Switches.values())).build();
1802   }
1803
1804   @PUT
1805   @Path("engine/topics/sources/ueb/{topic}/switches/lock")
1806   @ApiOperation(value = "Locks an UEB Source topic", response = UebTopicSource.class)
1807   @ApiResponses(value = {
1808       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1809           + "this request to be fulfilled")})
1810   public Response uebTopicLock(
1811       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic) {
1812     final UebTopicSource source = TopicEndpoint.manager.getUebTopicSource(topic);
1813     final boolean success = source.lock();
1814     if (success)
1815       return Response.status(Status.OK).entity(source).build();
1816     else
1817       return Response.status(Status.NOT_ACCEPTABLE)
1818           .entity(new Error("cannot perform operation on " + topic)).build();
1819   }
1820
1821   @DELETE
1822   @Path("engine/topics/sources/ueb/{topic}/switches/lock")
1823   @ApiOperation(value = "Unlocks an UEB Source topic", response = UebTopicSource.class)
1824   @ApiResponses(value = {
1825       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1826           + "this request to be fulfilled")})
1827   public Response uebTopicUnlock(
1828       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic) {
1829     final UebTopicSource source = TopicEndpoint.manager.getUebTopicSource(topic);
1830     final boolean success = source.unlock();
1831     if (success)
1832       return Response.status(Status.OK).entity(source).build();
1833     else
1834       return Response.status(Status.NOT_ACCEPTABLE)
1835           .entity(new Error("cannot perform operation on " + topic)).build();
1836   }
1837
1838   @GET
1839   @Path("engine/topics/sources/dmaap/{topic}/switches")
1840   @ApiOperation(value = "DMaaP Topic Control Switches",
1841       notes = "List of the DMaaP Topic Control Switches", responseContainer = "List")
1842   public Response dmaapTopicSwitches() {
1843     return Response.status(Response.Status.OK).entity(Arrays.asList(Switches.values())).build();
1844   }
1845
1846   @PUT
1847   @Path("engine/topics/sources/dmaap/{topic}/switches/lock")
1848   @ApiOperation(value = "Locks an DMaaP Source topic", response = DmaapTopicSource.class)
1849   @ApiResponses(value = {
1850       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1851           + "this request to be fulfilled")})
1852   public Response dmmapTopicLock(
1853       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic) {
1854     final DmaapTopicSource source = TopicEndpoint.manager.getDmaapTopicSource(topic);
1855     final boolean success = source.lock();
1856     if (success)
1857       return Response.status(Status.OK).entity(source).build();
1858     else
1859       return Response.status(Status.NOT_ACCEPTABLE)
1860           .entity(new Error("cannot perform operation on " + topic)).build();
1861   }
1862
1863   @DELETE
1864   @Path("engine/topics/sources/dmaap/{topic}/switches/lock")
1865   @ApiOperation(value = "Unlocks an DMaaP Source topic", response = DmaapTopicSource.class)
1866   @ApiResponses(value = {
1867       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1868           + "this request to be fulfilled")})
1869   public Response dmaapTopicUnlock(
1870       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic) {
1871     final DmaapTopicSource source = TopicEndpoint.manager.getDmaapTopicSource(topic);
1872     final boolean success = source.unlock();
1873     if (success)
1874       return Response.status(Status.OK).entity(source).build();
1875     else
1876       return Response.status(Status.SERVICE_UNAVAILABLE)
1877           .entity(new Error("cannot perform operation on " + topic)).build();
1878   }
1879
1880   @PUT
1881   @Path("engine/topics/sources/ueb/{topic}/events")
1882   @Consumes(MediaType.TEXT_PLAIN)
1883   @ApiOperation(value = "Offers an event to an UEB topic for internal processing by the engine",
1884       notes = "The offered event is treated as it was incoming from the network",
1885       responseContainer = "List")
1886   @ApiResponses(value = {
1887       @ApiResponse(code = 404, message = "The topic information cannot be found"),
1888       @ApiResponse(code = 406,
1889           message = "The system is an administrative state that prevents "
1890               + "this request to be fulfilled"),
1891       @ApiResponse(code = 500, message = "A server error has occurred processing this request")})
1892   public Response uebOffer(
1893       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic,
1894       @ApiParam(value = "Network Message", required = true) String json) {
1895     try {
1896       final UebTopicSource uebReader = TopicEndpoint.manager.getUebTopicSource(topic);
1897       final boolean success = uebReader.offer(json);
1898       if (success)
1899         return Response.status(Status.OK)
1900             .entity(Arrays.asList(TopicEndpoint.manager.getUebTopicSource(topic).getRecentEvents()))
1901             .build();
1902       else
1903         return Response.status(Status.NOT_ACCEPTABLE)
1904             .entity(new Error("Failure to inject event over " + topic)).build();
1905     } catch (final IllegalArgumentException e) {
1906       logger.debug("{}: cannot offer for encoder ueb topic for {} because of {}", this, topic,
1907           e.getMessage(), e);
1908       return Response.status(Response.Status.NOT_FOUND).entity(new Error(topic + " not found"))
1909           .build();
1910     } catch (final IllegalStateException e) {
1911       logger.debug("{}: cannot offer for encoder ueb topic for {} because of {}", this, topic,
1912           e.getMessage(), e);
1913       return Response.status(Response.Status.NOT_ACCEPTABLE)
1914           .entity(new Error(topic + " not acceptable due to current state")).build();
1915     } catch (final Exception e) {
1916       logger.debug("{}: cannot offer for encoder ueb topic for {} because of {}", this, topic,
1917           e.getMessage(), e);
1918       return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
1919           .entity(new Error(e.getMessage())).build();
1920     }
1921   }
1922
1923   @PUT
1924   @Path("engine/topics/sources/dmaap/{topic}/events")
1925   @Consumes(MediaType.TEXT_PLAIN)
1926   @ApiOperation(value = "Offers an event to a DMaaP topic for internal processing by the engine",
1927       notes = "The offered event is treated as it was incoming from the network",
1928       responseContainer = "List")
1929   @ApiResponses(value = {
1930       @ApiResponse(code = 404, message = "The topic information cannot be found"),
1931       @ApiResponse(code = 406,
1932           message = "The system is an administrative state that prevents "
1933               + "this request to be fulfilled"),
1934       @ApiResponse(code = 500, message = "A server error has occurred processing this request")})
1935   public Response dmaapOffer(
1936       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic,
1937       @ApiParam(value = "Network Message", required = true) String json) {
1938     try {
1939       final DmaapTopicSource dmaapReader = TopicEndpoint.manager.getDmaapTopicSource(topic);
1940       final boolean success = dmaapReader.offer(json);
1941       if (success)
1942         return Response.status(Status.OK)
1943             .entity(
1944                 Arrays.asList(TopicEndpoint.manager.getDmaapTopicSource(topic).getRecentEvents()))
1945             .build();
1946       else
1947         return Response.status(Status.NOT_ACCEPTABLE)
1948             .entity(new Error("Failure to inject event over " + topic)).build();
1949     } catch (final IllegalArgumentException e) {
1950       logger.debug("{}: cannot offer for encoder dmaap topic for {} because of {}", this, topic,
1951           e.getMessage(), e);
1952       return Response.status(Response.Status.NOT_FOUND).entity(new Error(topic + " not found"))
1953           .build();
1954     } catch (final IllegalStateException e) {
1955       logger.debug("{}: cannot offer for encoder dmaap topic for {} because of {}", this, topic,
1956           e.getMessage(), e);
1957       return Response.status(Response.Status.NOT_ACCEPTABLE)
1958           .entity(new Error(topic + " not acceptable due to current state")).build();
1959     } catch (final Exception e) {
1960       logger.debug("{}: cannot offer for encoder dmaap topic for {} because of {}", this, topic,
1961           e.getMessage(), e);
1962       return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
1963           .entity(new Error(e.getMessage())).build();
1964     }
1965   }
1966
1967   @GET
1968   @Path("engine/tools/uuid")
1969   @ApiOperation(value = "Produces an UUID", notes = "UUID generation utility")
1970   @Produces(MediaType.TEXT_PLAIN)
1971   public Response uuid() {
1972     return Response.status(Status.OK).entity(UUID.randomUUID().toString()).build();
1973   }
1974
1975   @GET
1976   @Path("engine/tools/loggers")
1977   @ApiOperation(value = "all active loggers", responseContainer = "List")
1978   @ApiResponses(value = {@ApiResponse(code = 500, message = "logging misconfiguration")})
1979   public Response loggers() {
1980     final List<String> names = new ArrayList<String>();
1981     if (!(LoggerFactory.getILoggerFactory() instanceof LoggerContext)) {
1982       logger.warn("The SLF4J logger factory is not configured for logback");
1983       return Response.status(Status.INTERNAL_SERVER_ERROR).entity(names).build();
1984     }
1985
1986     final LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
1987     for (final Logger logger : context.getLoggerList()) {
1988       names.add(logger.getName());
1989     }
1990
1991     return Response.status(Status.OK).entity(names).build();
1992   }
1993
1994   @GET
1995   @Path("engine/tools/loggers/{logger}")
1996   @Produces(MediaType.TEXT_PLAIN)
1997   @ApiOperation(value = "logging level of a logger")
1998   @ApiResponses(value = {@ApiResponse(code = 500, message = "logging misconfiguration"),
1999       @ApiResponse(code = 404, message = "logger not found")})
2000   public Response loggerName(
2001       @ApiParam(value = "Logger Name", required = true) @PathParam("logger") String loggerName) {
2002     if (!(LoggerFactory.getILoggerFactory() instanceof LoggerContext)) {
2003       logger.warn("The SLF4J logger factory is not configured for logback");
2004       return Response.status(Status.INTERNAL_SERVER_ERROR).build();
2005     }
2006
2007     final LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
2008     final ch.qos.logback.classic.Logger logger = context.getLogger(loggerName);
2009     if (logger == null) {
2010       return Response.status(Status.NOT_FOUND).build();
2011     }
2012
2013     final String loggerLevel = (logger.getLevel() != null) ? logger.getLevel().toString() : "";
2014     return Response.status(Status.OK).entity(loggerLevel).build();
2015   }
2016
2017   @PUT
2018   @Path("engine/tools/loggers/{logger}/{level}")
2019   @Produces(MediaType.TEXT_PLAIN)
2020   @Consumes(MediaType.TEXT_PLAIN)
2021   @ApiOperation(value = "sets the logger level", notes = "Please use the SLF4J logger levels")
2022   @ApiResponses(value = {@ApiResponse(code = 500, message = "logging misconfiguration"),
2023       @ApiResponse(code = 404, message = "logger not found")})
2024   public Response loggerName(
2025       @ApiParam(value = "Logger Name", required = true) @PathParam("logger") String loggerName,
2026       @ApiParam(value = "Logger Level", required = true) @PathParam("level") String loggerLevel) {
2027
2028     String newLevel;
2029     try {
2030       newLevel = LoggerUtil.setLevel(loggerName, loggerLevel);
2031     } catch (final IllegalArgumentException e) {
2032       logger.warn("{}: no logger {}", this, loggerName, loggerLevel, e);
2033       return Response.status(Status.NOT_FOUND).build();
2034     } catch (final IllegalStateException e) {
2035       logger.warn("{}: logging framework unavailable for {} / {}", this, loggerName, loggerLevel,
2036           e);
2037       return Response.status(Status.INTERNAL_SERVER_ERROR).build();
2038     }
2039
2040     return Response.status(Status.OK).entity(newLevel
2041
2042     ).build();
2043   }
2044
2045   /**
2046    * gets the underlying drools controller from the named policy controller
2047    *
2048    * @param controllerName the policy controller name
2049    * @return the underlying drools controller
2050    * @throws IllegalArgumentException if an invalid controller name has been passed in
2051    */
2052   protected DroolsController getDroolsController(String controllerName) {
2053     final PolicyController controller = PolicyController.factory.get(controllerName);
2054     if (controller == null)
2055       throw new IllegalArgumentException(controllerName + "  does not exist");
2056
2057     final DroolsController drools = controller.getDrools();
2058     if (drools == null)
2059       throw new IllegalArgumentException(controllerName + "  has no drools configuration");
2060
2061     return drools;
2062   }
2063
2064   /*
2065    * Helper classes for aggregation of results
2066    */
2067
2068   @Override
2069   public String toString() {
2070     final StringBuilder builder = new StringBuilder();
2071     builder.append("rest-telemetry-api []");
2072     return builder.toString();
2073   }
2074
2075   /**
2076    * Coding/Encoding Results Aggregation Helper class
2077    */
2078   public static class CodingResult {
2079     /**
2080      * serialized output
2081      */
2082
2083     public String jsonEncoding;
2084     /**
2085      * encoding result
2086      */
2087
2088     public Boolean encoding;
2089
2090     /**
2091      * decoding result
2092      */
2093     public Boolean decoding;
2094   }
2095
2096   /**
2097    * Generic Error Reporting class
2098    */
2099   public static class Error {
2100     public String error;
2101
2102     public Error(String error) {
2103       this.error = error;
2104     }
2105   }
2106
2107   /**
2108    * Feed Ports into Resources
2109    */
2110   public enum Inputs {
2111     configuration,
2112   }
2113
2114   /**
2115    * Resource Toggles
2116    */
2117   public enum Switches {
2118     activation, lock,
2119   }
2120 }
2121