Project

General

Profile

Download (22.2 KB) Statistics
| Branch: | Tag: | Revision:
1
// $Id$
2
/**
3
 * Copyright (C) 2009 EDIT 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
7
 * 1.1 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 io.swagger.annotations.Api;
13

    
14
import java.io.IOException;
15
import java.util.ArrayList;
16
import java.util.Arrays;
17
import java.util.Collection;
18
import java.util.EnumSet;
19
import java.util.HashSet;
20
import java.util.List;
21
import java.util.Set;
22
import java.util.UUID;
23

    
24
import javax.servlet.http.HttpServletRequest;
25
import javax.servlet.http.HttpServletResponse;
26

    
27
import org.apache.commons.lang.BooleanUtils;
28
import org.apache.lucene.queryparser.classic.ParseException;
29
import org.springframework.beans.factory.annotation.Autowired;
30
import org.springframework.stereotype.Controller;
31
import org.springframework.web.bind.WebDataBinder;
32
import org.springframework.web.bind.annotation.InitBinder;
33
import org.springframework.web.bind.annotation.RequestMapping;
34
import org.springframework.web.bind.annotation.RequestMethod;
35
import org.springframework.web.bind.annotation.RequestParam;
36

    
37
import eu.etaxonomy.cdm.api.service.IClassificationService;
38
import eu.etaxonomy.cdm.api.service.ITaxonNodeService;
39
import eu.etaxonomy.cdm.api.service.ITaxonService;
40
import eu.etaxonomy.cdm.api.service.ITermService;
41
import eu.etaxonomy.cdm.api.service.TaxaAndNamesSearchMode;
42
import eu.etaxonomy.cdm.api.service.config.FindTaxaAndNamesConfiguratorImpl;
43
import eu.etaxonomy.cdm.api.service.config.IFindTaxaAndNamesConfigurator;
44
import eu.etaxonomy.cdm.api.service.dto.FindByIdentifierDTO;
45
import eu.etaxonomy.cdm.api.service.pager.Pager;
46
import eu.etaxonomy.cdm.api.service.search.LuceneMultiSearchException;
47
import eu.etaxonomy.cdm.api.service.search.SearchResult;
48
import eu.etaxonomy.cdm.model.common.CdmBase;
49
import eu.etaxonomy.cdm.model.common.DefinedTerm;
50
import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
51
import eu.etaxonomy.cdm.model.common.Language;
52
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
53
import eu.etaxonomy.cdm.model.description.Feature;
54
import eu.etaxonomy.cdm.model.description.PresenceAbsenceTerm;
55
import eu.etaxonomy.cdm.model.location.NamedArea;
56
import eu.etaxonomy.cdm.model.taxon.Classification;
57
import eu.etaxonomy.cdm.model.taxon.Synonym;
58
import eu.etaxonomy.cdm.model.taxon.Taxon;
59
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
60
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
61
import eu.etaxonomy.cdm.persistence.query.MatchMode;
62
import eu.etaxonomy.cdm.persistence.query.OrderHint;
63
import eu.etaxonomy.cdm.remote.controller.util.PagerParameters;
64
import eu.etaxonomy.cdm.remote.editor.DefinedTermBaseList;
65
import eu.etaxonomy.cdm.remote.editor.MatchModePropertyEditor;
66
import eu.etaxonomy.cdm.remote.editor.TermBaseListPropertyEditor;
67
import eu.etaxonomy.cdm.remote.editor.UuidList;
68

    
69
/**
70
 * TODO write controller documentation
71
 *
72
 * @author a.kohlbecker
73
 * @date 20.03.2009
74
 */
