Support for FIQL queries on REST retreive operations
[controller.git] / opendaylight / northbound / flowprogrammer / src / main / java / org / opendaylight / controller / flowprogrammer / northbound / FlowProgrammerNorthbound.java
index c53e2d0a5ea0f11a03475e0c182236ae8d9271da..42bd59ea4577ff5c6d40b3ad4e8efaa976c900f5 100644 (file)
@@ -19,10 +19,12 @@ import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.ext.ContextResolver;
 
 import org.codehaus.enunciate.jaxrs.ResponseCode;
 import org.codehaus.enunciate.jaxrs.StatusCodes;
@@ -34,10 +36,10 @@ import org.opendaylight.controller.northbound.commons.RestMessages;
 import org.opendaylight.controller.northbound.commons.exception.InternalServerErrorException;
 import org.opendaylight.controller.northbound.commons.exception.MethodNotAllowedException;
 import org.opendaylight.controller.northbound.commons.exception.NotAcceptableException;
-import org.opendaylight.controller.northbound.commons.exception.ResourceConflictException;
 import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
 import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
 import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException;
+import org.opendaylight.controller.northbound.commons.query.QueryContext;
 import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
 import org.opendaylight.controller.sal.authorization.Privilege;
 import org.opendaylight.controller.sal.core.Node;
