Merge branch 'release/5.45.0'
[cdmlib.git] / cdmlib-remote / src / main / java / eu / etaxonomy / cdm / remote / controller / AbstractController.java
1 /**
2 * Copyright (C) 2009 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
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.
8 */
9 package eu.etaxonomy.cdm.remote.controller;
10
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;
17
18 import javax.servlet.http.HttpServletRequest;
19 import javax.servlet.http.HttpServletResponse;
20
21 import org.springframework.beans.factory.annotation.Autowired;
22 import org.springframework.web.bind.annotation.RequestMapping;
23
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;
31
32 /**
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.
36 *
37 * This class guarantees consistent use of init-strategies and harmonizes the logging of full
38 * request urls with query parameters.
39 *
40 * @author a.kohlbecker
41 * @since 23.06.2009
42 *
43 * @param <T>
44 * @param <SERVICE>
45 */
46 public abstract class AbstractController<T extends CdmBase, SERVICE extends IService<T>> {
47
48 protected static final List<String> DEFAULT_INIT_STRATEGY = Arrays.asList(new String []{
49 "$"
50 });
51 protected static final Integer DEFAULT_PAGE_SIZE = PagerParameters.DEFAULT_PAGESIZE;
52
53 /**
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}
58 */
59 public static final int DEFAULT_BATCH_THREAD_PRIORITY = 3;
60
61 protected static final boolean NO_UNPUBLISHED = DaoBase.NO_UNPUBLISHED;
62 protected static final boolean INCLUDE_UNPUBLISHED = DaoBase.INCLUDE_UNPUBLISHED;
63
64 protected SERVICE service;
65
66 @Autowired
67 protected UserHelper userHelper;
68
69 public abstract void setService(SERVICE service);
70
71 protected List<String> initializationStrategy = DEFAULT_INIT_STRATEGY;
72
73 /**
74 * Set the default initialization strategy for this controller.
75 *
76 * @param initializationStrategy
77 */
78 public final void setInitializationStrategy(List<String> initializationStrategy) {
79 this.initializationStrategy = initializationStrategy;
80 }
81
82 /**
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.
88 *
89 * @return the default initialization strategy
90 */
91 public final List<String> getInitializationStrategy() {
92 return this.initializationStrategy;
93 }
94
95 /**
96 * Returns the HTTP request path and query parameters as string
97 *
98 * @param request
99 * @return request path and query parameters as string.
100 */
101 public static String requestPathAndQuery(HttpServletRequest request) {
102 if(request == null) {
103 return "";
104 }
105 StringBuilder b = new StringBuilder();
106 b.append(request.getMethod()).append(": ");
107 b.append(request.getRequestURI());
108 String query = request.getQueryString();
109 if(query != null) {
110 b.append("?").append(query);
111 }
112
113 return b.toString();
114 }
115
116 /**
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>.
119 * <p>
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>
123 *
124 * @param basePath
125 * The base path of the controller method.
126 * @param request
127 * @return
128 */
129 protected String readPathParameter(HttpServletRequest request, String basePath) {
130 String pathParameter = request.getRequestURI().replaceFirst("^(?:.*)" + basePath , "");
131 if(pathParameter != null){
132 try {
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);
138 }
139 }
140 return pathParameter;
141 }
142
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);
146
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);
150 return p;
151 }
152
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++){
158 sub_c.add(a[i]);
159 }
160 } else {
161 sub_c.addAll(c);
162 }
163 return sub_c;
164
165 }
166
167 }