Add Pagination to Neutron Networks Northbound API 05/6005/4
authorDave <dave.j.tucker@hp.com>
Wed, 9 Apr 2014 15:28:19 +0000 (16:28 +0100)
committerEd Warnicke <eaw@cisco.com>
Wed, 7 May 2014 16:00:00 +0000 (16:00 +0000)
This commit adds pagination to the neutron network northbound API.
It is based on the information at the following link.
http://docs.openstack.org/api/openstack-network/2.0/content/pagination.html

In addition to not providing a "next" link on the last page of results this
implementation does not have a "previous" link on the first page.

Change-Id: I2c048c9cdc907d759e62fb8850b76cfa293b7fd2
Signed-off-by: Dave Tucker <dave.j.tucker@hp.com>
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNetworksNorthbound.java
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronPageLink.java [new file with mode: 0644]
opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/PaginatedNeutronNetworkRequest.java [new file with mode: 0644]

index d7437c831d4eb38a248c72bbe4050114a358e32e..52c3337e40047fb844352fd9dcc0b6c596fcb8d0 100644 (file)
@@ -9,12 +9,15 @@
 package org.opendaylight.controller.networkconfig.neutron.northbound;
 
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
+import javax.ws.rs.DefaultValue;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.PUT;
@@ -22,7 +25,9 @@ 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.UriInfo;
 import javax.ws.rs.core.Response;
 
 import org.codehaus.enunciate.jaxrs.ResponseCode;
@@ -60,6 +65,9 @@ import org.opendaylight.controller.sal.utils.ServiceHelper;
 @Path("/networks")
 public class NeutronNetworksNorthbound {
 
+    @Context
+    UriInfo uriInfo;
+
     private NeutronNetwork extractFields(NeutronNetwork o, List<String> fields) {
         return o.extractFields(fields);
     }
@@ -72,7 +80,7 @@ public class NeutronNetworksNorthbound {
     //@TypeHint(OpenStackNetworks.class)
     @StatusCodes({
         @ResponseCode(code = 200, condition = "Operation successful"),
-        @ResponseCode(code = 401, condition = "Unauthorized") })
+        @ResponseCode(code = 401, condition = "Unauthorized")})
     public Response listNetworks(
             // return fields
             @QueryParam("fields") List<String> fields,
@@ -88,9 +96,9 @@ public class NeutronNetworksNorthbound {
             @QueryParam("provider_physical_network") String queryProviderPhysicalNetwork,
             @QueryParam("provider_segmentation_id") String queryProviderSegmentationID,
             // pagination
-            @QueryParam("limit") String limit,
+            @QueryParam("limit") Integer limit,
             @QueryParam("marker") String marker,
-            @QueryParam("page_reverse") String pageReverse
+            @DefaultValue("false") @QueryParam("page_reverse") Boolean pageReverse
             // sorting not supported
             ) {
         INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
@@ -130,9 +138,94 @@ public class NeutronNetworksNorthbound {
                 }
             }
         }
