2 * Copyright (c) 2014, 2015 Red Hat, Inc. and others. All rights reserved.
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
9 package org.opendaylight.neutron.northbound.api;
11 import java.util.ArrayList;
12 import java.util.Collections;
13 import java.util.Comparator;
14 import java.util.List;
15 import javax.ws.rs.core.UriInfo;
16 import org.opendaylight.neutron.spi.INeutronObject;
17 import org.opendaylight.neutron.spi.NeutronNetwork;
18 import org.opendaylight.neutron.spi.NeutronObject;
19 import org.opendaylight.neutron.spi.NeutronPort;
20 import org.opendaylight.neutron.spi.NeutronSubnet;
22 public final class PaginatedRequestFactory {
24 private static final Comparator<INeutronObject> NEUTRON_OBJECT_COMPARATOR = new Comparator<INeutronObject>() {
26 public int compare(INeutronObject o1, INeutronObject o2) {
27 return o1.getID().compareTo(o2.getID());
31 public static class PaginationResults<T extends INeutronObject<T>> {
33 List<NeutronPageLink> links;
35 public PaginationResults(List<T> collection, List<NeutronPageLink> links) {
36 this.collection = collection;
41 private static final class MarkerObject extends NeutronObject<MarkerObject>
42 implements INeutronObject<MarkerObject> {
43 private final String id;
45 MarkerObject(String id) {
51 public String getID() {
56 public void setID(String id) {
57 throw new UnsupportedOperationException("Marker has constant ID");
61 public MarkerObject extractFields(List<String> fields) {
62 throw new UnsupportedOperationException("extractFields shouldn't be called for MarkerObject");
66 private PaginatedRequestFactory() {
70 * SuppressWarnings is needed because the compiler does not understand that we
71 * are actually safe here.
73 * FIXME: the only caller performs a cast back, so this is not actually necessary.
75 @SuppressWarnings("unchecked")
76 public static <T extends INeutronObject<T>> INeutronRequest<T> createRequest(Integer limit, String marker,
77 Boolean pageReverse, UriInfo uriInfo, List<T> collection, Class<T> clazz) {
78 PaginationResults<T> results = paginate(limit, marker, pageReverse, uriInfo, collection);
80 if (clazz.equals(NeutronNetwork.class)) {
81 return (INeutronRequest<T>) new NeutronNetworkRequest((List<NeutronNetwork>) results.collection,
84 if (clazz.equals(NeutronSubnet.class)) {
85 return (INeutronRequest<T>) new NeutronSubnetRequest((List<NeutronSubnet>) results.collection,
88 if (clazz.equals(NeutronPort.class)) {
89 return (INeutronRequest<T>) new NeutronPortRequest((List<NeutronPort>) results.collection, results.links);
94 private static <T extends INeutronObject<T>> PaginationResults<T> paginate(Integer limit, String marker,
95 Boolean pageReverse, UriInfo uriInfo, List<T> collection) {
96 List<NeutronPageLink> links = new ArrayList<>();
101 Boolean lastPage = false;
103 Collections.sort(collection, NEUTRON_OBJECT_COMPARATOR);
105 if (marker != null) {
106 int offset = Collections.binarySearch(collection, new MarkerObject(marker), NEUTRON_OBJECT_COMPARATOR);
108 throw new ResourceNotFoundException("UUID for marker: " + marker + " could not be found");
112 startPos = offset + 1;
114 startPos = offset - limit;
120 firstPage = startPos == 0;
122 if (startPos + limit >= collection.size()) {
123 collection = collection.subList(startPos, collection.size());
124 startMarker = collection.get(0).getID();
125 endMarker = collection.get(collection.size() - 1).getID();
127 } else if (startPos < 0) {
128 if (startPos + limit > 0) {
129 collection = collection.subList(0, startPos + limit);
130 startMarker = collection.get(0).getID();
131 endMarker = collection.get(collection.size() - 1).getID();
134 throw new BadRequestException(
135 "Requested page is out of bounds. Please check the supplied limit and marker");
138 collection = collection.subList(startPos, startPos + limit);
139 startMarker = collection.get(0).getID();
140 endMarker = collection.get(limit - 1).getID();
144 NeutronPageLink next = new NeutronPageLink();
146 next.setHref(uriInfo.getAbsolutePath().toString() + "?limit=" + limit.toString() + "&marker=" + endMarker);
151 NeutronPageLink previous = new NeutronPageLink();
152 previous.setRef("previous");
153 previous.setHref(uriInfo.getAbsolutePath().toString() + "?limit=" + limit.toString() + "&marker="
154 + startMarker + "&page_reverse=True");
158 return new PaginationResults<T>(collection, links);