75
@Controller
76
@Api("taxon")
77
@RequestMapping(value = {"/taxon"})
78
public class TaxonListController extends IdentifiableListController<TaxonBase, ITaxonService> {
79

    
80

    
81
    private static final List<String> SIMPLE_TAXON_INIT_STRATEGY = DEFAULT_INIT_STRATEGY;
82
    protected List<String> getSimpleTaxonInitStrategy() {
83
        // TODO Auto-generated method stub
84
        return SIMPLE_TAXON_INIT_STRATEGY;
85
    }
86

    
87
    /**
88
     *
89
     */
90
    public TaxonListController(){
91
        super();
92
        setInitializationStrategy(Arrays.asList(new String[]{"$","name.nomenclaturalReference"}));
93
    }
94

    
95
    /* (non-Javadoc)
96
     * @see eu.etaxonomy.cdm.remote.controller.BaseListController#setService(eu.etaxonomy.cdm.api.service.IService)
97
     */
98
    @Override
99
    @Autowired
100
    public void setService(ITaxonService service) {
101
        this.service = service;
102
    }
103

    
104
    @Autowired
105
    private IClassificationService classificationService;
106

    
107
    @Autowired
108
    private ITaxonNodeService taxonNodeService;
109

    
110

    
111
    @Autowired
112
    private ITermService termService;
113

    
114
    @InitBinder
115
    @Override
116
    public void initBinder(WebDataBinder binder) {
117
        super.initBinder(binder);
118
        binder.registerCustomEditor(DefinedTermBaseList.class, new TermBaseListPropertyEditor<NamedArea>(termService));
119
        binder.registerCustomEditor(MatchMode.class, new MatchModePropertyEditor());
120

    
121
    }
122

    
123
    /**
124
     * Find Taxa, Synonyms, Common Names by name, either globally or in a specific geographic area.
125
     * <p>
126
     * URI: <b>taxon&#x002F;search</b>
127
     *
128
     * @param query
129
     *            the string to query for. Since the wildcard character '*'
130
     *            internally always is appended to the query string, a search
131
     *            always compares the query string with the beginning of a name.
132
     *            - <i>required parameter</i>
133
     * @param classificationNodeUuid
134
     *            the {@link UUID} of the root node of a {@link Classification} to which the
135
     *            search is to be restricted. - <i>optional parameter</i>
136
     * @param areas
137
     *            restrict the search to a set of geographic {@link NamedArea}s.
138
     *            The parameter currently takes a list of TDWG area labels.
139
     *            - <i>optional parameter</i>
140
     * @param pageNumber
141
     *            the number of the page to be returned, the first page has the
142
     *            pageNumber = 1 - <i>optional parameter</i>
143
     * @param pageSize
144
     *            the maximum number of entities returned per page (can be -1
145
     *            to return all entities in a single page) - <i>optional parameter</i>
146
     * @param doTaxa
147
     *            weather to search for instances of {@link Taxon} - <i>optional parameter</i>
148
     * @param doSynonyms
149
     *            weather to search for instances of {@link Synonym} - <i>optional parameter</i>
150
     * @param doTaxaByCommonNames
151
     *            for instances of {@link Taxon} by a common name used - <i>optional parameter</i>
152
     * @return a Pager on a list of {@link IdentifiableEntity}s initialized by
153
     *         the following strategy {@link #SIMPLE_TAXON_INIT_STRATEGY}
154
     * @throws IOException
155
     * @throws LuceneMultiSearchException
156
     * @throws ParseException
157
     */
158
    @RequestMapping(method = RequestMethod.GET, value={"search"})
159
    public Pager<SearchResult<TaxonBase>> doSearch(
160
            @RequestParam(value = "query", required = true) String query,
161
            @RequestParam(value = "classificationNodeUuid", required = false) UUID classificationNodeUuid,
162
            @RequestParam(value = "area", required = false) DefinedTermBaseList<NamedArea> areaList,
163
            @RequestParam(value = "status", required = false) Set<PresenceAbsenceTerm> status,
164
            @RequestParam(value = "pageNumber", required = false) Integer pageNumber,
165
            @RequestParam(value = "pageSize", required = false) Integer pageSize,
166
            @RequestParam(value = "doTaxa", required = false) Boolean doTaxa,
167
            @RequestParam(value = "doSynonyms", required = false) Boolean doSynonyms,
168
            @RequestParam(value = "doMisappliedNames", required = false) Boolean doMisappliedNames,
169
            @RequestParam(value = "doTaxaByCommonNames", required = false) Boolean doTaxaByCommonNames,
170
            HttpServletRequest request,
171
            HttpServletResponse response
172
            )
173
             throws IOException, ParseException, LuceneMultiSearchException {
174

    
175

    
176
        logger.info("search : " + requestPathAndQuery(request) );
177

    
178
        Set<NamedArea> areaSet = null;
179
        if(areaList != null){
180
            areaSet = new HashSet<NamedArea>(areaList.size());
181
            areaSet.addAll(areaList);
182
            TaxonListController.includeAllSubAreas(areaSet, termService);
183
        }
184

    
185
        PagerParameters pagerParams = new PagerParameters(pageSize, pageNumber);
186
        pagerParams.normalizeAndValidate(response);
187

    
188
        // TODO change type of do* parameters  to TaxaAndNamesSearchMode
189
        EnumSet<TaxaAndNamesSearchMode> searchModes = EnumSet.noneOf(TaxaAndNamesSearchMode.class);
190
        if(BooleanUtils.toBoolean(doTaxa)) {
191
            searchModes.add(TaxaAndNamesSearchMode.doTaxa);
192
        }
193
        if(BooleanUtils.toBoolean(doSynonyms)) {
194
            searchModes.add(TaxaAndNamesSearchMode.doSynonyms);
195
        }
196
        if(BooleanUtils.toBoolean(doMisappliedNames)) {
197
            searchModes.add(TaxaAndNamesSearchMode.doMisappliedNames);
198
        }
199
        if(BooleanUtils.toBoolean(doTaxaByCommonNames)) {
200
            searchModes.add(TaxaAndNamesSearchMode.doTaxaByCommonNames);
201
        }
202

    
203
        Classification classification = null;
204
        if(classificationNodeUuid != null){
205
            TaxonNode rootNode = taxonNodeService.load(classificationNodeUuid);
206
            if(rootNode!=null){
207
                classification = rootNode.getClassification();
208
            }
209
        }
210

    
211
        return service.findTaxaAndNamesByFullText(searchModes, query,
212
                classification, areaSet, status, null,
213
                false, pagerParams.getPageSize(), pagerParams.getPageIndex(),
214
                OrderHint.NOMENCLATURAL_SORT_ORDER.asList(), getSimpleTaxonInitStrategy());
215
    }
216

    
217
    /**
218
     * Find Taxa, Synonyms, Common Names by name, either globally or in a specific geographic area.
219
     * <p>
220
     * URI: <b>&#x002F;{datasource-name}&#x002F;portal&#x002F;taxon&#x002F;find</b>
221
     *
222
     * @param query
223
     *            the string to query for. Since the wildcard character '*'
224
     *            internally always is appended to the query string, a search
225
     *            always compares the query string with the beginning of a name.
226
     *            - <i>required parameter</i>
227
     * @param treeUuid
228
     *            the {@link UUID} of a {@link Classification} to which the
229
     *            search is to be restricted. - <i>optional parameter</i>
230
     * @param areas
231
     *            restrict the search to a set of geographic {@link NamedArea}s.
232
     *            The parameter currently takes a list of TDWG area labels.
233
     *            - <i>optional parameter</i>
234
     * @param pageNumber
235
     *            the number of the page to be returned, the first page has the
236
     *            pageNumber = 1 - <i>optional parameter</i>
237
     * @param pageSize
238
     *            the maximum number of entities returned per page (can be -1
239
     *            to return all entities in a single page) - <i>optional parameter</i>
240
     * @param doTaxa
241
     *            weather to search for instances of {@link Taxon} - <i>optional parameter</i>
242
     * @param doSynonyms
243
     *            weather to search for instances of {@link Synonym} - <i>optional parameter</i>
244
     * @param doTaxaByCommonNames
245
     *            for instances of {@link Taxon} by a common name used - <i>optional parameter</i>
246
     * @param matchMode
247
     *           valid values are "EXACT", "BEGINNING", "ANYWHERE", "END" (case sensitive !!!)
248
     * @return a Pager on a list of {@link IdentifiableEntity}s initialized by
249
     *         the following strategy {@link #SIMPLE_TAXON_INIT_STRATEGY}
250
     * @throws IOException
251
     */
252
    @RequestMapping(method = RequestMethod.GET, value={"find"})
253
    public Pager<IdentifiableEntity> doFind(
254
            @RequestParam(value = "query", required = true) String query,
255
            @RequestParam(value = "tree", required = false) UUID treeUuid,
256
            @RequestParam(value = "area", required = false) Set<NamedArea> areas,
257
            @RequestParam(value = "pageNumber", required = false) Integer pageNumber,
258
            @RequestParam(value = "pageSize", required = false) Integer pageSize,
259
            @RequestParam(value = "doTaxa", required = false) Boolean doTaxa,
260
            @RequestParam(value = "doSynonyms", required = false) Boolean doSynonyms,
261
            @RequestParam(value = "doMisappliedNames", required = false) Boolean doMisappliedNames,
262
            @RequestParam(value = "doTaxaByCommonNames", required = false) Boolean doTaxaByCommonNames,
263
            @RequestParam(value = "matchMode", required = false) MatchMode matchMode,
264
            HttpServletRequest request,
265
            HttpServletResponse response
266
            )
267
             throws IOException {
268

    
269

    
270
        logger.info("find : " + request.getRequestURI() + "?" + request.getQueryString() );
271

    
272
        PagerParameters pagerParams = new PagerParameters(pageSize, pageNumber);
273
        pagerParams.normalizeAndValidate(response);
274

    
275
        IFindTaxaAndNamesConfigurator config = new FindTaxaAndNamesConfiguratorImpl();
276
        config.setPageNumber(pagerParams.getPageIndex());
277
        config.setPageSize(pagerParams.getPageSize());
278
        config.setTitleSearchString(query);
279
        config.setDoTaxa(doTaxa!= null ? doTaxa : Boolean.FALSE );
280
        config.setDoSynonyms(doSynonyms != null ? doSynonyms : Boolean.FALSE );
281
        config.setDoMisappliedNames(doMisappliedNames != null ? doMisappliedNames : Boolean.FALSE);
282
        config.setDoTaxaByCommonNames(doTaxaByCommonNames != null ? doTaxaByCommonNames : Boolean.FALSE );
283
        config.setMatchMode(matchMode != null ? matchMode : MatchMode.BEGINNING);
284
        config.setTaxonPropertyPath(getSimpleTaxonInitStrategy());
285
        config.setNamedAreas(areas);
286
        if(treeUuid != null){
287
            Classification classification = classificationService.find(treeUuid);
288
            config.setClassification(classification);
289
        }
290

    
291
        return service.findTaxaAndNames(config);
292

    
293
    }
294

    
295

    
296
    /**
297
     * @param clazz
298
     * @param queryString
299
     * @param treeUuid TODO unimplemented in TaxonServiceImpl !!!!
300
     * @param languages
301
     * @param pageNumber
302
     * @param pageSize
303
     * @param request
304
     * @param response
305
     * @return
306
     * @throws IOException
307
     * @throws ParseException
308
     */
309
    @RequestMapping(method = RequestMethod.GET, value={"findByDescriptionElementFullText"})
310
    public Pager<SearchResult<TaxonBase>> dofindByDescriptionElementFullText(
311
            @RequestParam(value = "clazz", required = false) Class<? extends DescriptionElementBase> clazz,
312
            @RequestParam(value = "query", required = true) String queryString,
313
            @RequestParam(value = "tree", required = false) UUID treeUuid,
314
            @RequestParam(value = "features", required = false) UuidList featureUuids,
315
            @RequestParam(value = "languages", required = false) List<Language> languages,
316
            @RequestParam(value = "hl", required = false) Boolean highlighting,
317
            @RequestParam(value = "pageNumber", required = false) Integer pageNumber,
318
            @RequestParam(value = "pageSize", required = false) Integer pageSize,
319
            HttpServletRequest request,
320
            HttpServletResponse response
321
            )
322
             throws IOException, ParseException {
323

    
324
         logger.info("findByDescriptionElementFullText : " + requestPathAndQuery(request) );
325

    
326
         PagerParameters pagerParams = new PagerParameters(pageSize, pageNumber);
327
         pagerParams.normalizeAndValidate(response);
328

    
329
         if(highlighting == null){
330
             highlighting = false;
331
         }
332

    
333
         Classification classification = null;
334
        if(treeUuid != null){
335
            classification = classificationService.find(treeUuid);
336
        }
337

    
338
        List<Feature> features = null;
339
        if(featureUuids != null){
340
            features = new ArrayList<Feature>(featureUuids.size());
341
            for(UUID uuid : featureUuids){
342
                features.add((Feature) termService.find(uuid));
343
            }
344
        }
345

    
346
        Pager<SearchResult<TaxonBase>> pager = service.findByDescriptionElementFullText(
347
                clazz, queryString, classification, features, languages, highlighting,
348
                pagerParams.getPageSize(), pagerParams.getPageIndex(),
349
                ((List<OrderHint>)null), getSimpleTaxonInitStrategy());
350
        return pager;
351
    }
352

    
353
    @RequestMapping(method = RequestMethod.GET, value={"findByFullText"})
354
    public Pager<SearchResult<TaxonBase>> dofindByFullText(
355
            @RequestParam(value = "clazz", required = false) Class<? extends TaxonBase> clazz,
356
            @RequestParam(value = "query", required = true) String queryString,
357
            @RequestParam(value = "tree", required = false) UUID treeUuid,
358
            @RequestParam(value = "languages", required = false) List<Language> languages,
359
            @RequestParam(value = "hl", required = false) Boolean highlighting,
360
            @RequestParam(value = "pageNumber", required = false) Integer pageNumber,
361
            @RequestParam(value = "pageSize", required = false) Integer pageSize,
362
            HttpServletRequest request,
363
            HttpServletResponse response
364
            )
365
             throws IOException, ParseException {
366

    
367
         logger.info("findByFullText : " + requestPathAndQuery(request)  );
368

    
369
         PagerParameters pagerParams = new PagerParameters(pageSize, pageNumber);
370
         pagerParams.normalizeAndValidate(response);
371

    
372
         if(highlighting == null){
373
             highlighting = false;
374
         }
375

    
376
         Classification classification = null;
377
        if(treeUuid != null){
378
            classification = classificationService.find(treeUuid);
379
        }
380

    
381
        Pager<SearchResult<TaxonBase>> pager = service.findByFullText(clazz, queryString, classification, languages,
382
                highlighting, pagerParams.getPageSize(), pagerParams.getPageIndex(), ((List<OrderHint>)  null),
383
                initializationStrategy);
384
        return pager;
385
    }
386

    
387
    @RequestMapping(method = RequestMethod.GET, value={"findByEverythingFullText"})
388
    public Pager<SearchResult<TaxonBase>> dofindByEverythingFullText(
389
            @RequestParam(value = "clazz", required = false) Class<? extends TaxonBase> clazz,
390
            @RequestParam(value = "query", required = true) String queryString,
391
            @RequestParam(value = "tree", required = false) UUID treeUuid,
392
            @RequestParam(value = "languages", required = false) List<Language> languages,
393
            @RequestParam(value = "hl", required = false) Boolean highlighting,
394
            @RequestParam(value = "pageNumber", required = false) Integer pageNumber,
395
            @RequestParam(value = "pageSize", required = false) Integer pageSize,
396
            HttpServletRequest request,
397
            HttpServletResponse response
398
            )
399
             throws IOException, ParseException, LuceneMultiSearchException {
400

    
401
         logger.info("findByEverythingFullText : " + requestPathAndQuery(request) );
402

    
403
         PagerParameters pagerParams = new PagerParameters(pageSize, pageNumber);
404
         pagerParams.normalizeAndValidate(response);
405

    
406
         if(highlighting == null){
407
             highlighting = false;
408
         }
409

    
410
         Classification classification = null;
411
        if(treeUuid != null){
412
            classification = classificationService.find(treeUuid);
413
        }
414

    
415
        Pager<SearchResult<TaxonBase>> pager = service.findByEverythingFullText(
416
                queryString, classification, languages, highlighting,
417
                pagerParams.getPageSize(), pagerParams.getPageIndex(),
418
                ((List<OrderHint>)null), initializationStrategy);
419
        return pager;
420
    }
421

    
422
    /**
423
     * @param areaSet
424
     */
425
    static public void includeAllSubAreas(Set<NamedArea> areaSet, ITermService termService) {
426
        Collection<NamedArea> tmpAreas = new HashSet<NamedArea>(areaSet);
427
        // expand all areas to include also the sub areas
428
        Pager<NamedArea> pager = null;
429
        while(true){
430
            pager = termService.getIncludes(tmpAreas, 1000, null, null);
431
            if(pager.getCount() == 0){
432
                break;
433
            }
434
            tmpAreas = pager.getRecords();
435
            tmpAreas.removeAll(areaSet);
436
            areaSet.addAll(tmpAreas);
437
        }
438
    }
439

    
440
    @RequestMapping(value = "findBestMatchingTaxon", method = RequestMethod.GET)
441
    public TaxonBase doFindBestMatchingTaxon(
442
            @RequestParam(value = "query", required = true) String taxonName,
443
            HttpServletRequest request,
444
            HttpServletResponse response)throws IOException {
445

    
446
        Taxon bestMatchingTaxon =  service.findBestMatchingTaxon(taxonName);
447

    
448
        return bestMatchingTaxon;
449
    }
450

    
451
    /**
452
     * list IdentifiableEntity objects by identifiers
453
     *
454
     * @param type
455
     * @param identifierType
456
     * @param identifier
457
     * @param pageNumber
458
     * @param pageSize
459
     * @param matchMode
460
     * @param request
461
     * @param response
462
     * @return
463
     * @see IdentifiableListController#doFindByIdentifier(Class, String, String, Integer, Integer, MatchMode, Boolean, HttpServletRequest, HttpServletResponse)
464
     * @throws IOException
465
     */
466
    @RequestMapping(method = RequestMethod.GET, value={"findByIdentifier"}, params={"subtree"})
467
    public <T extends TaxonBase>  Pager<FindByIdentifierDTO<T>> doFindByIdentifier(
468
            @RequestParam(value = "class", required = false) Class<T> type,
469
            @RequestParam(value = "identifierType", required = false) UUID identifierType,
470
            @RequestParam(value = "identifier", required = false) String identifier,
471
            @RequestParam(value = "pageNumber", required = false) Integer pageNumber,
472
            @RequestParam(value = "pageSize", required = false) Integer pageSize,
473
            @RequestParam(value = "matchMode", required = false) MatchMode matchMode,
474
            @RequestParam(value = "includeEntity", required = false, defaultValue="true") Boolean includeEntity, //TODO true only for debuging
475
            @RequestParam(value = "subtree", required = true) UUID subtreeUuid,
476
            HttpServletRequest request,
477
            HttpServletResponse response
478
            )
479
             throws IOException {
480

    
481
        DefinedTerm definedTerm = null;
482
        if(identifierType != null){
483
            definedTerm = CdmBase.deproxy(termService.find(identifierType), DefinedTerm.class);
484
        }
485

    
486
        TaxonNode subTree;
487
        Classification cl = classificationService.load(subtreeUuid);
488
        if (cl != null){
489
            subTree = cl.getRootNode();
490
        }else{
491
            subTree = taxonNodeService.find(subtreeUuid);
492
        }
493

    
494
        logger.info("doFindByIdentifier [subtreeUuid]  : " + request.getRequestURI() + "?" + request.getQueryString() );
495

    
496

    
497
        PagerParameters pagerParams = new PagerParameters(pageSize, pageNumber).normalizeAndValidate(response);
498

    
499
        matchMode = matchMode != null ? matchMode : MatchMode.EXACT;
500
        return service.findByIdentifier(type, identifier, definedTerm , subTree, matchMode, includeEntity, pagerParams.getPageSize(), pagerParams.getPageIndex(), initializationStrategy);
501
    }
502

    
503
}
(55-55/63)