Project

General

Profile

Download (33 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2007 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

    
10
package eu.etaxonomy.cdm.remote.controller;
11

    
12
import java.io.IOException;
13
import java.util.ArrayList;
14
import java.util.Arrays;
15
import java.util.Hashtable;
16
import java.util.Iterator;
17
import java.util.List;
18
import java.util.Map;
19
import java.util.Set;
20
import java.util.UUID;
21

    
22
import javax.servlet.http.HttpServletRequest;
23
import javax.servlet.http.HttpServletResponse;
24

    
25
import org.apache.log4j.Logger;
26
import org.springframework.beans.factory.annotation.Autowired;
27
import org.springframework.stereotype.Controller;
28
import org.springframework.web.bind.WebDataBinder;
29
import org.springframework.web.bind.annotation.InitBinder;
30
import org.springframework.web.bind.annotation.PathVariable;
31
import org.springframework.web.bind.annotation.RequestMapping;
32
import org.springframework.web.bind.annotation.RequestMethod;
33
import org.springframework.web.bind.annotation.RequestParam;
34
import org.springframework.web.servlet.ModelAndView;
35

    
36
import eu.etaxonomy.cdm.api.service.INameService;
37
import eu.etaxonomy.cdm.api.service.ITaxonNodeService;
38
import eu.etaxonomy.cdm.api.service.ITaxonService;
39
import eu.etaxonomy.cdm.api.service.ITermService;
40
import eu.etaxonomy.cdm.api.util.TaxonRelationshipEdge;
41
import eu.etaxonomy.cdm.database.UpdatableRoutingDataSource;
42
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
43
import eu.etaxonomy.cdm.model.common.CdmBase;
44
import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
45
import eu.etaxonomy.cdm.model.common.RelationshipBase.Direction;
46
import eu.etaxonomy.cdm.model.location.NamedArea;
47
import eu.etaxonomy.cdm.model.media.Media;
48
import eu.etaxonomy.cdm.model.media.MediaRepresentationPart;
49
import eu.etaxonomy.cdm.model.name.NameRelationship;
50
import eu.etaxonomy.cdm.model.taxon.Synonym;
51
import eu.etaxonomy.cdm.model.taxon.Taxon;
52
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
53
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
54
import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
55
import eu.etaxonomy.cdm.persistence.dao.initializer.EntityInitStrategy;
56
import eu.etaxonomy.cdm.persistence.query.MatchMode;
57
import eu.etaxonomy.cdm.remote.controller.util.ControllerUtils;
58
import eu.etaxonomy.cdm.remote.controller.util.IMediaToolbox;
59
import eu.etaxonomy.cdm.remote.editor.CdmTypePropertyEditor;
60
import eu.etaxonomy.cdm.remote.editor.DefinedTermBaseList;
61
import eu.etaxonomy.cdm.remote.editor.MatchModePropertyEditor;
62
import eu.etaxonomy.cdm.remote.editor.NamedAreaPropertyEditor;
63
import eu.etaxonomy.cdm.remote.editor.TermBaseListPropertyEditor;
64
import eu.etaxonomy.cdm.remote.editor.UUIDListPropertyEditor;
65
import eu.etaxonomy.cdm.remote.editor.UuidList;
66
import io.swagger.annotations.Api;
67

    
68
/**
69
 * The TaxonPortalController class is a Spring MVC Controller.
70
 * <p>
71
 * The syntax of the mapped service URIs contains the the {datasource-name} path element.
72
 * The available {datasource-name}s are defined in a configuration file which
73
 * is loaded by the {@link UpdatableRoutingDataSource}. If the
74
 * UpdatableRoutingDataSource is not being used in the actual application
75
 * context any arbitrary {datasource-name} may be used.
76
 * <p>
77
 * Methods mapped at type level, inherited from super classes ({@link BaseController}):
78
 * <blockquote>
79
 * URI: <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-uuid}</b>
80
 *
81
 * Get the {@link TaxonBase} instance identified by the <code>{taxon-uuid}</code>.
82
 * The returned Taxon is initialized by
83
 * the following strategy {@link #TAXON_INIT_STRATEGY}
84
 * </blockquote>
85
 *
86
 * @author a.kohlbecker
87
 * @since 20.07.2009
88
 *
89
 */
90
@Controller
91
@Api("portal_taxon")
92
@RequestMapping(value = {"/portal/taxon/{uuid}"})
93
public class TaxonPortalController extends TaxonController{
94

    
95
    public static final Logger logger = Logger.getLogger(TaxonPortalController.class);
96

    
97
    @Autowired
98
    private INameService nameService;
99

    
100
    @Autowired
101
    private ITaxonNodeService taxonNodeService;
102

    
103
    @Autowired
104
    private ITaxonService taxonService;
105

    
106
    @Autowired
107
    private ITermService termService;
108

    
109
    @Autowired
110
    private IMediaToolbox mediaToolbox;
111

    
112

    
113
    public static final EntityInitStrategy TAXON_INIT_STRATEGY = new EntityInitStrategy(Arrays.asList(new String []{
114
            "$",
115
            "sources",
116
            "statusNote",
117
            "relationsFromThisTaxon.toTaxon.secSource.citation.authorship",
118
            "relationsFromThisTaxon.toTaxon.secSource.citation.inReference.authorship",
119
            "relationsToThisTaxon.fromTaxon.secSource.citation.authorship",
120
            "relationsToThisTaxon.fromTaxon.secSource.citation.inReference.authorship",
121
            // the name
122
            "name.$",
123
            "name.nomenclaturalSource.citation.authorship",
124
            "name.nomenclaturalSource.citation.inReference.authorship",
125
            "name.rank.representations",
126
            "name.status.type.representations",
127
            "name.status.source.citation",
128
            "sec.authorship"
129
//            "descriptions" // TODO remove
130

    
131
            }));
132

    
133
    public static final EntityInitStrategy TAXON_WITH_CHILDNODES_INIT_STRATEGY = new EntityInitStrategy(Arrays.asList(new String []{
134
            "taxonNodes.$",
135
            "taxonNodes.classification.$",
136
            "taxonNodes.childNodes.$"
137
            }));
138

    
139
    public static final EntityInitStrategy SIMPLE_TAXON_INIT_STRATEGY = new EntityInitStrategy(Arrays.asList(new String []{
140
            "$",
141
            // the name
142
            "name.$",
143
            "name.rank.representations",
144
            "name.status.type.representations",
145
            "name.status.source.citation",
146
            "name.nomenclaturalSource.citation.authorship",
147
            "name.nomenclaturalSource.citation.inReference.authorship",
148
            "taxonNodes.classification",
149
            "sec.authorship"
150
            }));
151

    
152
    public static final EntityInitStrategy SYNONYMY_INIT_STRATEGY = new EntityInitStrategy(Arrays.asList(new String []{
153
            // initialize homotypical and heterotypical groups; needs synonyms
154
            "synonyms.$",
155
            "synonyms.name.status.type.representations",
156
            "synonyms.name.status.source.citation",
157
            "synonyms.name.nomenclaturalSource.citation.authorship",
158
            "synonyms.name.nomenclaturalSource.citation.inReference.authorship",
159
//            "synonyms.name.homotypicalGroup.typifiedNames.$",
160
//            "synonyms.name.homotypicalGroup.typifiedNames.taxonBases.$",
161
            "synonyms.name.combinationAuthorship.$",
162

    
163
            "name.typeDesignations",
164

    
165
            "name.homotypicalGroup.$",
166
            "name.homotypicalGroup.typifiedNames.$",
167
            "name.homotypicalGroup.typifiedNames.nomenclaturalSource.citation.authorship",
168
            "name.homotypicalGroup.typifiedNames.nomenclaturalSource.citation.inReference.authorship",
169
//            "name.homotypicalGroup.typifiedNames.taxonBases.$"
170
    }));
171

    
172

    
173
    private static final EntityInitStrategy TAXONRELATIONSHIP_INIT_STRATEGY = new EntityInitStrategy(Arrays.asList(new String []{
174
            "$",
175
            "type.inverseRepresentations",
176
            "fromTaxon.sec",
177
            "fromTaxon.name",
178
            "toTaxon.sec",
179
            "toTaxon.name"
180
    }));
181

    
182
    public static final EntityInitStrategy NAMERELATIONSHIP_INIT_STRATEGY = new EntityInitStrategy(Arrays.asList(new String []{
183
            "$",
184
            "type.inverseRepresentations",
185
            "source.citation",
186
            "toName.$",
187
            "toName.nomenclaturalSource.citation.authorship",
188
            "toName.nomenclaturalSource.citation.inReference.authorship",
189
            "fromName.$",
190
            "fromName.nomenclaturalSource.citation.authorship",
191
            "fromName.nomenclaturalSource.citation.inReference.authorship",
192

    
193
    }));
194

    
195
    protected static final EntityInitStrategy TAXONDESCRIPTION_INIT_STRATEGY = DescriptionPortalController.DESCRIPTION_INIT_STRATEGY;
196

    
197
    protected static final EntityInitStrategy DESCRIPTION_ELEMENT_INIT_STRATEGY = new EntityInitStrategy(Arrays.asList(new String []{
198
            "$",
199
            "sources.citation.authorship",
200
            "sources.citation.inReference.authorship",
201
            "sources.nameUsedInSource",
202
            "multilanguageText",
203
            "media",
204
    }));
205

    
206

    
207
//	private static final List<String> NAMEDESCRIPTION_INIT_STRATEGY = Arrays.asList(new String []{
208
//			"uuid",
209
//			"feature",
210
//			"elements.$",
211
//			"elements.multilanguageText",
212
//			"elements.media",
213
//	});
214

    
215
    protected static final EntityInitStrategy TAXONDESCRIPTION_MEDIA_INIT_STRATEGY = new EntityInitStrategy(Arrays.asList(new String []{
216
            "elements.media"
217

    
218
    }));
219

    
220
    private static final EntityInitStrategy TYPEDESIGNATION_INIT_STRATEGY = new EntityInitStrategy(Arrays.asList(new String []{
221
            "typeSpecimen.$",
222
            "citation.authorship.$",
223
            "typeName",
224
            "typeStatus"
225
    }));
226

    
227
    protected static final EntityInitStrategy TAXONNODE_WITH_CHILDNODES_INIT_STRATEGY = new EntityInitStrategy(Arrays.asList(new String []{
228
            "childNodes.taxon",
229
    }));
230

    
231
    protected static final EntityInitStrategy TAXONNODE_INIT_STRATEGY = new EntityInitStrategy(Arrays.asList(new String []{
232
            "taxonNodes.classification",
233
            "taxonNodes.parent",
234
            "taxonNodes.statusNote.*",
235
            "taxonNodes.taxon.name",
236
            "taxonNodes.taxon.secSource.citation",
237
            "taxonNodes.source.citation.authorship",
238
            "taxonNodes.source.citation.inReference.authorship",
239
            "acceptedTaxon.taxonNodes.classification",
240
    }));
241

    
242
    private static final String termTreeUuidPattern = "^/taxon(?:(?:/)([^/?#&\\.]+))+.*";
243

    
244
    @Override
245
    protected <CDM_BASE extends CdmBase> List<String> complementInitStrategy(Class<CDM_BASE> clazz,
246
            List<String> pathProperties) {
247

    
248
        if(pathProperties != null) {
249
            List<String> complemented = new ArrayList<>(pathProperties);
250
            if(pathProperties.contains("name")) {
251
                // pathProperties for web service request for portal/taxon/{uuid}/name
252
                complemented.add("name.nomenclaturalSource.citation.authorship");
253
                complemented.add("name.nomenclaturalSource.citation.inReference.authorship");
254
                return complemented;
255
            }
256
        }
257
        return pathProperties;
258
    }
259

    
260
    public TaxonPortalController(){
261
        super();
262
        setInitializationStrategy(TAXON_INIT_STRATEGY.getPropertyPaths());
263
    }
264

    
265
    @Autowired
266
    @Override
267
    public void setService(ITaxonService service) {
268
        this.service = service;
269
    }
270

    
271
    @InitBinder
272
    @Override
273
    public void initBinder(WebDataBinder binder) {
274
        super.initBinder(binder);
275
        binder.registerCustomEditor(NamedArea.class, new NamedAreaPropertyEditor());
276
        binder.registerCustomEditor(MatchMode.class, new MatchModePropertyEditor());
277
        binder.registerCustomEditor(Class.class, new CdmTypePropertyEditor());
278
        binder.registerCustomEditor(UuidList.class, new UUIDListPropertyEditor());
279
        binder.registerCustomEditor(DefinedTermBaseList.class, new TermBaseListPropertyEditor<>(termService));
280
    }
281

    
282
    /**
283
     * Get the synonymy for a taxon identified by the <code>{taxon-uuid}</code>.
284
     * The synonymy consists
285
     * of two parts: The group of homotypic synonyms of the taxon and the
286
     * heterotypic synonymy groups of the taxon. The synonymy is ordered
287
     * historically by the type designations and by the publication date of the
288
     * nomenclatural reference
289
     * <p>
290
     * URI:
291
     * <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-uuid}&#x002F;synonymy</b>
292
     *
293
     *
294
     * @param request
295
     * @param response
296
     * @return a Map with two entries which are mapped by the following keys:
297
     *         "homotypicSynonymsByHomotypicGroup", "heterotypicSynonymyGroups",
298
     *         containing lists of {@link Synonym}s which // TODO Auto-generated catch block
299
                    e.printStackTrace();are initialized using the
300
     *         following initialization strategy: {@link #SYNONYMY_INIT_STRATEGY}
301
     *
302
     * @throws IOException
303
     */
304
    @RequestMapping(
305
            value = {"synonymy"},
306
            method = RequestMethod.GET)
307
    public ModelAndView doGetSynonymy(@PathVariable("uuid") UUID taxonUuid,
308
            @RequestParam(value = "subtree", required = false) UUID subtreeUuid,
309
            HttpServletRequest request,
310
            HttpServletResponse response)throws IOException {
311

    
312
        boolean includeUnpublished = NO_UNPUBLISHED;
313
        if(request != null){
314
            logger.info("doGetSynonymy() " + requestPathAndQuery(request));
315
        }
316
        ModelAndView mv = new ModelAndView();
317

    
318
        Taxon taxon = getCdmBaseInstance(Taxon.class, taxonUuid, response, getTaxonNodeInitStrategy().getPropertyPaths());
319
        TaxonNode subtree = getSubtreeOrError(subtreeUuid, taxonNodeService, response);
320
        taxon = checkExistsSubtreeAndAccess(taxon, subtree, NO_UNPUBLISHED, response);
321

    
322
        Map<String, List<?>> synonymy = new Hashtable<>();
323

    
324
        //new
325
        List<List<Synonym>> synonymyGroups = service.getSynonymsByHomotypicGroup(taxon, SYNONYMY_INIT_STRATEGY.getPropertyPaths());
326
        if(!includeUnpublished){
327
            synonymyGroups = removeUnpublishedSynonyms(synonymyGroups);
328
        }
329

    
330
        synonymy.put("homotypicSynonymsByHomotypicGroup", synonymyGroups.get(0));
331
        synonymyGroups.remove(0);
332
        synonymy.put("heterotypicSynonymyGroups", synonymyGroups);
333

    
334
        //old
335
//        synonymy.put("homotypicSynonymsByHomotypicGroup", service.getHomotypicSynonymsByHomotypicGroup(taxon, SYNONYMY_INIT_STRATEGY));
336
//        synonymy.put("heterotypicSynonymyGroups", service.getHeterotypicSynonymyGroups(taxon, SYNONYMY_INIT_STRATEGY));
337

    
338
        mv.addObject(synonymy);
339
        return mv;
340
    }
341

    
342

    
343
    /**
344
     * @param synonymyGroups
345
     */
346
    private List<List<Synonym>> removeUnpublishedSynonyms(List<List<Synonym>> synonymyGroups) {
347
        List<List<Synonym>> result = new ArrayList<>();
348
        boolean isHomotypicToAccepted = true;
349

    
350
        for (List<Synonym> oldList : synonymyGroups){
351
            List<Synonym> newList = new ArrayList<>();
352
            for (Synonym oldSyn : oldList){
353
                if (oldSyn.isPublish()){
354
                    newList.add(oldSyn);
355
                }
356
            }
357
            if (isHomotypicToAccepted || !newList.isEmpty()){
358
                result.add(newList);
359
            }
360
            isHomotypicToAccepted = false;
361
        }
362
        return result;
363
    }
364

    
365
    /**
366
     * {@inheritDoc}
367
     */
368
    @Override
369
    protected List<String> getTaxonDescriptionInitStrategy() {
370
        return TAXONDESCRIPTION_INIT_STRATEGY.getPropertyPaths();
371
    }
372

    
373
    @Override
374
    protected List<String> getTaxonDescriptionElementInitStrategy() {
375
        return DESCRIPTION_ELEMENT_INIT_STRATEGY.getPropertyPaths();
376
    }
377

    
378
    @Override
379
    protected  EntityInitStrategy getTaxonNodeInitStrategy() {
380
        return TAXONNODE_INIT_STRATEGY;
381
    }
382

    
383
    /**
384
     * Get the list of {@link TaxonRelationship}s for the given
385
     * {@link TaxonBase} instance identified by the <code>{taxon-uuid}</code>.
386
     * <p>
387
     * URI: <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-uuid}&#x002F;taxonRelationships</b>
388
     *
389
     * @param request
390
     * @param response
391
     * @return a List of {@link TaxonRelationship} entities which are initialized
392
     *         using the following initialization strategy:
393
     *         {@link #TAXONRELATIONSHIP_INIT_STRATEGY}
394
     * @throws IOException
395
     */
396
    @RequestMapping(
397
            value = {"taxonRelationships"},
398
            method = RequestMethod.GET)
399
    public List<TaxonRelationship> doGetTaxonRelations(@PathVariable("uuid") UUID uuid,
400
            HttpServletRequest request, HttpServletResponse response)throws IOException {
401

    
402
        boolean includeUnpublished = NO_UNPUBLISHED;
403
        logger.info("doGetTaxonRelations()" + requestPathAndQuery(request));
404
        Taxon taxon = getCdmBaseInstance(Taxon.class, uuid, response, (List<String>)null);
405
        taxon = checkExistsAndAccess(taxon, includeUnpublished, response);
406

    
407
        List<TaxonRelationship> toRelationships = service.listToTaxonRelationships(taxon, null,
408
                includeUnpublished, null, null, null, TAXONRELATIONSHIP_INIT_STRATEGY.getPropertyPaths());
409
        List<TaxonRelationship> fromRelationships = service.listFromTaxonRelationships(taxon, null,
410
                includeUnpublished, null, null, null, TAXONRELATIONSHIP_INIT_STRATEGY.getPropertyPaths());
411

    
412
        List<TaxonRelationship> allRelationships = new ArrayList<>(toRelationships.size() + fromRelationships.size());
413
        allRelationships.addAll(toRelationships);
414
        allRelationships.addAll(fromRelationships);
415

    
416
        return allRelationships;
417
    }
418

    
419
    /**
420
     * Get the list of {@link NameRelationship}s of the Name associated with the
421
     * {@link TaxonBase} instance identified by the <code>{taxon-uuid}</code>.
422
     * <p>
423
     * URI: <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-uuid}&#x002F;nameRelationships</b>
424
     *
425
     * @param request
426
     * @param response
427
     * @return a List of {@link NameRelationship} entities which are initialized
428
     *         using the following initialization strategy:
429
     *         {@link #NAMERELATIONSHIP_INIT_STRATEGY}
430
     * @throws IOException
431
     */
432
    @RequestMapping(
433
            value = {"toNameRelationships"},
434
            method = RequestMethod.GET)
435
    public List<NameRelationship> doGetToNameRelations(@PathVariable("uuid") UUID uuid,
436
            HttpServletRequest request, HttpServletResponse response)throws IOException {
437
        logger.info("doGetNameRelations()" + request.getRequestURI());
438
        boolean includeUnpublished = NO_UNPUBLISHED;
439

    
440
        TaxonBase<?> taxonBase = getCdmBaseInstance(TaxonBase.class, uuid, response, (List<String>)null);
441
        taxonBase = checkExistsAndAccess(taxonBase, includeUnpublished, response);
442

    
443
        List<NameRelationship> list = nameService.listNameRelationships(taxonBase.getName(), Direction.relatedTo, null, null, 0, null, NAMERELATIONSHIP_INIT_STRATEGY.getPropertyPaths());
444
        return list;
445
    }
446

    
447
    /**
448
     * Get the list of {@link NameRelationship}s of the Name associated with the
449
     * {@link TaxonBase} instance identified by the <code>{taxon-uuid}</code>.
450
     * <p>
451
     * URI: <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-uuid}&#x002F;nameRelationships</b>
452
     *
453
     * @param request
454
     * @param response
455
     * @return a List of {@link NameRelationship} entities which are initialized
456
     *         using the following initialization strategy:
457
     *         {@link #NAMERELATIONSHIP_INIT_STRATEGY}
458
     * @throws IOException
459
     */
460
    @RequestMapping(
461
            value = {"fromNameRelationships"},
462
            method = RequestMethod.GET)
463
    public List<NameRelationship> doGetFromNameRelations(@PathVariable("uuid") UUID uuid,
464
            HttpServletRequest request, HttpServletResponse response)throws IOException {
465
        logger.info("doGetNameFromNameRelations()" + requestPathAndQuery(request));
466

    
467
        boolean includeUnpublished = NO_UNPUBLISHED;
468

    
469
        TaxonBase<?> taxonBase = getCdmBaseInstance(TaxonBase.class, uuid, response, SIMPLE_TAXON_INIT_STRATEGY.getPropertyPaths());
470
        taxonBase = checkExistsAndAccess(taxonBase, includeUnpublished, response);
471

    
472
        List<NameRelationship> list = nameService.listNameRelationships(taxonBase.getName(), Direction.relatedFrom, null, null, 0, null, NAMERELATIONSHIP_INIT_STRATEGY.getPropertyPaths());
473

    
474
        return list;
475
    }
476

    
477

    
478
//	@RequestMapping(value = "specimens", method = RequestMethod.GET)
479
//	public ModelAndView doGetSpecimens(
480
//			@PathVariable("uuid") UUID uuid,
481
//			HttpServletRequest request,
482
//			HttpServletResponse response) throws IOException, ClassNotFoundException {
483
//		logger.info("doGetSpecimens() - " + request.getRequestURI());
484
//
485
//		ModelAndView mv = new ModelAndView();
486
//
487
//		List<DerivedUnitFacade> derivedUnitFacadeList = new ArrayList<>();
488
//
489
//		// find speciemens in the TaxonDescriptions
490
//		List<TaxonDescription> taxonDescriptions = doGetDescriptions(uuid, request, response);
491
//		if (taxonDescriptions != null) {
492
//
493
//			for (TaxonDescription description : taxonDescriptions) {
494
//				derivedUnitFacadeList.addAll( occurrenceService.listDerivedUnitFacades(description, null) );
495
//			}
496
//		}
497
//		// TODO find specimens in the NameDescriptions ??
498
//
499
//		// TODO also find type specimens
500
//
501
//		mv.addObject(derivedUnitFacadeList);
502
//
503
//		return mv;
504
//	}
505

    
506
    /**
507
     * Get the {@link Media} attached to the {@link Taxon} instance
508
     * identified by the <code>{taxon-uuid}</code>.
509
     *
510
     * Usage &#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;{taxon-
511
     * uuid}&#x002F;media&#x002F;{mime type
512
     * list}&#x002F;{size}[,[widthOrDuration}][,{height}]&#x002F;
513
     *
514
     * Whereas
515
     * <ul>
516
     * <li><b>{mime type list}</b>: a comma separated list of mime types, in the
517
     * order of preference. The forward slashes contained in the mime types must
518
     * be replaced by a colon. Regular expressions can be used. Each media
519
     * associated with this given taxon is being searched whereas the first
520
     * matching mime type matching a representation always rules.</li>
521
     * <li><b>{size},{widthOrDuration},{height}</b>: <i>not jet implemented</i>
522
     * valid values are an integer or the asterisk '*' as a wildcard</li>
523
     * </ul>
524
     *
525
     * @param request
526
     * @param response
527
     * @return a List of {@link Media} entities which are initialized
528
     *         using the following initialization strategy:
529
     *         {@link #TAXONDESCRIPTION_INIT_STRATEGY}
530
     * @throws IOException
531
     */
532
    @RequestMapping(
533
        value = {"media"},
534
        method = RequestMethod.GET)
535
    public List<Media> doGetMedia(
536
            @PathVariable("uuid") UUID uuid,
537
            @RequestParam(value = "type", required = false) Class<? extends MediaRepresentationPart> type,
538
            @RequestParam(value = "mimeTypes", required = false) String[] mimeTypes,
539
            @RequestParam(value = "relationships", required = false) UuidList relationshipUuids,
540
            @RequestParam(value = "relationshipsInvers", required = false) UuidList relationshipInversUuids,
541
            @RequestParam(value = "includeTaxonDescriptions", required = true) Boolean  includeTaxonDescriptions,
542
            @RequestParam(value = "includeOccurrences", required = true) Boolean  includeOccurrences,
543
            @RequestParam(value = "includeTaxonNameDescriptions", required = true) Boolean  includeTaxonNameDescriptions,
544
            @RequestParam(value = "widthOrDuration", required = false) Integer  widthOrDuration,
545
            @RequestParam(value = "height", required = false) Integer height,
546
            @RequestParam(value = "size", required = false) Integer size,
547
            HttpServletRequest request, HttpServletResponse response) throws IOException {
548

    
549
        logger.info("doGetMedia() " + requestPathAndQuery(request));
550

    
551
        List<String> initStrategy = null;
552

    
553
        EntityMediaContext<Taxon> taxonMediaContext = loadMediaForTaxonAndRelated(uuid, relationshipUuids,
554
                relationshipInversUuids, includeTaxonDescriptions, includeOccurrences, includeTaxonNameDescriptions,
555
                response, initStrategy, MediaPortalController.MEDIA_INIT_STRATEGY.getPropertyPaths());
556

    
557
        List<Media> mediafilteredForPreferredRepresentations = mediaToolbox.processAndFilterPreferredMediaRepresentations(type, mimeTypes, widthOrDuration, height, size,
558
                taxonMediaContext.media);
559

    
560
        return mediafilteredForPreferredRepresentations;
561
    }
562

    
563
    /**
564
     * @param uuid
565
     * @param type
566
     * @param mimeTypes
567
     * @param relationshipUuids
568
     * @param relationshipInversUuids
569
     * @param includeTaxonDescriptions
570
     * @param includeOccurrences
571
     * @param includeTaxonNameDescriptions
572
     * @param widthOrDuration
573
     * @param height
574
     * @param size
575
     * @param response
576
     * @param initStrategy
577
     * @return
578
     * @throws IOException
579
     * @Deprecated To be replaced by other loadMediaForTaxonAndRelated method
580
     */
581
    @Deprecated
582
    public  EntityMediaContext<Taxon> loadMediaForTaxonAndRelated(UUID uuid,
583
            UuidList relationshipUuids, UuidList relationshipInversUuids,
584
            Boolean includeTaxonDescriptions, Boolean includeOccurrences, Boolean includeTaxonNameDescriptions,
585
            HttpServletResponse response,
586
            List<String> taxonInitStrategy) throws IOException {
587
        return loadMediaForTaxonAndRelated(uuid, relationshipUuids, relationshipInversUuids,
588
                includeTaxonDescriptions, includeOccurrences, includeTaxonNameDescriptions, response, taxonInitStrategy, null);
589
    }
590

    
591
    /**
592
     * @param uuid
593
     * @param type
594
     * @param mimeTypes
595
     * @param relationshipUuids
596
     * @param relationshipInversUuids
597
     * @param includeTaxonDescriptions
598
     * @param includeOccurrences
599
     * @param includeTaxonNameDescriptions
600
     * @param widthOrDuration
601
     * @param height
602
     * @param size
603
     * @param response
604
     * @param initStrategy
605
     * @return
606
     * @throws IOException
607
     */
608
    public  EntityMediaContext<Taxon> loadMediaForTaxonAndRelated(UUID uuid,
609
            UuidList relationshipUuids, UuidList relationshipInversUuids,
610
            Boolean includeTaxonDescriptions, Boolean includeOccurrences, Boolean includeTaxonNameDescriptions,
611
            HttpServletResponse response,
612
            List<String> taxonInitStrategy, List<String> mediaInitStrategy) throws IOException {
613

    
614
        boolean includeUnpublished = NO_UNPUBLISHED;
615

    
616

    
617
        Taxon taxon = getCdmBaseInstance(Taxon.class, uuid, response, taxonInitStrategy);
618
        taxon = checkExistsAndAccess(taxon, includeUnpublished, response);
619

    
620
        Set<TaxonRelationshipEdge> includeRelationships = ControllerUtils.loadIncludeRelationships(relationshipUuids, relationshipInversUuids, termService);
621

    
622
        List<Media> media = listMediaForTaxon(taxon, includeRelationships,
623
                includeTaxonDescriptions, includeOccurrences, includeTaxonNameDescriptions, mediaInitStrategy);
624

    
625
        EntityMediaContext<Taxon> entityMediaContext = new EntityMediaContext<Taxon>(taxon, media);
626

    
627
        return entityMediaContext;
628
    }
629

    
630
    @RequestMapping(
631
            value = {"subtree/media"},
632
            method = RequestMethod.GET)
633
    public List<Media> doGetSubtreeMedia(
634
            @PathVariable("uuid") UUID uuid,
635
            @RequestParam(value = "type", required = false) Class<? extends MediaRepresentationPart> type,
636
            @RequestParam(value = "mimeTypes", required = false) String[] mimeTypes,
637
            @RequestParam(value = "relationships", required = false) UuidList relationshipUuids,
638
            @RequestParam(value = "relationshipsInvers", required = false) UuidList relationshipInversUuids,
639
            @RequestParam(value = "includeTaxonDescriptions", required = true) Boolean  includeTaxonDescriptions,
640
            @RequestParam(value = "includeOccurrences", required = true) Boolean  includeOccurrences,
641
            @RequestParam(value = "includeTaxonNameDescriptions", required = true) Boolean  includeTaxonNameDescriptions,
642
            @RequestParam(value = "widthOrDuration", required = false) Integer  widthOrDuration,
643
            @RequestParam(value = "height", required = false) Integer height,
644
            @RequestParam(value = "size", required = false) Integer size,
645
            HttpServletRequest request, HttpServletResponse response)throws IOException {
646

    
647

    
648
        boolean includeUnpublished = NO_UNPUBLISHED;
649

    
650
        logger.info("doGetSubtreeMedia() " + requestPathAndQuery(request));
651

    
652
        List<String> initStrategy = TAXON_WITH_CHILDNODES_INIT_STRATEGY.getPropertyPaths();
653

    
654
        Taxon taxon = getCdmBaseInstance(Taxon.class, uuid, response, initStrategy);
655
        taxon = checkExistsAndAccess(taxon, includeUnpublished, response);
656

    
657
        Set<TaxonRelationshipEdge> includeRelationships = ControllerUtils.loadIncludeRelationships(relationshipUuids, relationshipInversUuids, termService);
658

    
659
        List<Media> media = listMediaForTaxon(taxon, includeRelationships,
660
                includeTaxonDescriptions, includeOccurrences, includeTaxonNameDescriptions, null);
661
        media = addTaxonomicChildrenMedia(includeTaxonDescriptions, includeOccurrences, includeTaxonNameDescriptions, taxon,
662
                includeRelationships, media);
663

    
664
        List<Media> mediafilteredForPreferredRepresentations = mediaToolbox.processAndFilterPreferredMediaRepresentations(type, mimeTypes, widthOrDuration, height, size,
665
                media);
666

    
667
        return mediafilteredForPreferredRepresentations;
668
    }
669

    
670
    /**
671
     * @param includeTaxonDescriptions
672
     * @param includeOccurrences
673
     * @param includeTaxonNameDescriptions
674
     * @param taxon
675
     * @param includeRelationships
676
     * @param media
677
     */
678
    public List<Media> addTaxonomicChildrenMedia(Boolean includeTaxonDescriptions, Boolean includeOccurrences,
679
            Boolean includeTaxonNameDescriptions, Taxon taxon, Set<TaxonRelationshipEdge> includeRelationships,
680
            List<Media> media) {
681

    
682
        //TODO use treeindex
683
        //looking for all medias of direct children
684
        TaxonNode node;
685
        if (taxon.getTaxonNodes().size()>0){
686
            Set<TaxonNode> nodes = taxon.getTaxonNodes();
687
            Iterator<TaxonNode> iterator = nodes.iterator();
688
            //TaxonNode holen
689
            node = iterator.next();
690
            //Check if TaxonNode belongs to the current tree
691

    
692
            node = taxonNodeService.load(node.getUuid(), TAXONNODE_WITH_CHILDNODES_INIT_STRATEGY.getPropertyPaths());
693
            List<TaxonNode> children = node.getChildNodes();
694
            Taxon childTaxon;
695
            for (TaxonNode child : children){
696
                childTaxon = child.getTaxon();
697
                if(childTaxon != null) {
698
                    childTaxon = (Taxon)taxonService.load(childTaxon.getUuid(), NO_UNPUBLISHED, null);
699
                    media.addAll(listMediaForTaxon(childTaxon, includeRelationships,
700
                            includeTaxonDescriptions, includeOccurrences, includeTaxonNameDescriptions, MediaPortalController.MEDIA_INIT_STRATEGY.getPropertyPaths()));
701
                }
702
            }
703
        }
704
        return media;
705
    }
706

    
707
    /**
708
     *
709
     * @param taxon
710
     * @param includeRelationships
711
     * @param type
712
     * @param mimeTypes
713
     * @param widthOrDuration
714
     * @param height
715
     * @param size
716
     * @return
717
     */
718
    private List<Media> listMediaForTaxon(Taxon taxon, Set<TaxonRelationshipEdge> includeRelationships,
719
            Boolean includeTaxonDescriptions, Boolean includeOccurrences, Boolean includeTaxonNameDescriptions, List<String> propertyPath) {
720

    
721
        List<Media> media = service.listMedia(taxon, includeRelationships,
722
                false, includeTaxonDescriptions, includeOccurrences, includeTaxonNameDescriptions, propertyPath);
723

    
724
        return media;
725
    }
726

    
727

    
728
    public class EntityMediaContext<T extends IdentifiableEntity> {
729

    
730
        T entity;
731
        List<Media> media;
732
        /**
733
         * @param entity
734
         * @param media
735
         */
736
        public EntityMediaContext(T entity, List<Media> media) {
737

    
738
            this.entity = HibernateProxyHelper.deproxy(entity);
739
            this.media = media;
740
        }
741
        public T getEntity() {
742
            return entity;
743
        }
744
        public List<Media> getMedia() {
745
            return media;
746
        }
747
        /**
748
         * @param addTaxonomicChildrenMedia
749
         */
750
        public void setMedia(List<Media> media) {
751
            this.media = media;
752

    
753
        }
754

    
755

    
756

    
757
    }
758

    
759
// ---------------------- code snippet preserved for possible later use --------------------
760
//	@RequestMapping(
761
//			value = {"//*/portal/taxon/*/descriptions"}, // mapped as absolute path, see CdmAntPathMatcher
762
//			method = RequestMethod.GET)
763
//	public List<TaxonDescription> doGetDescriptionsbyFeatureTree(HttpServletRequest request, HttpServletResponse response)throws IOException {
764
//		TaxonBase tb = getCdmBase(request, response, null, Taxon.class);
765
//		if(tb instanceof Taxon){
766
//			//T O D O this is a quick and dirty implementation -> generalize
767
//			UUID featureTreeUuid = readValueUuid(request, termTreeUuidPattern);
768
//
769
//			FeatureTree featureTree = descriptionService.getFeatureTreeByUuid(featureTreeUuid);
770
//			Pager<TaxonDescription> p = descriptionService.getTaxonDescriptions((Taxon)tb, null, null, null, null, TAXONDESCRIPTION_INIT_STRATEGY);
771
//			List<TaxonDescription> descriptions = p.getRecords();
772
//
773
//			if(!featureTree.isDescriptionSeparated()){
774
//
775
//				TaxonDescription superDescription = TaxonDescription.NewInstance();
776
//				//put all descriptionElements in superDescription and make it invisible
777
//				for(TaxonDescription description: descriptions){
778
//					for(DescriptionElementBase element: description.getElements()){
779
//						superDescription.addElement(element);
780
//					}
781
//				}
782
//				List<TaxonDescription> separatedDescriptions = new ArrayList<TaxonDescription>(descriptions.size());
783
//				separatedDescriptions.add(superDescription);
784
//				return separatedDescriptions;
785
//			}else{
786
//				return descriptions;
787
//			}
788
//		} else {
789
//			response.sendError(HttpServletResponse.SC_NOT_FOUND, "invalid type; Taxon expected but " + tb.getClass().getSimpleName() + " found.");
790
//			return null;
791
//		}
792
//	}
793

    
794
}
(62-62/76)