443f4ea763d5322c9773b77a3f05ac9d9c5371d2
[cdmlib.git] / cdmlib-remote / src / main / java / eu / etaxonomy / cdm / remote / controller / ext / KmlController.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.ext;
10
11 import java.awt.Color;
12 import java.io.IOException;
13 import java.util.ArrayList;
14 import java.util.Arrays;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Set;
18 import java.util.UUID;
19 import java.util.stream.Collectors;
20
21 import javax.servlet.http.HttpServletRequest;
22 import javax.servlet.http.HttpServletResponse;
23
24 import org.apache.logging.log4j.LogManager;
25 import org.apache.logging.log4j.Logger;
26 import org.springframework.beans.factory.annotation.Autowired;
27 import org.springframework.http.HttpStatus;
28 import org.springframework.http.ResponseEntity;
29 import org.springframework.stereotype.Controller;
30 import org.springframework.web.bind.WebDataBinder;
31 import org.springframework.web.bind.annotation.CrossOrigin;
32 import org.springframework.web.bind.annotation.InitBinder;
33 import org.springframework.web.bind.annotation.PathVariable;
34 import org.springframework.web.bind.annotation.RequestMapping;
35 import org.springframework.web.bind.annotation.RequestMethod;
36 import org.springframework.web.bind.annotation.RequestParam;
37
38 import de.micromata.opengis.kml.v_2_2_0.Kml;
39 import eu.etaxonomy.cdm.api.service.INameService;
40 import eu.etaxonomy.cdm.api.service.IOccurrenceService;
41 import eu.etaxonomy.cdm.api.service.ITaxonService;
42 import eu.etaxonomy.cdm.api.service.ITermService;
43 import eu.etaxonomy.cdm.api.util.TaxonRelationshipEdge;
44 import eu.etaxonomy.cdm.database.UpdatableRoutingDataSource;
45 import eu.etaxonomy.cdm.ext.geo.IEditGeoService;
46 import eu.etaxonomy.cdm.model.common.MarkerType;
47 import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;
48 import eu.etaxonomy.cdm.model.name.TypeDesignationBase;
49 import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
50 import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationType;
51 import eu.etaxonomy.cdm.model.taxon.Taxon;
52 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
53 import eu.etaxonomy.cdm.persistence.query.OrderHint;
54 import eu.etaxonomy.cdm.persistence.query.OrderHint.SortOrder;
55 import eu.etaxonomy.cdm.remote.controller.BaseController;
56 import eu.etaxonomy.cdm.remote.controller.OptionsController;
57 import eu.etaxonomy.cdm.remote.controller.util.ControllerUtils;
58 import eu.etaxonomy.cdm.remote.editor.DefinedTermBaseList;
59 import eu.etaxonomy.cdm.remote.editor.TermBaseListPropertyEditor;
60 import eu.etaxonomy.cdm.remote.editor.UUIDListPropertyEditor;
61 import eu.etaxonomy.cdm.remote.editor.UuidList;
62 import io.swagger.annotations.Api;
63
64 /**
65 * The ExternalGeoController class is a Spring MVC Controller.
66 * <p>
67 * The syntax of the mapped service URIs contains the the {datasource-name} path element.
68 * The available {datasource-name}s are defined in a configuration file which
69 * is loaded by the {@link UpdatableRoutingDataSource}. If the
70 * UpdatableRoutingDataSource is not being used in the actual application
71 * context any arbitrary {datasource-name} may be used.
72 * <p>
73 * @author a.kohlbecker
74 * @since 18.06.2009
75 */
76 @CrossOrigin(origins = "*")
77 @Controller
78 @Api(value="mapServiceParameters")
79 @RequestMapping(value = { "kml" })
80 public class KmlController extends BaseController<TaxonBase, ITaxonService> {
81
82 private static final Logger logger = LogManager.getLogger();
83
84 @Autowired
85 private IEditGeoService geoservice;
86
87 @Autowired
88 private IOccurrenceService occurrenceService;
89
90 @Autowired
91 private INameService nameService;
92
93 @Autowired
94 private ITermService termService;
95
96 @InitBinder
97 @Override
98 public void initBinder(WebDataBinder binder) {
99 super.initBinder(binder);
100 binder.registerCustomEditor(UuidList.class, new UUIDListPropertyEditor());
101 binder.registerCustomEditor(DefinedTermBaseList.class, new TermBaseListPropertyEditor<MarkerType>(termService));
102 }
103
104 @Autowired
105 @Override
106 public void setService(ITaxonService service) {
107 this.service = service;
108 }
109
110 /**
111 * TODO This controller method replaces the general {@link OptionsController} which has been disabled temporarily.
112 * The {@link OptionsController} was causing problems in some situations by blocking POST requests to other controllers.
113 * This mainly happened in the taxeditor project where the integration test could not be run due to the cdm remote instance which
114 * did not allow POST requests to the /remoting-public/user.service
115 */
116 @RequestMapping(
117 value = "/**",
118 method = RequestMethod.OPTIONS
119 )
120 public ResponseEntity options() {
121 return new ResponseEntity(HttpStatus.OK);
122 }
123
124 /**
125 * Assembles and returns URI parameter Strings for the EDIT Map Service. The distribution areas for the
126 * {@link Taxon} instance identified by the <code>{taxon-uuid}</code> are found and are translated into
127 * an valid URI parameter String. Higher level distribution areas are expanded in order to include all
128 * nested sub-areas.
129 * <p>
130 * URI: <b>&#x002F;{datasource-name}&#x002F;geo&#x002F;map&#x002F;distribution&#x002F;{taxon-uuid}</b>
131 *
132 * @param request
133 * @param response
134 * @return URI parameter Strings for the EDIT Map Service
135 * @throws IOException TODO write controller method documentation
136 */
137 @RequestMapping(value = { "specimensOrOccurences/{uuid-list}" }, method = RequestMethod.GET)
138 public Kml doGetSpecimensOrOccurencesKml(
139 @PathVariable("uuid-list") UuidList uuidList,
140 HttpServletRequest request,
141 HttpServletResponse response)
142 throws IOException {
143
144
145 logger.info("doGetSpecimensOrOccurencesKml() " + requestPathAndQuery(request));
146
147 Map<SpecimenOrObservationType, Color> specimenOrObservationTypeColors = null;
148
149 List<SpecimenOrObservationBase> specimensOrObersvations = occurrenceService.load(uuidList, null);
150
151 specimensOrObersvations = specimensOrObersvations.stream().filter(s -> s != null).collect(Collectors.toList());
152
153 Kml kml = geoservice.occurrencesToKML(specimensOrObersvations, specimenOrObservationTypeColors);
154
155 return kml;
156 }
157
158 /**
159 * Assembles and returns URI parameter Strings for the EDIT Map Service. The distribution areas for the
160 * {@link Taxon} instance identified by the <code>{taxon-uuid}</code> are found and are translated into
161 * an valid URI parameter String. Higher level distribution areas are expanded in order to include all
162 * nested sub-areas.
163 * <p>
164 * URI: <b>&#x002F;{datasource-name}&#x002F;geo&#x002F;map&#x002F;distribution&#x002F;{taxon-uuid}</b>
165 *
166 * @param request
167 * @param response
168 * @return URI parameter Strings for the EDIT Map Service
169 * @throws IOException TODO write controller method documentation
170 */
171 @RequestMapping(value = { "typeDesignations/{uuid-list}" }, method = RequestMethod.GET)
172 public Kml doGetTypeDesignationsKml(
173 @PathVariable("uuid-list") UuidList uuidList,
174 HttpServletRequest request,
175 HttpServletResponse response)
176 throws IOException {
177
178
179 logger.info("doGetTypeDesignationsKml() " + requestPathAndQuery(request));
180
181 Map<SpecimenOrObservationType, Color> specimenOrObservationTypeColors = null;
182
183 List<TypeDesignationBase<?>> typeDesignations = nameService.loadTypeDesignations(uuidList, Arrays.asList("typeSpecimen"));
184
185 List<SpecimenOrObservationBase> specimensOrObersvations = typeDesignations.stream()
186 .filter(td -> td != null && td instanceof SpecimenTypeDesignation)
187 .map(SpecimenTypeDesignation.class::cast)
188 .map(SpecimenTypeDesignation::getTypeSpecimen)
189 .filter(s -> s != null)
190 .collect(Collectors.toList());
191
192 Kml kml = geoservice.occurrencesToKML(specimensOrObersvations, specimenOrObservationTypeColors);
193
194 return kml;
195 }
196
197 /**
198 * Assembles and returns URI parameter Strings for the EDIT Map Service. The distribution areas for the
199 * {@link Taxon} instance identified by the <code>{taxon-uuid}</code> are found and are translated into
200 * an valid URI parameter String. Higher level distribution areas are expanded in order to include all
201 * nested sub-areas.
202 * <p>
203 * URI: <b>&#x002F;{datasource-name}&#x002F;geo&#x002F;map&#x002F;distribution&#x002F;{taxon-uuid}</b>
204 *
205 * @param request
206 * @param response
207 * @return URI parameter Strings for the EDIT Map Service
208 * @throws IOException TODO write controller method documentation
209 */
210 @RequestMapping(value = { "taxonOccurrencesFor/{uuid}" }, method = RequestMethod.GET)
211 public Kml doGetTaxonOccurrenceKml(
212 @PathVariable("uuid") UUID uuid,
213 @RequestParam(value = "relationships", required = false) UuidList relationshipUuids,
214 @RequestParam(value = "relationshipsInvers", required = false) UuidList relationshipInversUuids,
215 @RequestParam(value = "maxDepth", required = false) Integer maxDepth,
216 HttpServletRequest request,
217 HttpServletResponse response)
218 throws IOException {
219
220
221 logger.info("doGetTaxonOccurrenceKml() " + requestPathAndQuery(request));
222
223 Map<SpecimenOrObservationType, Color> specimenOrObservationTypeColors = null;
224
225 List<SpecimenOrObservationBase> specimensOrObersvations = occurencesForTaxon(uuid, relationshipUuids,
226 relationshipInversUuids, maxDepth, response);
227
228 Kml kml = geoservice.occurrencesToKML(specimensOrObersvations, specimenOrObservationTypeColors);
229
230 return kml;
231 }
232
233 private List<SpecimenOrObservationBase> occurencesForTaxon(UUID taxonUuid, UuidList relationshipUuids,
234 UuidList relationshipInversUuids, Integer maxDepth, HttpServletResponse response) throws IOException {
235 Set<TaxonRelationshipEdge> includeRelationships = ControllerUtils.loadIncludeRelationships(
236 relationshipUuids, relationshipInversUuids, termService);
237
238 Taxon taxon = getCdmBaseInstance(Taxon.class, taxonUuid, response, (List<String>)null);
239
240 List<OrderHint> orderHints = new ArrayList<>();
241 orderHints.add(new OrderHint("titleCache", SortOrder.DESCENDING));
242
243 List<SpecimenOrObservationBase> specimensOrObersvations = occurrenceService.listByAssociatedTaxon(
244 null, includeRelationships, taxon, maxDepth, null, null, orderHints, null);
245 return specimensOrObersvations;
246 }
247
248
249 }