Project

General

Profile

Download (24.4 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.DefinedTermBase;
51
import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
52
import eu.etaxonomy.cdm.model.common.Language;
53
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
54
import eu.etaxonomy.cdm.model.description.Feature;
55
import eu.etaxonomy.cdm.model.description.PresenceAbsenceTerm;
56
import eu.etaxonomy.cdm.model.location.NamedArea;
57
import eu.etaxonomy.cdm.model.name.Rank;
58
import eu.etaxonomy.cdm.model.taxon.Classification;
59
import eu.etaxonomy.cdm.model.taxon.Synonym;
60
import eu.etaxonomy.cdm.model.taxon.Taxon;
61
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
62
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
63
import eu.etaxonomy.cdm.persistence.query.MatchMode;
64
import eu.etaxonomy.cdm.persistence.query.OrderHint;
65
import eu.etaxonomy.cdm.remote.controller.util.PagerParameters;
66
import eu.etaxonomy.cdm.remote.editor.DefinedTermBaseList;
67
import eu.etaxonomy.cdm.remote.editor.MatchModePropertyEditor;
68
import eu.etaxonomy.cdm.remote.editor.RankPropertyEditor;
69
import eu.etaxonomy.cdm.remote.editor.TermBaseListPropertyEditor;
70
import eu.etaxonomy.cdm.remote.editor.TermBasePropertyEditor;
71
import eu.etaxonomy.cdm.remote.editor.UuidList;
72

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

    
84

    
85
    private static final List<String> SIMPLE_TAXON_INIT_STRATEGY = DEFAULT_INIT_STRATEGY;
86
    protected List<String> getSimpleTaxonInitStrategy() {
87
        // TODO Auto-generated method stub
88
        return SIMPLE_TAXON_INIT_STRATEGY;
89
    }
90

    
91
    /**
92
     *
93
     */
94
    public TaxonListController(){
95
        super();
96
        setInitializationStrategy(Arrays.asList(new String[]{"$","name.nomenclaturalReference"}));
97
    }
98

    
99
    @Override
100
    @Autowired
101
    public void setService(ITaxonService service) {
102
        this.service = service;
103
    }
104

    
105
    @Autowired
106
    private IClassificationService classificationService;
107

    
108
    @Autowired
109
    private ITaxonNodeService taxonNodeService;
110

    
111

    
112
    @Autowired
113
    private ITermService termService;
114

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

    
124
    }
125

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

    
178

    
179
        logger.info("search : " + requestPathAndQuery(request) );
180

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

    
188
        PagerParameters pagerParams = new PagerParameters(pageSize, pageNumber);
189
        pagerParams.normalizeAndValidate(response);
190

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

    
206
        Classification classification = classificationService.load(classificationUuid);
207

    
208
        Set<PresenceAbsenceTerm> statusSet = null;
209
        if(status != null) {
210
                statusSet = new HashSet<PresenceAbsenceTerm>(Arrays.asList(status));
211
        }
212

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

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

    
271

    
272
        logger.info("find : " + request.getRequestURI() + "?" + request.getQueryString() );
273

    
274
        PagerParameters pagerParams = new PagerParameters(pageSize, pageNumber);
275
        pagerParams.normalizeAndValidate(response);
276

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

    
293
        return service.findTaxaAndNames(config);
294

    
295
    }
296

    
297

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

    
326
         logger.info("findByDescriptionElementFullText : " + requestPathAndQuery(request) );
327

    
328
         PagerParameters pagerParams = new PagerParameters(pageSize, pageNumber);
329
         pagerParams.normalizeAndValidate(response);
330

    
331
         if(highlighting == null){
332
             highlighting = false;
333
         }
334

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

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

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

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

    
369
         logger.info("findByFullText : " + requestPathAndQuery(request)  );
370

    
371
         PagerParameters pagerParams = new PagerParameters(pageSize, pageNumber);
