11/*
22 * SysML v2 REST/HTTP Pilot Implementation
3- * Copyright (C) 2020 InterCAX LLC
4- * Copyright (C) 2020 California Institute of Technology ("Caltech")
3+ * Copyright (C) 2020 InterCAX LLC
4+ * Copyright (C) 2020 California Institute of Technology ("Caltech")
5+ * Copyright (C) 2022 Twingineer LLC
56 *
67 * This program is free software: you can redistribute it and/or modify
78 * it under the terms of the GNU Lesser General Public License as published by
@@ -37,67 +38,88 @@ public abstract class BaseController extends Controller {
3738 protected static char CURSOR_SEPARATOR = '|' ;
3839 protected static int DEFAULT_PAGE_SIZE = 100 ;
3940
40- protected static UUID fromCursor (String cursor ) throws IllegalArgumentException {
41+ private static String stringFromCursor (String cursor ) throws IllegalArgumentException {
4142 byte [] decoded = Base64 .getUrlDecoder ().decode (cursor );
4243 int separatorIndex = Bytes .indexOf (decoded , (byte ) CURSOR_SEPARATOR );
4344 if (separatorIndex < 0 ) {
4445 throw new IllegalArgumentException ("Provided cursor is malformed" );
4546 }
46- return UUID .fromString (
47- new String (decoded , separatorIndex + 1 , decoded .length - separatorIndex - 1 )
48- );
47+ return new String (decoded , separatorIndex + 1 , decoded .length - separatorIndex - 1 );
4948 }
5049
51- protected static String toCursor ( UUID id ) throws IllegalArgumentException {
50+ private static String stringToCursor ( String string ) {
5251 String unencoded = String .valueOf (Instant .now ().toEpochMilli ()) +
5352 CURSOR_SEPARATOR +
54- id . toString () ;
53+ string ;
5554 return Base64 .getUrlEncoder ().withoutPadding ().encodeToString (unencoded .getBytes ());
5655 }
5756
58- protected static class PageRequest {
59- private final UUID after ;
60- private final UUID before ;
57+ private static UUID uuidFromCursor (String cursor ) throws IllegalArgumentException {
58+ return UUID .fromString (stringFromCursor (cursor ));
59+ }
60+
61+ private static String uuidToCursor (UUID id ) throws IllegalArgumentException {
62+ return stringToCursor (id .toString ());
63+ }
64+
65+ protected static class PageRequest <T > {
66+ private final T after ;
67+ private final T before ;
6168 private final int size ;
6269
63- private PageRequest (UUID after , UUID before , int size ) {
70+ private PageRequest (T after , T before , int size ) {
71+ if (size <= 0 ) {
72+ throw new IllegalArgumentException ("Page size must be greater than zero" );
73+ }
74+
6475 this .after = after ;
6576 this .before = before ;
6677 this .size = size ;
6778 }
6879
69- public UUID getAfter () {
80+ public T getAfter () {
7081 return after ;
7182 }
7283
73- public UUID getBefore () {
84+ public T getBefore () {
7485 return before ;
7586 }
7687
7788 public int getSize () {
7889 return size ;
7990 }
91+ }
8092
81- protected static PageRequest from (Http .Request request ) throws IllegalArgumentException {
82- UUID after = Optional .ofNullable (request .getQueryString ("page[after]" ))
83- .map (BaseController ::fromCursor )
84- //.map(UUID::fromString)
85- .orElse (null );
86- UUID before = Optional .ofNullable (request .getQueryString ("page[before]" ))
87- .map (BaseController ::fromCursor )
88- //.map(UUID::fromString)
89- .orElse (null );
90- int size = Optional .ofNullable (request .getQueryString ("page[size]" ))
91- .map (Integer ::parseInt )
92- .orElse (DEFAULT_PAGE_SIZE );
93- if (size <= 0 ) {
94- throw new IllegalArgumentException ("Page size must be greater than zero" );
95- }
96- return new PageRequest (after , before , size );
97- }
93+ protected static PageRequest <UUID > uuidRequest (Http .Request request ) throws IllegalArgumentException {
94+ return request (request , BaseController ::uuidFromCursor );
95+ }
96+
97+ protected static PageRequest <String > stringRequest (Http .Request request ) throws IllegalArgumentException {
98+ return request (request , BaseController ::stringFromCursor );
99+ }
100+
101+ private static <T > PageRequest <T > request (Http .Request request , Function <String , T > decoder ) throws IllegalArgumentException {
102+ T after = Optional .ofNullable (request .getQueryString ("page[after]" ))
103+ .map (decoder )
104+ .orElse (null );
105+ T before = Optional .ofNullable (request .getQueryString ("page[before]" ))
106+ .map (decoder )
107+ .orElse (null );
108+ int size = Optional .ofNullable (request .getQueryString ("page[size]" ))
109+ .map (Integer ::parseInt )
110+ .orElse (DEFAULT_PAGE_SIZE );
111+ return new PageRequest <>(after , before , size );
112+ }
113+
114+ protected static Result uuidResponse (Result result , int resultSize , Function <Integer , UUID > idAtIndex , Http .Request request , PageRequest <UUID > pageRequest ) {
115+ return response (result , resultSize , idAtIndex , request , pageRequest , BaseController ::uuidToCursor );
116+ }
117+
118+ protected static Result stringResponse (Result result , int resultSize , Function <Integer , String > idAtIndex , Http .Request request , PageRequest <String > pageRequest ) {
119+ return response (result , resultSize , idAtIndex , request , pageRequest , BaseController ::stringToCursor );
98120 }
99121
100- protected static Result paginateResult (Result result , int resultSize , Function <Integer , UUID > idAtIndex , Http .Request request , PageRequest pageRequest ) {
122+ private static < T > Result response (Result result , int resultSize , Function <Integer , T > idAtIndex , Http .Request request , PageRequest < T > pageRequest , Function < T , String > encoder ) {
101123 if (resultSize > 0 ) {
102124 boolean pageFull = resultSize == pageRequest .getSize ();
103125 boolean hasNext = pageFull || pageRequest .getBefore () != null ;
@@ -108,7 +130,7 @@ protected static Result paginateResult(Result result, int resultSize, Function<I
108130 linkHeaderValueBuilder .append (String .format ("<http://%s%s?page[after]=%s&page[size]=%s>; rel=\" next\" " ,
109131 request .host (),
110132 request .path (),
111- toCursor (idAtIndex .apply (resultSize - 1 )),
133+ encoder . apply (idAtIndex .apply (resultSize - 1 )),
112134 pageRequest .getSize ()));
113135 if (hasPrev ) {
114136 linkHeaderValueBuilder .append (", " );
@@ -118,7 +140,7 @@ protected static Result paginateResult(Result result, int resultSize, Function<I
118140 linkHeaderValueBuilder .append (String .format ("<http://%s%s?page[before]=%s&page[size]=%s>; rel=\" prev\" " ,
119141 request .host (),
120142 request .path (),
121- toCursor (idAtIndex .apply (0 )),
143+ encoder . apply (idAtIndex .apply (0 )),
122144 pageRequest .getSize ()));
123145 }
124146 if (linkHeaderValueBuilder .length () > 0 ) {
0 commit comments