Coverage Report - com.jcabi.github.RtSearchPagination
 
Classes in this File Line Coverage Branch Coverage Complexity
RtSearchPagination
85%
6/7
0%
0/4
1.321
RtSearchPagination$Hidden
42%
8/19
N/A
1.321
RtSearchPagination$SearchRequest
41%
5/12
N/A
1.321
RtSearchPagination$SearchURI
0%
0/13
0%
0/10
1.321
 
 1  2
 /**
 2  
  * Copyright (c) 2013-2015, jcabi.com
 3  
  * All rights reserved.
 4  
  *
 5  
  * Redistribution and use in source and binary forms, with or without
 6  
  * modification, are permitted provided that the following conditions
 7  
  * are met: 1) Redistributions of source code must retain the above
 8  
  * copyright notice, this list of conditions and the following
 9  
  * disclaimer. 2) Redistributions in binary form must reproduce the above
 10  
  * copyright notice, this list of conditions and the following
 11  
  * disclaimer in the documentation and/or other materials provided
 12  
  * with the distribution. 3) Neither the name of the jcabi.com nor
 13  
  * the names of its contributors may be used to endorse or promote
 14  
  * products derived from this software without specific prior written
 15  
  * permission.
 16  
  *
 17  
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 18  
  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
 19  
  * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 20  
  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 21  
  * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 22  
  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 23  
  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 24  
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 25  
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 26  
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 27  
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 28  
  * OF THE POSSIBILITY OF SUCH DAMAGE.
 29  
  */
 30  
 package com.jcabi.github;
 31  
 
 32  
 import com.jcabi.aspects.Immutable;
 33  
 import com.jcabi.http.Request;
 34  
 import com.jcabi.http.RequestBody;
 35  
 import com.jcabi.http.RequestURI;
 36  
 import com.jcabi.http.Response;
 37  
 import com.jcabi.http.Wire;
 38  
 import java.io.IOException;
 39  
 import java.io.InputStream;
 40  
 import java.io.StringReader;
 41  
 import java.lang.reflect.InvocationTargetException;
 42  
 import java.net.URI;
 43  
 import java.util.Iterator;
 44  
 import java.util.List;
 45  
 import java.util.Map;
 46  
 import javax.json.Json;
 47  
 import javax.json.JsonObject;
 48  
 import javax.validation.constraints.NotNull;
 49  
 import lombok.EqualsAndHashCode;
 50  
 
 51  
 /**
 52  
  * Github search pagination.
 53  
  *
 54  
  * @author Alexander Sinyagin (sinyagin.alexander@gmail.com)
 55  
  * @version $Id$
 56  
  * @param <T> Type of iterable objects
 57  
  */
 58  
 @Immutable
 59  0
 @EqualsAndHashCode
 60  
 @SuppressWarnings("PMD.TooManyMethods")
 61  
 final class RtSearchPagination<T> implements Iterable<T> {
 62  
 
 63  
     /**
 64  
      * Search request.
 65  
      */
 66  
     private final transient Request request;
 67  
 
 68  
     /**
 69  
      * Pagination mapping.
 70  
      */
 71  
     private final transient RtValuePagination.Mapping<T, JsonObject> mapping;
 72  
 
 73  
     /**
 74  
      * Ctor.
 75  
      * @param req RESTful API entry point
 76  
      * @param path Search path
 77  
      * @param keywords Search keywords
 78  
      * @param sort Sort field
 79  
      * @param order Sort order
 80  
      * @param mppng Pagination mapping
 81  
      * @checkstyle ParameterNumber (4 lines)
 82  
      */
 83  
     RtSearchPagination(final Request req, final String path,
 84  
         final String keywords, final String sort, final String order,
 85  5
         final RtValuePagination.Mapping<T, JsonObject> mppng) {
 86  5
         this.request = req.uri().path(path)
 87  
             .queryParam("q", keywords)
 88  
             .queryParam("sort", sort)
 89  
             .queryParam("order", order)
 90  
             .back();
 91  5
         this.mapping = mppng;
 92  5
     }
 93  
 
 94  
     @Override
 95  
     @NotNull(message = "Iterator is never NULL")
 96  
     public Iterator<T> iterator() {
 97  5
         return new RtPagination<T>(
 98  
             new RtSearchPagination.SearchRequest(this.request), this.mapping
 99  
         ).iterator();
 100  
     }
 101  
 
 102  
     /**
 103  
      * Request which hides everything but items.
 104  
      */
 105  
     @SuppressWarnings({ "PMD.TooManyMethods", "PMD.CyclomaticComplexity" })
 106  
     private static final class SearchRequest implements Request {
 107  
         /**
 108  
          * Inner request.
 109  
          */
 110  
         private final transient Request request;
 111  
         /**
 112  
          * Ctor.
 113  
          * @param req Request to wrap
 114  
          */
 115  
         SearchRequest(@NotNull(message = "request can't be NULL")
 116  5
             final Request req) {
 117  5
             this.request = req;
 118  5
         }
 119  
         @Override
 120  
         @NotNull(message = "Request isn't ever NULL")
 121  
         public RequestURI uri() {
 122  0
             return new SearchURI(this.request.uri());
 123  
         }
 124  
         @Override
 125  
         @NotNull(message = "body is never NULL")
 126  
         public RequestBody body() {
 127  0
             return this.request.body();
 128  
         }
 129  
         @Override
 130  
         @NotNull(message = "header is nerver NULL")
 131  
         public Request header(@NotNull(message = "header name can't be NULL")
 132  
             final String name, @NotNull(message = "header value can't be NULL")
 133  
             final Object value) {
 134  0
             return new SearchRequest(this.request.header(name, value));
 135  
         }
 136  
         @Override
 137  
         @NotNull(message = "Request is nerver NULL")
 138  
         public Request reset(@NotNull(message = "header name can't be NULL")
 139  
             final String name) {
 140  0
             return new SearchRequest(this.request.reset(name));
 141  
         }
 142  
         @Override
 143  
         @NotNull(message = "Request is never NULL")
 144  
         public Request method(@NotNull(message = "method can't be NULL")
 145  
             final String method) {
 146  0
             return new SearchRequest(this.request.method(method));
 147  
         }
 148  
         /**
 149  
          * Hide everything from the body but items.
 150  
          * @return Response
 151  
          * @throws IOException If any I/O problem occurs
 152  
          */
 153  
         @Override
 154  
         @NotNull(message = "Response is never NULL")
 155  
         public Response fetch() throws IOException {
 156  5
             return new RtSearchPagination.Hidden(this.request.fetch());
 157  
         }
 158  
         @Override
 159  
         public Response fetch(final InputStream stream) throws IOException {
 160  0
             return new RtSearchPagination.Hidden(this.request.fetch(stream));
 161  
         }
 162  
         @Override
 163  
         @NotNull(message = "Request should never be NULL")
 164  
         public <T extends Wire> Request through(final Class<T> type,
 165  
             final Object... args) {
 166  0
             return new SearchRequest(this.request.through(type, args));
 167  
         }
 168  
     }
 169  
 
 170  
     /**
 171  
      * Response to return.
 172  
      */
 173  
     @Immutable
 174  
     private static final class Hidden implements Response {
 175  
         /**
 176  
          * Original response.
 177  
          */
 178  
         private final transient Response response;
 179  
         /**
 180  
          * Ctor.
 181  
          * @param resp Response
 182  
          */
 183  5
         Hidden(final Response resp) {
 184  5
             this.response = resp;
 185  5
         }
 186  
         @Override
 187  
         @NotNull(message = "Request cannot be NULL")
 188  
         public Request back() {
 189  0
             return new SearchRequest(this.response.back());
 190  
         }
 191  
         @Override
 192  
         public int status() {
 193  5
             return this.response.status();
 194  
         }
 195  
         @Override
 196  
         @NotNull(message = "reason is never NULL")
 197  
         public String reason() {
 198  0
             return this.response.reason();
 199  
         }
 200  
         @Override
 201  
         @NotNull(message = "headers is never NULL")
 202  
         public Map<String, List<String>> headers() {
 203  5
             return this.response.headers();
 204  
         }
 205  
         @Override
 206  
         @NotNull(message = "body is never NULL")
 207  
         public String body() {
 208  5
             return Json.createReader(new StringReader(this.response.body()))
 209  
                 .readObject().getJsonArray("items").toString();
 210  
         }
 211  
         @Override
 212  
         public byte[] binary() {
 213  0
             return this.response.binary();
 214  
         }
 215  
         // @checkstyle MethodName (4 lines)
 216  
         @Override
 217  
         @SuppressWarnings("PMD.ShortMethodName")
 218  
         @NotNull(message = "T is never NULL")
 219  
         public <T extends Response> T as(final Class<T> type) {
 220  
             try {
 221  15
                 return type.getDeclaredConstructor(Response.class)
 222  
                     .newInstance(this);
 223  0
             } catch (final InstantiationException ex) {
 224  0
                 throw new IllegalStateException(ex);
 225  0
             } catch (final IllegalAccessException ex) {
 226  0
                 throw new IllegalStateException(ex);
 227  0
             } catch (final InvocationTargetException ex) {
 228  0
                 throw new IllegalStateException(ex);
 229  0
             } catch (final NoSuchMethodException ex) {
 230  0
                 throw new IllegalStateException(ex);
 231  
             }
 232  
         }
 233  
     }
 234  
 
 235  
     /**
 236  
      * Wrapper of RequestURI that returns {@link SearchRequest}.
 237  
      */
 238  
     @Immutable
 239  0
     @EqualsAndHashCode(of = "address")
 240  
     private static final class SearchURI implements RequestURI {
 241  
         /**
 242  
          * Underlying address.
 243  
          */
 244  
         private final transient RequestURI address;
 245  
         /**
 246  
          * Ctor.
 247  
          * @param uri The URI
 248  
          */
 249  0
         public SearchURI(final RequestURI uri) {
 250  0
             this.address = uri;
 251  0
         }
 252  
         @Override
 253  
         public Request back() {
 254  0
             return new SearchRequest(this.address.back());
 255  
         }
 256  
         @Override
 257  
         public URI get() {
 258  0
             return this.address.get();
 259  
         }
 260  
         @Override
 261  
         public RequestURI set(final URI uri) {
 262  0
             return new SearchURI(this.address.set(uri));
 263  
         }
 264  
         @Override
 265  
         public RequestURI queryParam(final String name, final Object value) {
 266  0
             return new SearchURI(this.address.queryParam(name, value));
 267  
         }
 268  
         @Override
 269  
         public RequestURI queryParams(final Map<String, String> map) {
 270  0
             return new SearchURI(this.address.queryParams(map));
 271  
         }
 272  
         @Override
 273  
         public RequestURI path(final String segment) {
 274  0
             return new SearchURI(this.address.path(segment));
 275  
         }
 276  
         @Override
 277  
         public RequestURI userInfo(final String info) {
 278  0
             return new SearchURI(this.address.userInfo(info));
 279  
         }
 280  
         @Override
 281  
         public RequestURI port(final int num) {
 282  0
             return new SearchURI(this.address.port(num));
 283  
         }
 284  
     }
 285  
 }