-        //TODO: apply pagination to results
-        return Response.status(200).entity(
-                new NeutronNetworkRequest(ans)).build();
+
+        Comparator<NeutronNetwork> neutronNetworkComparator = new Comparator<NeutronNetwork>() {
+            @Override
+            public int compare(NeutronNetwork o1, NeutronNetwork o2) {
+                return o1.getID().compareTo(o2.getID());
+            }
+        };
+
+        Collections.sort(ans, neutronNetworkComparator);
+
+        if (limit != null && ans.size() > 1) {
+            List<NeutronPageLink> links = new ArrayList<>();
+            Integer startPos = null;
+            String startMarker;
+            String endMarker;
+            Boolean firstPage = false;
+            Boolean lastPage = false;
+
+            if (marker == null) {
+                startPos = 0;
+            }
+
+            else {
+
+                NeutronNetwork markerNetwork = new NeutronNetwork();
+                markerNetwork.setNetworkUUID(marker);
+
+                startPos = Collections.binarySearch(ans, markerNetwork, neutronNetworkComparator);
+
+                if (!pageReverse){
+                    startPos = startPos + 1;
+                }
+                else {
+                    startPos = startPos - limit;
+                }
+
+            }
+
+            if (startPos == null) {
+                throw new ResourceNotFoundException("UUID for marker:" + marker + " could not be found");
+            }
+
+            if (startPos == 0){
+                firstPage = true;
+            }
+
+            if (startPos + limit >= ans.size()) {
+                ans = ans.subList(startPos, ans.size());
+                startMarker = ans.get(0).getID();
+                endMarker = ans.get(ans.size() - 1).getID();
+                lastPage = true;
+            }
+            else if (startPos < 0) {
+                if (startPos + limit > 0) {
+                    ans = ans.subList(0, startPos + limit);
+                    startMarker = ans.get(0).getID();
+                    endMarker = ans.get(ans.size() - 1).getID();
+                    firstPage = true;
+                }
+                else {
+                    throw new BadRequestException("Requested page is out of bounds. Please check the supplied limit and marker");
+                }
+            }
+            else {
+                ans = ans.subList(startPos, startPos + limit);
+                startMarker = ans.get(0).getID();
+                endMarker = ans.get(limit-1).getID();
+            }
+
+            if (!lastPage) {
+                NeutronPageLink next = new NeutronPageLink();
+                next.setRef("next");
+                next.setHref(uriInfo.getAbsolutePath().toString() + "?limit=" + limit.toString() + "&marker=" + endMarker);
+                links.add(next);
+            }
+
+            if (!firstPage) {
+                NeutronPageLink previous = new NeutronPageLink();
+                previous.setRef("previous");
+                previous.setHref(uriInfo.getAbsolutePath().toString() + "?limit=" + limit.toString() + "&marker=" + startMarker + "&page_reverse=True");
+                links.add(previous);
+            }
+
+            return Response.status(200).entity(new PaginatedNeutronNetworkRequest(ans, links)).build();
+        }
+
+    return Response.status(200).entity(new NeutronNetworkRequest(ans)).build();
+
     }
 
     /**
diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronPageLink.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronPageLink.java
new file mode 100644 (file)
index 0000000..f65d7f6
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2014 Hewlett-Packard Development Company L.P
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Authors : Dave Tucker
+ */
+
+package org.opendaylight.controller.networkconfig.neutron.northbound;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronPageLink {
+
+    @XmlElement(name="ref")
+    String ref;
+
+    @XmlElement (name="href")
+    String href;
+
+    public String getRef() {
+        return ref;
+    }
+
+    public void setRef(String ref) {
+        this.ref = ref;
+    }
+
+    public String getHref() {
+        return href;
+    }
+
+    public void setHref(String href) {
+        this.href = href;
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/PaginatedNeutronNetworkRequest.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/PaginatedNeutronNetworkRequest.java
new file mode 100644 (file)
index 0000000..c050661
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2014 Hewlett-Packard Development Company L.P
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Authors : Dave Tucker
+ */
+
+package org.opendaylight.controller.networkconfig.neutron.northbound;
+
+import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.util.List;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class PaginatedNeutronNetworkRequest {
+
+    @XmlElement (name="networks")
+    List<NeutronNetwork> networks;
+
+    @XmlElement (name="network_links")
+    List<NeutronPageLink> networkLinks;
+
+    public PaginatedNeutronNetworkRequest() {
+    }
+
+    public PaginatedNeutronNetworkRequest(List<NeutronNetwork> networks, List<NeutronPageLink> networkLinks) {
+        this.networks = networks;
+        this.networkLinks = networkLinks;
+    }
+
+    public List<NeutronNetwork> getNetworks() {
+        return networks;
+    }
+
+    public void setNetworks(List<NeutronNetwork> networks) {
+        this.networks = networks;
+    }
+
+    public List<NeutronPageLink> getNetworkLinks() {
+        return networkLinks;
+    }
+
+    public void setNetworkLinks(List<NeutronPageLink> networkLinks) {
+        this.networkLinks = networkLinks;
+    }
+}