2 * Copyright (C) 2009 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
9 package eu
.etaxonomy
.cdm
.remote
.controller
;
11 import java
.io
.IOException
;
12 import java
.io
.UnsupportedEncodingException
;
13 import java
.util
.ArrayList
;
14 import java
.util
.Arrays
;
15 import java
.util
.Collection
;
16 import java
.util
.List
;
18 import javax
.servlet
.http
.HttpServletRequest
;
19 import javax
.servlet
.http
.HttpServletResponse
;
21 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
22 import org
.springframework
.web
.bind
.annotation
.RequestMapping
;
24 import eu
.etaxonomy
.cdm
.api
.service
.IService
;
25 import eu
.etaxonomy
.cdm
.api
.service
.pager
.Pager
;
26 import eu
.etaxonomy
.cdm
.api
.service
.pager
.impl
.DefaultPagerImpl
;
27 import eu
.etaxonomy
.cdm
.api
.util
.UserHelper
;
28 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
29 import eu
.etaxonomy
.cdm
.persistence
.dao
.hibernate
.common
.DaoBase
;
30 import eu
.etaxonomy
.cdm
.remote
.controller
.util
.PagerParameters
;
33 * Abstract controller class for CDM Rest service controllers which return entities or DTOs
34 * from the underlying data base. Implementations of this class are primarily bound to a
35 * specific cdm service class and thus are operating primarily on a specific cdm base type.
37 * This class guarantees consistent use of init-strategies and harmonizes the logging of full
38 * request urls with query parameters.
40 * @author a.kohlbecker
46 public abstract class AbstractController
<T
extends CdmBase
, SERVICE
extends IService
<T
>> {
48 protected static final List
<String
> DEFAULT_INIT_STRATEGY
= Arrays
.asList(new String
[]{
51 protected static final Integer DEFAULT_PAGE_SIZE
= PagerParameters
.DEFAULT_PAGESIZE
;
54 * Default thread priority for long term processes which are running in
55 * separate threads. These batch processes are usually monitored with the
56 * {@link ProgressMonitorController}. This value must be lower than
57 * {@link Thread#NORM_PRIORITY}
59 public static final int DEFAULT_BATCH_THREAD_PRIORITY
= 3;
61 protected static final boolean NO_UNPUBLISHED
= DaoBase
.NO_UNPUBLISHED
;
62 protected static final boolean INCLUDE_UNPUBLISHED
= DaoBase
.INCLUDE_UNPUBLISHED
;
64 protected SERVICE service
;
67 protected UserHelper userHelper
;
69 public abstract void setService(SERVICE service
);
71 protected List
<String
> initializationStrategy
= DEFAULT_INIT_STRATEGY
;
74 * Set the default initialization strategy for this controller.
76 * @param initializationStrategy
78 public final void setInitializationStrategy(List
<String
> initializationStrategy
) {
79 this.initializationStrategy
= initializationStrategy
;
83 * Provides access to the default initialization strategy.
84 * The default initialization strategy is predefined for all controllers in
85 * {@link #DEFAULT_INIT_STRATEGY} but can be altered by
86 * concrete implementations by utilizing {@link #setInitializationStrategy(List)}
87 * in the constructor of the specific controller.
89 * @return the default initialization strategy
91 public final List
<String
> getInitializationStrategy() {
92 return this.initializationStrategy
;
96 * Returns the HTTP request path and query parameters as string
99 * @return request path and query parameters as string.
101 public static String
requestPathAndQuery(HttpServletRequest request
) {
102 if(request
== null) {
105 StringBuilder b
= new StringBuilder();
106 b
.append(request
.getMethod()).append(": ");
107 b
.append(request
.getRequestURI());
108 String query
= request
.getQueryString();
110 b
.append("?").append(query
);
117 * This method is useful to read path parameters from request urls in methods where the method has been annotated with a
118 * {@link RequestMapping} having wildcards as trailing characters like in <code>@RequestMapping("identifier/**")</code>.
120 * Reads the path part following pattern passed as <code>basePath</code> and returns it is urldecoded String.
121 * The <code>basepath</code> usually is the combination of the class level and method level RequestMappings e.g.:
122 * <code>"/registration/identifier/"</code>
125 * The base path of the controller method.
129 protected String
readPathParameter(HttpServletRequest request
, String basePath
) {
130 String pathParameter
= request
.getRequestURI().replaceFirst("^(?:.*)" + basePath
, "");
131 if(pathParameter
!= null){
133 pathParameter
= java
.net
.URLDecoder
.decode(pathParameter
, "UTF-8");
134 pathParameter
= pathParameter
.replaceAll("\\.json$|\\.xml$", "");
135 } catch (UnsupportedEncodingException e
) {
136 // should never happen
137 throw new RuntimeException(e
);
140 return pathParameter
;
143 protected <T
extends CdmBase
> Pager
<T
> pagerForSubCollectionOf(Collection
<T
> c
, Integer pageNumber
, Integer pageSize
, HttpServletResponse response
) throws IOException
{
144 PagerParameters pagerParameters
= new PagerParameters(pageSize
, pageNumber
);
145 pagerParameters
.normalizeAndValidate(response
);
147 int subCollectionStart
= pagerParameters
.getPageIndex() * pagerParameters
.getPageSize();
148 List
<T
> sub_c
= subCollection(c
, subCollectionStart
, pagerParameters
.getPageSize());
149 Pager
<T
> p
= new DefaultPagerImpl
<>(pageNumber
, c
.size(), pagerParameters
.getPageSize(), sub_c
);
153 protected <E
> List
<E
> subCollection(Collection
<?
extends E
> c
, Integer start
, Integer length
) {
154 List
<E
> sub_c
= new ArrayList
<E
>(length
);
155 if(c
.size() > length
){
156 E
[] a
= (E
[]) c
.toArray();
157 for(int i
= start
; i
< start
+ length
; i
++){