372
         pagerParams.normalizeAndValidate(response);
373

    
374
         if(highlighting == null){
375
             highlighting = false;
376
         }
377

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

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

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

    
403
         logger.info("findByEverythingFullText : " + requestPathAndQuery(request) );
404

    
405
         PagerParameters pagerParams = new PagerParameters(pageSize, pageNumber);
406
         pagerParams.normalizeAndValidate(response);
407

    
408
         if(highlighting == null){
409
             highlighting = false;
410
         }
411

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

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

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

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

    
448
        logger.info("doFindBestMatchingTaxon : " + requestPathAndQuery(request) );
449

    
450
        Taxon bestMatchingTaxon =  service.findBestMatchingTaxon(taxonName);
451

    
452
        return bestMatchingTaxon;
453
    }
454

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

    
485
        DefinedTerm definedTerm = null;
486
        if(identifierType != null){
487
            definedTerm = CdmBase.deproxy(termService.find(identifierType), DefinedTerm.class);
488
        }
489

    
490
        TaxonNode subTree;
491
        Classification cl = classificationService.load(subtreeUuid);
492
        if (cl != null){
493
            subTree = cl.getRootNode();
494
        }else{
495
            subTree = taxonNodeService.find(subtreeUuid);
496
        }
497

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

    
500

    
501
        PagerParameters pagerParams = new PagerParameters(pageSize, pageNumber).normalizeAndValidate(response);
502

    
503
        matchMode = matchMode != null ? matchMode : MatchMode.EXACT;
504
        return service.findByIdentifier(type, identifier, definedTerm , subTree, matchMode, includeEntity, pagerParams.getPageSize(), pagerParams.getPageIndex(), initializationStrategy);
505
    }
506

    
507
    @RequestMapping(value = "doFindByNameParts", method = RequestMethod.GET)
508
    public Pager<TaxonBase> doFindByNameParts(
509
            @RequestParam(value = "genusOrUninomial", required = false) String genusOrUninomial,
510
            @RequestParam(value = "infragenericEpithet", required = false) String infragenericEpithet,
511
            @RequestParam(value = "specificEpithet", required = false) String specificEpithet,
512
            @RequestParam(value = "infraspecificEpithet", required = false) String infraspecificEpithet,
513
            @RequestParam(value = "authorship", required = false) String authorship,
514
            @RequestParam(value = "rankUuid", required = false) UUID rankUuid,
515
            @RequestParam(value = "pageNumber", required = false) Integer pageNumber,
516
            @RequestParam(value = "pageSize", required = false) Integer pageSize,
517
            HttpServletRequest request,
518
            HttpServletResponse response)throws IOException {
519

    
520
        logger.info("doFindByNameParts : " + requestPathAndQuery(request) );
521

    
522
        if (genusOrUninomial == null && infragenericEpithet == null && specificEpithet == null && infraspecificEpithet == null){
523
            response.sendError(404 , "At least 1 name part must be defined " );
524
            return null;
525
        }
526

    
527
        Rank rank = null;
528
        if (rankUuid != null){
529
             rank = findRank(rankUuid);
530
        }
531

    
532
        Pager<TaxonBase> result = service.findTaxaByName(null, genusOrUninomial, infragenericEpithet, specificEpithet, infraspecificEpithet, authorship, rank, pageSize, pageNumber);
533

    
534
        return result;
535
    }
536

    
537

    
538
    private Rank findRank(UUID rankUuid) {
539
        Rank rank = null;
540
        if(rankUuid != null){
541
            DefinedTermBase<?> definedTermBase =  termService.find(rankUuid);
542
            if(definedTermBase instanceof Rank){
543
                rank = (Rank) definedTermBase;
544
            } else {
545
               throw new IllegalArgumentException("DefinedTermBase is not a Rank");
546
            }
547
        }
548
        return rank;
549
    }
550

    
551
}
(55-55/63)