@@ -63,6 +65,14 @@ public class FlowProgrammerNorthbound {
 
     private String username;
 
+    private QueryContext queryContext;
+    @Context
+    public void setQueryContext(ContextResolver<QueryContext> queryCtxResolver) {
+      if (queryCtxResolver != null) {
+        queryContext = queryCtxResolver.getContext(QueryContext.class);
+      }
+    }
+
     @Context
     public void setSecurityContext(SecurityContext context) {
         if (context != null && context.getUserPrincipal() != null) {
@@ -195,15 +205,21 @@ public class FlowProgrammerNorthbound {
     @StatusCodes({ @ResponseCode(code = 200, condition = "Operation successful"),
         @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
         @ResponseCode(code = 404, condition = "The containerName is not found"),
-        @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
-    public FlowConfigs getStaticFlows(@PathParam("containerName") String containerName) {
+        @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable"),
+        @ResponseCode(code = 400, condition = "Incorrect query syntex")})
+    public FlowConfigs getStaticFlows(@PathParam("containerName") String containerName,
+                   @QueryParam("_q") String queryString) {
         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
             throw new UnauthorizedException("User is not authorized to perform this operation on container "
                     + containerName);
         }
 
-        List<FlowConfig> flowConfigs = getStaticFlowsInternal(containerName, null);
-        return new FlowConfigs(flowConfigs);
+        FlowConfigs result = new FlowConfigs(getStaticFlowsInternal(containerName, null));
+        if (queryString != null) {
+            queryContext.createQuery(queryString, FlowConfigs.class)
+                .filter(result, FlowConfig.class);
+        }
+        return result;
     }
 
     /**
@@ -273,7 +289,8 @@ public class FlowProgrammerNorthbound {
         @ResponseCode(code = 404, condition = "The containerName or nodeId is not found"),
         @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
     public FlowConfigs getStaticFlows(@PathParam("containerName") String containerName,
-            @PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId) {
+            @PathParam("nodeType") String nodeType, @PathParam("nodeId") String nodeId,
+            @QueryParam("_q") String queryString) {
         if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
             throw new UnauthorizedException("User is not authorized to perform this operation on container "
                     + containerName);
@@ -282,8 +299,12 @@ public class FlowProgrammerNorthbound {
         if (node == null) {
             throw new ResourceNotFoundException(nodeId + " : " + RestMessages.NONODE.toString());
         }
-        List<FlowConfig> flows = getStaticFlowsInternal(containerName, node);
-        return new FlowConfigs(flows);
+        FlowConfigs flows = new FlowConfigs(getStaticFlowsInternal(containerName, node));
+        if (queryString != null) {
+            queryContext.createQuery(queryString, FlowConfigs.class)
+                .filter(flows, FlowConfig.class);
+        }
+        return flows;
     }
 
     /**
@@ -373,8 +394,7 @@ public class FlowProgrammerNorthbound {
     }
 
     /**
-     * Add a flow configuration. If a flow by the given name already exists,
-     * this method will respond with a non-successful status response.
+     * Add or Modify a flow configuration. If the flow exists already, it will replace the current flow.
      *
      * @param containerName
      *            Name of the Container (Eg. 'default')
@@ -433,6 +453,7 @@ public class FlowProgrammerNorthbound {
     @PUT
     @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
     @StatusCodes({
+        @ResponseCode(code = 200, condition = "Static Flow modified successfully"),
         @ResponseCode(code = 201, condition = "Flow Config processed successfully"),
         @ResponseCode(code = 400, condition = "Failed to create Static Flow entry due to invalid flow configuration"),
         @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
@@ -441,7 +462,7 @@ public class FlowProgrammerNorthbound {
         @ResponseCode(code = 409, condition = "Failed to create Static Flow entry due to Conflicting Name or configuration"),
         @ResponseCode(code = 500, condition = "Failed to create Static Flow entry. Failure Reason included in HTTP Error response"),
         @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
-    public Response addFlow(@PathParam(value = "containerName") String containerName,
+    public Response addOrModifyFlow(@PathParam(value = "containerName") String containerName,
             @PathParam(value = "name") String name, @PathParam("nodeType") String nodeType,
             @PathParam(value = "nodeId") String nodeId, @TypeHint(FlowConfig.class) FlowConfig flowConfig) {
 
@@ -455,7 +476,8 @@ public class FlowProgrammerNorthbound {
                     .build();
         }
         handleResourceCongruence(name, flowConfig.getName());
-        handleResourceCongruence(nodeId, flowConfig.getNode().getNodeIDString());
+        handleResourceCongruence(nodeType, flowConfig.getNode().getType());
+        handleResourceCongruence(nodeId, flowConfig.getNode().getID() == null ? null : flowConfig.getNode().getNodeIDString());
         handleDefaultDisabled(containerName);
 
         IForwardingRulesManager frm = getForwardingRulesManagerService(containerName);
@@ -465,18 +487,24 @@ public class FlowProgrammerNorthbound {
         }
 
         Node node = handleNodeAvailability(containerName, nodeType, nodeId);
+        Status status;
 
         FlowConfig staticFlow = frm.getStaticFlow(name, node);
-        if (staticFlow != null) {
-            throw new ResourceConflictException(name + " already exists." + RestMessages.RESOURCECONFLICT.toString());
-        }
-
-        Status status = frm.addStaticFlow(flowConfig);
 
-        if (status.isSuccess()) {
-            NorthboundUtils.auditlog("Flow Entry", username, "added",
-                    name + " on Node " + NorthboundUtils.getNodeDesc(node, containerName, this), containerName);
-            return Response.status(Response.Status.CREATED).entity("Success").build();
+        if (staticFlow == null) {
+          status = frm.addStaticFlow(flowConfig);
+          if(status.isSuccess()){
+              NorthboundUtils.auditlog("Flow Entry", username, "added",
+                      name + " on Node " + NorthboundUtils.getNodeDesc(node, containerName, this), containerName);
+              return Response.status(Response.Status.CREATED).entity("Success").build();
+          }
+        } else {
+          status = frm.modifyStaticFlow(flowConfig);
+          if(status.isSuccess()){
+              NorthboundUtils.auditlog("Flow Entry", username, "updated",
+                      name + " on Node " + NorthboundUtils.getNodeDesc(node, containerName, this), containerName);
+              return NorthboundUtils.getResponse(status);
+          }
         }
         return NorthboundUtils.getResponse(status);
     }
@@ -506,7 +534,6 @@ public class FlowProgrammerNorthbound {
 
     @Path("/{containerName}/node/{nodeType}/{nodeId}/staticFlow/{name}")
     @DELETE
-    @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
     @StatusCodes({
         @ResponseCode(code = 204, condition = "Flow Config deleted successfully"),
         @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),