View Javadoc

1   package com.atlassian.plugins.rest.doclet.generators.schema.beans.attachment;
2   
3   import com.atlassian.plugins.rest.common.expand.entity.ListWrapper;
4   import com.atlassian.plugins.rest.common.expand.entity.ListWrapperCallback;
5   import com.atlassian.plugins.rest.common.expand.parameter.Indexes;
6   import com.google.common.collect.ImmutableList;
7   import com.google.common.collect.Lists;
8   
9   import java.util.Arrays;
10  import java.util.Collections;
11  import java.util.List;
12  import javax.xml.bind.annotation.XmlAttribute;
13  import javax.xml.bind.annotation.XmlElement;
14  import javax.xml.bind.annotation.XmlRootElement;
15  import javax.xml.bind.annotation.XmlTransient;
16  
17  import static java.util.Collections.emptyList;
18  
19  /**
20   * This is a list wrapper that works by wrapping a java.util.Collection that has been eagerly loaded into memory. As
21   * such, it does not take full advantage of the "expandable" concepts since it requires callers to have previously
22   * loaded the entire data set into memory, but it has the advantage of being simple to implement.
23   * <p/>
24   * This class makes a shallow copy of the wrapped collection.
25   *
26   * @see com.atlassian.plugins.rest.common.expand.Expandable
27   * @since v4.2
28   */
29  @XmlRootElement (name = "list")
30  public class SimpleListWrapper<T> implements ListWrapper<T>
31  {
32      /**
33       * Returns an empty SimpleListWrapper.
34       *
35       * @param <T> the type of the list element
36       * @return an empty SimpleListWrapper
37       */
38      public static <T> SimpleListWrapper<T> empty()
39      {
40          return of(Collections.<T>emptyList());
41      }
42  
43      /**
44       * Returns a new SimpleListWrapper that wraps the given elements.
45       *
46       * @param <T> the type of the list element
47       * @param elements the elements to wrap
48       * @return a new SimpleListWrapper
49       */
50      public static <T> SimpleListWrapper<T> of(T... elements)
51      {
52          return of(Arrays.asList(elements));
53      }
54  
55      /**
56       * Returns a new SimpleListWrapper that is backed by the given collection.
57       *
58       * @param <T> the type of the list element
59       * @param list the backing Collection
60       * @return a new SimpleListWrapper
61       */
62      public static <T> SimpleListWrapper<T> of(List<T> list)
63      {
64          return of(list, null);
65      }
66  
67      /**
68       * Returns a new SimpleListWrapper that is backed by the given list and returns at most maxResults items to the
69       * client.
70       *
71       * @param <T> the type of the list element
72       * @param list the backing List
73       * @param maxResults the maximum number of results to return to the client in one call, or null
74       * @return a new SimpleListWrapper
75       */
76      public static <T> SimpleListWrapper<T> of(List<T> list, Integer maxResults)
77      {
78          return new SimpleListWrapper<T>(list, maxResults, list.size());
79      }
80  
81      /**
82       * Returns a new SimpleListWrapper that is backed by the given list and returns at most maxResults items to the
83       * client. The size attribute will contain the provided value, instead of the actual size of the passed-in list.
84       *
85       * @param <T> the type of the list element
86       * @param list the backing List
87       * @param maxResults the maximum number of results to return to the client in one call
88       * @param size the size of the data set
89       * @return a new SimpleListWrapper
90       */
91      public static <T> SimpleListWrapper<T> of(List<T> list, Integer maxResults, int size)
92      {
93          return new SimpleListWrapper<T>(list, maxResults, size);
94      }
95  
96      /**
97       * The size of the data set.
98       */
99      @XmlAttribute (name = "size")
100     private int size;
101 
102     /**
103      * The maximum number of results returned.
104      */
105     @XmlAttribute (name = "max-results")
106     private Integer maxResults;
107 
108     /**
109      * This private field is never changed from within this class. Instead, it is modified by the REST plugin's expand
110      * functionality via Java reflection APIs.
111      *
112      * @see #pagingCallback
113      */
114     @XmlElement (name = "items")
115     private List<T> items = Collections.emptyList();
116 
117     /**
118      * The callback used by the REST plugin to expand the items.
119      */
120     @XmlTransient
121     private ListWrapperCallback<T> pagingCallback;
122 
123     /**
124      * No-arg constructor for use by tools that work using reflection.
125      */
126     private SimpleListWrapper()
127     {
128         // necessary for JAXB
129     }
130 
131     /**
132      * Creates a new SimpleListWrapper backed by the given list and returns at most maxResults items to the client.
133      *
134      * @param list a Collection
135      * @param maxResults the maximum number of results to return to the client in one call
136      * @param size the size of the data set
137      */
138     protected SimpleListWrapper(List<T> list, Integer maxResults, int size)
139     {
140         this.size = size;
141         this.maxResults = maxResults;
142         this.pagingCallback = ofList(ImmutableList.copyOf(list), maxResults != null ? maxResults : Integer.MAX_VALUE);
143     }
144 
145     /**
146      * Returns a ListWrapperCallback that the REST plugin can use to retrieve elements having specific indexes.
147      *
148      * @return a ListWrapperCallback<T>
149      */
150     public ListWrapperCallback<T> getPagingCallback()
151     {
152         return pagingCallback;
153     }
154 
155     public int getSize()
156     {
157         return size;
158     }
159 
160     public int getMaxResults()
161     {
162         return maxResults;
163     }
164 
165     public final ListWrapperCallback<T> getCallback()
166     {
167         return new ListWrapperCallback<T>()
168         {
169             public List<T> getItems(Indexes indexes)
170             {
171                 return getPagingCallback().getItems(indexes);
172             }
173         };
174     }
175 
176     @Override
177     public String toString()
178     {
179         return "SimpleListWrapper{" +
180                 "size=" + size +
181                 ", maxResults=" + maxResults +
182                 ", pagingCallback=" + pagingCallback +
183                 ", items=" + items +
184                 '}';
185     }
186 
187     /**
188      * Returns a new ListWrapperCallback that can be used to selectively retrieve items from the given list.
189      *
190      * @param items the List to wrap
191      * @param maxResults the maximum number of elements that the wrapper will return
192      * @return a new ListWrapperCallback
193      * @throws NullPointerException if items is null
194      * @throws IllegalArgumentException if maxResults is non-negative
195      */
196     static <T> ListWrapperCallback<T> ofList(final List<T> items, final int maxResults)
197     {
198         if (items == null) { throw new NullPointerException("items"); }
199         if (maxResults < 0) { throw new IllegalArgumentException("maxResults must be non-negative: " + maxResults); }
200 
201         return new ListWrapperCallback<T>()
202         {
203             public List<T> getItems(Indexes indexes)
204             {
205                 if (maxResults == 0)
206                 {
207                     return emptyList();
208                 }
209 
210                 int remainingResults = maxResults;
211                 final List<T> toReturn = Lists.newArrayListWithCapacity(Math.min(items.size(), maxResults));
212 
213                 for (Integer i : indexes.getIndexes(items.size()))
214                 {
215                     if (remainingResults-- == 0) { break; }
216                     toReturn.add(items.get(i));
217                 }
218 
219                 return toReturn;
220             }
221         };
222     }
223 }