Make neutron a simple osgi app
[controller.git] / opendaylight / networkconfiguration / neutron / northbound / src / main / java / org / opendaylight / controller / networkconfig / neutron / northbound / PaginatedRequestFactory.java
1 /*
2  * Copyright (C) 2014 Red Hat, Inc.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  *
8  *  Authors : Dave Tucker
9  */
10
11 package org.opendaylight.controller.networkconfig.neutron.northbound;
12
13 import java.util.ArrayList;
14 import java.util.Collections;
15 import java.util.Comparator;
16 import java.util.List;
17 import javax.ws.rs.core.UriInfo;
18
19 import org.opendaylight.controller.networkconfig.neutron.INeutronObject;
20 import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
21 import org.opendaylight.controller.networkconfig.neutron.NeutronPort;
22 import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;
23
24 public class PaginatedRequestFactory {
25     private static final Comparator<INeutronObject> NEUTRON_OBJECT_COMPARATOR = new Comparator<INeutronObject>() {
26         @Override
27         public int compare(INeutronObject o1, INeutronObject o2) {
28             return o1.getID().compareTo(o2.getID());
29         }
30     };
31
32     public static class PaginationResults<T extends INeutronObject> {
33         List<T> collection;
34         List<NeutronPageLink> links;
35
36         public PaginationResults(List<T> collection, List<NeutronPageLink> links) {
37             this.collection = collection;
38             this.links = links;
39         }
40     }
41
42     private static final class MarkerObject implements INeutronObject {
43         private final String id;
44
45         MarkerObject(String id) {
46             this.id = id;
47         }
48
49         @Override
50         public String getID() {
51             return id;
52         }
53
54         @Override
55         public void setID(String id) {
56             throw new UnsupportedOperationException("Marker has constant ID");
57         }
58     }
59
60     /*
61      * SuppressWarnings is needed because the compiler does not understand that we
62      * are actually safe here.
63      *
64      * FIXME: the only caller performs a cast back, so this is not actually necessary.
65      */
66     @SuppressWarnings("unchecked")
67     public static <T extends INeutronObject> INeutronRequest<T> createRequest(Integer limit, String marker,
68                                                                            Boolean pageReverse,
69                                                                            UriInfo uriInfo,
70                                                                            List<T> collection,
71                                                                            Class<T> clazz) {
72         PaginationResults<T> results = _paginate(limit, marker, pageReverse, uriInfo, collection);
73
74         if (clazz.equals(NeutronNetwork.class)){
75             return (INeutronRequest<T>) new NeutronNetworkRequest((List<NeutronNetwork>) results.collection, results.links);
76         }
77         if (clazz.equals(NeutronSubnet.class)){
78             return (INeutronRequest<T>) new NeutronSubnetRequest((List<NeutronSubnet>) results.collection, results.links);
79         }
80         if (clazz.equals(NeutronPort.class)){
81             return (INeutronRequest<T>) new NeutronPortRequest((List<NeutronPort>) results.collection, results.links);
82         }
83         return null;
84     }
85
86     private static <T extends INeutronObject> PaginationResults<T> _paginate(Integer limit, String marker, Boolean pageReverse, UriInfo uriInfo, List<T> collection) {
87         List<NeutronPageLink> links = new ArrayList<>();
88         final int startPos;
89         String startMarker;
90         String endMarker;
91         Boolean firstPage = false;
92         Boolean lastPage = false;
93
94         Collections.sort(collection, NEUTRON_OBJECT_COMPARATOR);
95
96         if (marker != null) {
97             int offset = Collections.binarySearch(collection, new MarkerObject(marker), NEUTRON_OBJECT_COMPARATOR);
98             if (offset < 0) {
99                 throw new ResourceNotFoundException("UUID for marker: " + marker + " could not be found");
100             }
101
102             if (!pageReverse) {
103                 startPos = offset + 1;
104             }
105             else {
106                 startPos = offset - limit;
107             }
108         }
109         else {
110             startPos = 0;
111         }
112
113         if (startPos == 0){
114             firstPage = true;
115         }
116
117         if (startPos + limit >= collection.size()) {
118             collection = collection.subList(startPos, collection.size());
119             startMarker = collection.get(0).getID();
120             endMarker = collection.get(collection.size() - 1).getID();
121             lastPage = true;
122         }
123         else if (startPos < 0) {
124             if (startPos + limit > 0) {
125                 collection = collection.subList(0, startPos + limit);
126                 startMarker = collection.get(0).getID();
127                 endMarker = collection.get(collection.size() - 1).getID();
128                 firstPage = true;
129             }
130             else {
131                 throw new BadRequestException("Requested page is out of bounds. Please check the supplied limit and marker");
132             }
133         }
134         else {
135             collection = collection.subList(startPos, startPos + limit);
136             startMarker = collection.get(0).getID();
137             endMarker = collection.get(limit-1).getID();
138         }
139
140         if (!lastPage) {
141             NeutronPageLink next = new NeutronPageLink();
142             next.setRef("next");
143             next.setHref(uriInfo.getAbsolutePath().toString() + "?limit=" + limit.toString() + "&marker=" + endMarker);
144             links.add(next);
145         }
146
147         if (!firstPage) {
148             NeutronPageLink previous = new NeutronPageLink();
149             previous.setRef("previous");
150             previous.setHref(uriInfo.getAbsolutePath().toString() + "?limit=" + limit.toString() + "&marker=" + startMarker + "&page_reverse=True");
151             links.add(previous);
152         }
153
154         return new PaginationResults<T>(collection, links);
155     }
156 }