javadoc for ipni reference service
[cdmlib.git] / cdmlib-ext / src / main / java / eu / etaxonomy / cdm / ext / ipni / IpniService.java
1 // $Id$
2 /**
3 * Copyright (C) 2009 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
6 *
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
9 */
10 package eu.etaxonomy.cdm.ext.ipni;
11
12 import java.io.BufferedReader;
13 import java.io.IOException;
14 import java.io.InputStream;
15 import java.io.InputStreamReader;
16 import java.net.HttpURLConnection;
17 import java.net.MalformedURLException;
18 import java.net.URL;
19 import java.text.ParseException;
20 import java.util.ArrayList;
21 import java.util.HashMap;
22 import java.util.List;
23 import java.util.Map;
24
25 import org.apache.commons.lang.StringUtils;
26 import org.apache.log4j.Logger;
27 import org.springframework.stereotype.Component;
28
29 import eu.etaxonomy.cdm.api.application.ICdmApplicationConfiguration;
30 import eu.etaxonomy.cdm.api.facade.DerivedUnitFacade;
31 import eu.etaxonomy.cdm.api.facade.DerivedUnitFacade.DerivedUnitType;
32 import eu.etaxonomy.cdm.common.CdmUtils;
33 import eu.etaxonomy.cdm.model.agent.Person;
34 import eu.etaxonomy.cdm.model.agent.Team;
35 import eu.etaxonomy.cdm.model.common.Annotation;
36 import eu.etaxonomy.cdm.model.common.AnnotationType;
37 import eu.etaxonomy.cdm.model.common.Extension;
38 import eu.etaxonomy.cdm.model.common.ExtensionType;
39 import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
40 import eu.etaxonomy.cdm.model.common.Language;
41 import eu.etaxonomy.cdm.model.common.TimePeriod;
42 import eu.etaxonomy.cdm.model.name.BotanicalName;
43 import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
44 import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
45 import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
46 import eu.etaxonomy.cdm.model.name.Rank;
47 import eu.etaxonomy.cdm.model.reference.ReferenceBase;
48 import eu.etaxonomy.cdm.model.reference.ReferenceFactory;
49 import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
50
51
52 /**
53 * @author a.mueller
54 * @created Aug 16, 2010
55 * @version 1.0
56 *
57 */
58 @Component
59 public class IpniService implements IIpniService{
60 private static final String EAST_OR_WEST = "East or west";
61
62 private static final String NORTH_OR_SOUTH = "North or south";
63
64 private static final String LATITUDE_SECONDS = "Latitude seconds";
65
66 private static final String LATITUDE_MINUTES = "Latitude minutes";
67
68 private static final String LATITUDE_DEGREES = "Latitude degrees";
69
70 private static final String COLLECTION_DATE_AS_TEXT = "Collection date as text";
71
72 private static final String COLLECTION_DAY1 = "Collection day1";
73
74 private static final String COLLECTION_MONTH1 = "Collection month1";
75
76 private static final String COLLECTION_YEAR1 = "Collection year1";
77
78 private static final String COLLECTION_DAY2 = "Collection day2";
79
80 private static final String COLLECTION_MONTH2 = "Collection month2";
81
82 private static final String COLLECTION_YEAR2 = "Collection year2";
83
84 private static final String COLLECTION_NUMBER = "Collection number";
85
86 private static final String COLLECTOR_TEAM_AS_TEXT = "Collector team as text";
87
88 private static final String LOCALITY = "Locality";
89
90 private static final String TYPE_REMARKS = "Type remarks";
91
92 private static final Logger logger = Logger.getLogger(IpniService.class);
93
94 // GENERAL
95 public static String ID = "Id";
96 public static String VERSION = "Version";
97 public static final String REMARKS = "Remarks";
98
99 //NAMES
100 public static final String FULL_NAME_WITHOUT_FAMILY_AND_AUTHORS = "Full name without family and authors";
101 public static final String AUTHORS = "Authors";
102 public static final String FAMILY = "Family";
103 public static final String GENUS = "Genus";
104 public static final String INFRA_GENUS = "Infra genus";
105 public static final String SPECIES = "Species";
106 public static final String INFRA_SPECIFIC = "Infra species";
107 public static final String RANK = "Rank";
108 public static final String BASIONYM_AUTHOR = "Basionym author";
109 public static final String PUBLISHING_AUTHOR = "Publishing author";
110 public static final String PUBLICATION = "Publication";
111 public static final String PUBLICATION_YEAR_FULL = "Publication year full";
112 public static final String NAME_STATUS = "Name status";
113 public static final String BASIONYM = "Basionym";
114 public static final String REPLACED_SYNONYM = "Replaced synonym";
115
116
117 //AUTHORS
118
119 public static final String STANDARD_FORM = "Standard Form";
120
121 public static final String DEFAULT_AUTHOR_FORENAME = "Default author forename";
122 public static final String DEFAULT_AUTHOR_SURNAME = "Default author surname";
123 public static final String TAXON_GROUPS = "Taxon groups";
124 public static final String DATES = "Dates";
125 public static final String ALTERNATIVE_NAMES = "Alternative names";
126
127 public static final String DEFAULT_AUTHOR_NAME = "Default author name";
128
129 public static final String NAME_NOTES = "Name notes";
130 public static final String NAME_SOURCE = "Name source";
131 public static final String DATE_TYPE_CODE = "Date type code";
132 public static final String DATE_TYPE_STRING = "Date type string";
133
134 public static final String ALTERNATIVE_ABBREVIATIONS = "Alternative abbreviations";
135 public static final String EXAMPLE_OF_NAME_PUBLISHED = "Example of name published";
136
137
138 //PUBLICATIONS
139
140 public static final String ABBREVIATION = "Abbreviation";
141 public static final String TITLE = "Title";
142 public static final String BPH_NUMBER = "BPH number";
143 public static final String ISBN = "ISBN";
144 public static final String ISSN = "ISSN";
145 public static final String AUTHORS_ROLE = "Authors role";
146 public static final String EDITION = "Edition";
147 public static final String DATE = "Date";
148 public static final String IN_PUBLICATION_FACADE = "In publication facade";
149 public static final String LC_NUMBER = "LC number";
150 public static final String PLACE = "Place";
151 public static final String PUBLICATION_AUTHOR_TEAM = "Publication author team";
152 public static final String PRECEDED_BY = "Preceded";
153 public static final String TL2_AUTHOR = "TL2 author";
154 public static final String TL2_NUMBER = "TL2 number";
155 public static final String TDWG_ABBREVIATION = "TDWG abbreviation";
156
157 private enum ServiceType{
158 AUTHOR,
159 NAME,
160 PUBLICATION,
161 }
162
163 public enum IpniRank{
164 ALL ("All"),
165 FAMILIAL ("Familial"),
166 INFRA_FAMILIAL ("Infrafamilial"),
167 GENERIC("Generic"),
168 INFRA_GENERIC("Infrageneric"),
169 SPECIFIC ("Specific"),
170 INFRA_SPECIFIC("InfraSpecific");
171
172 String strRank;
173 IpniRank(String strRank){
174 this.strRank = strRank;
175 }
176
177 public static IpniRank valueOf(Rank rank){
178 if (rank == null){
179 return ALL;
180 }else if (rank.isInfraSpecific()){
181 return INFRA_SPECIFIC;
182 }else if (rank.isSpecies()){
183 return SPECIFIC;
184 }else if (rank.isInfraGeneric()){
185 return INFRA_GENERIC;
186 }else if (rank.isGenus()){
187 return GENERIC;
188 }else if (rank.isLower(Rank.FAMILY())){
189 return INFRA_FAMILIAL;
190 }else if (rank.isHigher(Rank.SUBFAMILY())){
191 return FAMILIAL;
192 }else{
193 logger.warn("Rank could not be transformed to ipni rank. Use ALL instead");
194 return ALL;
195 }
196 }
197 }
198
199
200 // private URL serviceUrl;
201
202 // ******************************** CONSTRUCTOR **************************************
203
204 // ****************************** METHODS ****************************************************/
205
206
207 /* (non-Javadoc)
208 * @see eu.etaxonomy.cdm.ext.ipni.IIpniService#getAuthors(java.lang.String, java.lang.String, java.lang.String, java.lang.String, eu.etaxonomy.cdm.api.application.ICdmApplicationConfiguration, eu.etaxonomy.cdm.ext.ipni.IpniServiceAuthorConfigurator)
209 */
210 public List<Person> getAuthors(String abbreviation, String surname, String forename, String isoCountry, ICdmApplicationConfiguration services, IpniServiceAuthorConfigurator config){
211 //config
212 if (config == null){
213 config = new IpniServiceAuthorConfigurator();
214 }
215
216
217 abbreviation = normalizeParameter(abbreviation);
218 surname = normalizeParameter(surname);
219 isoCountry = normalizeParameter(isoCountry);
220 forename = normalizeParameter(forename);
221
222 DelimitedFormat format = config.getFormat();
223
224 String request = "find_abbreviation=" + abbreviation +
225 "&find_surname=" + surname +
226 "&find_isoCountry=" + isoCountry +
227 "&find_forename=" + forename +
228 "&output_format=" + format.parameter;
229
230 return (List)queryService(request, services, getServiceUrl(IIpniService.AUTHOR_SERVICE_URL), config, ServiceType.AUTHOR);
231 }
232
233
234 /**
235 *
236 * @param restRequest
237 * @return
238 */
239 private List<? extends IdentifiableEntity> queryService(String request, ICdmApplicationConfiguration services, URL serviceUrl, IIpniServiceConfigurator config, ServiceType serviceType){
240 if (config == null){
241 throw new NullPointerException("Ipni service configurator should not be null");
242 }
243 try {
244 // create the request url
245 URL newUrl = new URL(serviceUrl.getProtocol(),
246 serviceUrl.getHost(),
247 serviceUrl.getPort(),
248 serviceUrl.getPath()
249 + "?" + request);
250 // open a connection
251 HttpURLConnection connection = (HttpURLConnection) newUrl.openConnection();
252 // set the accept property to XML so we can use jdom to handle the content
253 //connection.setRequestProperty("Accept", "text/xml");
254
255
256 logger.info("Firing request for URL: " + newUrl);
257
258 int responseCode = connection.getResponseCode();
259
260 // get the content at the resource
261 InputStream content = (InputStream) connection.getContent();
262
263 // build the result
264 List<? extends IdentifiableEntity> result;
265 if (serviceType.equals(ServiceType.AUTHOR)){
266 result = buildAuthorList(content, services, config);
267 }else if (serviceType.equals(ServiceType.NAME)){
268 result = buildNameList(content, services, config);
269 }else{
270 result = buildPublicationList(content, services, config);
271 }
272 if(responseCode == HttpURLConnection.HTTP_OK){
273 return result;
274 }else{
275 //TODO error handling
276 logger.error("No Http_OK");
277 }
278
279 } catch (IOException e) {
280 logger.error("No content for request: " + request);
281 }
282
283 // error
284 return null;
285 }
286
287 private List<ReferenceBase> buildPublicationList( InputStream content, ICdmApplicationConfiguration services, IIpniServiceConfigurator iConfig) throws IOException {
288 IpniServicePublicationConfigurator config = (IpniServicePublicationConfigurator)iConfig;
289
290 List<ReferenceBase> result = new ArrayList<ReferenceBase>();
291 BufferedReader reader = new BufferedReader (new InputStreamReader(content));
292
293 String headerLine = reader.readLine();
294 Map<Integer, String> parameterMap = getParameterMap(headerLine);
295
296 String line = reader.readLine();
297 while (StringUtils.isNotBlank(line)){
298 ReferenceBase reference = getPublicationFromLine(line, parameterMap, services, config);
299 result.add(reference);
300 line = reader.readLine();
301 }
302
303 return result;
304 }
305
306
307 private ReferenceBase getPublicationFromLine(String line, Map<Integer, String> parameterMap, ICdmApplicationConfiguration appConfig, IpniServicePublicationConfigurator config) {
308 //fill value map
309 String[] splits = line.split("%");
310
311 Map<String, String> valueMap = new HashMap<String, String>();
312 for (int i = 0; i < splits.length; i++){
313 valueMap.put(parameterMap.get(i), splits[i]);
314 }
315
316 //create reference object
317 ReferenceBase ref = ReferenceFactory.newGeneric();
318
319 //reference
320 if (config.isUseAbbreviationAsTitle() == true){
321 ref.setTitle(valueMap.get(ABBREVIATION));
322 //TODO handle title as extension
323 }else{
324 ref.setTitle(valueMap.get(TITLE));
325 //TODO handle abbreviation as extension
326 }
327 ref.setIsbn(valueMap.get(ISBN));
328 ref.setIssn(valueMap.get(ISSN));
329 ref.setEdition(valueMap.get(EDITION));
330 ref.setPlacePublished(valueMap.get(PLACE));
331
332 String author = valueMap.get(PUBLICATION_AUTHOR_TEAM);
333 Team team = Team.NewTitledInstance(author, author);
334 ref.setAuthorTeam(team);
335
336 //remarks
337 String remarks = valueMap.get(REMARKS);
338 Annotation annotation = Annotation.NewInstance(remarks, AnnotationType.EDITORIAL(), Language.ENGLISH());
339 ref.addAnnotation(annotation);
340
341 //dates
342 TimePeriod date = TimePeriod.parseString(valueMap.get(DATE));
343 ref.setDatePublished(date);
344
345 //source
346 ReferenceBase citation = getIpniCitation(appConfig);
347 ref.addSource(valueMap.get(ID), "Publication", citation, valueMap.get(VERSION));
348
349
350 /* TODO
351 BPH number
352 Authors role
353 In publication facade
354 LC number
355 Preceded by
356 TL2 author
357 TL2 number
358 TDWG abbreviation
359 */
360
361 return ref;
362 }
363
364
365 private List<BotanicalName> buildNameList( InputStream content, ICdmApplicationConfiguration appConfig, IIpniServiceConfigurator iConfig) throws IOException {
366 IpniServiceNamesConfigurator config = (IpniServiceNamesConfigurator)iConfig;
367 List<BotanicalName> result = new ArrayList<BotanicalName>();
368 BufferedReader reader = new BufferedReader (new InputStreamReader(content));
369
370 String headerLine = reader.readLine();
371 Map<Integer, String> parameterMap = getParameterMap(headerLine);
372
373 String line = reader.readLine();
374 while (StringUtils.isNotBlank(line)){
375 BotanicalName name = getNameFromLine(line,parameterMap, appConfig);
376 result.add(name);
377 line = reader.readLine();
378 }
379
380
381 return result;
382 }
383
384
385 private BotanicalName getNameFromLine(String line, Map<Integer, String> parameterMap, ICdmApplicationConfiguration appConfig) {
386 //Id%Version%Standard form%Default author forename%Default author surname%Taxon groups%Dates%Alternative names
387 String[] splits = line.split("%");
388 Map<String, String> valueMap = new HashMap<String, String>();
389
390 for (int i = 0; i < splits.length; i++){
391 valueMap.put(parameterMap.get(i), splits[i]);
392 }
393
394 BotanicalName name = BotanicalName.NewInstance(null);
395
396 //caches
397 name.setNameCache(valueMap.get(FULL_NAME_WITHOUT_FAMILY_AND_AUTHORS), true);
398 name.setAuthorshipCache(valueMap.get(AUTHORS), true);
399
400 //epithets
401 name.setGenusOrUninomial(valueMap.get(GENUS));
402 name.setInfraGenericEpithet(valueMap.get(INFRA_GENUS));
403 name.setSpecificEpithet(valueMap.get(SPECIES));
404 name.setInfraSpecificEpithet(valueMap.get(INFRA_SPECIFIC));
405
406 //rank
407 try {
408 String rankStr = nomalizeRank(valueMap.get(RANK));
409 name.setRank(Rank.getRankByNameOrAbbreviation(rankStr, NomenclaturalCode.ICBN, true));
410 } catch (UnknownCdmTypeException e) {
411 logger.warn("Rank was unknown");
412 }
413
414 //authors
415 name.setBasionymAuthorTeam(Team.NewTitledInstance(valueMap.get(BASIONYM_AUTHOR), valueMap.get(BASIONYM_AUTHOR)));
416 name.setCombinationAuthorTeam(Team.NewTitledInstance(valueMap.get(PUBLISHING_AUTHOR), valueMap.get(PUBLISHING_AUTHOR)));
417
418 //publication
419 ReferenceBase ref = ReferenceFactory.newGeneric();
420 ref.setTitleCache(valueMap.get(PUBLICATION));
421 TimePeriod datePublished = TimePeriod.parseString(valueMap.get(PUBLICATION_YEAR_FULL));
422 name.setNomenclaturalReference(ref);
423
424 //name status
425 NomenclaturalStatusType statusType = null;
426 String statusString = valueMap.get(NAME_STATUS);
427 if (StringUtils.isNotBlank(statusString)){
428 try {
429 statusType = NomenclaturalStatusType.getNomenclaturalStatusTypeByAbbreviation(statusString);
430 NomenclaturalStatus nomStatus = NomenclaturalStatus.NewInstance(statusType);
431 name.addStatus(nomStatus);
432 } catch (UnknownCdmTypeException e) {
433 logger.warn("Name status not recognized: " + statusString);
434 }
435 }
436
437 //remarks
438 String remarks = valueMap.get(REMARKS);
439 Annotation annotation = Annotation.NewInstance(remarks, AnnotationType.EDITORIAL(), Language.ENGLISH());
440 name.addAnnotation(annotation);
441
442 //basionym
443 BotanicalName basionym = BotanicalName.NewInstance(null);
444 basionym.setTitleCache(valueMap.get(BASIONYM), true);
445 name.addBasionym(basionym);
446
447 //replaced synonym
448 BotanicalName replacedSynoynm = BotanicalName.NewInstance(null);
449 replacedSynoynm.setTitleCache(valueMap.get(REPLACED_SYNONYM), true);
450 name.addReplacedSynonym(replacedSynoynm, null, null, null);
451
452 //type information
453 DerivedUnitFacade specimen = DerivedUnitFacade.NewInstance(DerivedUnitType.Specimen);
454
455
456 //gathering period
457 String collectionDateAsText = valueMap.get(COLLECTION_DATE_AS_TEXT);
458 TimePeriod gatheringPeriod = TimePeriod.parseString(collectionDateAsText);
459
460 try {
461 gatheringPeriod.setStartDay(getIntegerDateValueOrNull(valueMap, COLLECTION_DAY1));
462 gatheringPeriod.setStartMonth(getIntegerDateValueOrNull(valueMap, COLLECTION_MONTH1));
463 gatheringPeriod.setStartYear(getIntegerDateValueOrNull(valueMap, COLLECTION_YEAR1));
464 gatheringPeriod.setEndDay(getIntegerDateValueOrNull(valueMap, COLLECTION_DAY2));
465 gatheringPeriod.setEndMonth(getIntegerDateValueOrNull(valueMap, COLLECTION_MONTH2));
466 gatheringPeriod.setEndYear(getIntegerDateValueOrNull(valueMap, COLLECTION_YEAR2));
467 } catch (IndexOutOfBoundsException e) {
468 logger.info("Exception occurred when trying to fill gathering period");
469 }
470 specimen.setGatheringPeriod(gatheringPeriod);
471
472 specimen.setFieldNumber(valueMap.get(COLLECTION_NUMBER));
473
474 //collector team
475 String team = valueMap.get(COLLECTOR_TEAM_AS_TEXT);
476 Team collectorTeam = Team.NewTitledInstance(team, team);
477 specimen.setCollector(collectorTeam);
478
479 specimen.setLocality(valueMap.get(LOCALITY));
480
481 try {
482 String latDegrees = CdmUtils.Nz(valueMap.get(LATITUDE_DEGREES));
483 String latMinutes = CdmUtils.Nz(valueMap.get(LATITUDE_MINUTES));
484 String latSeconds = CdmUtils.Nz(valueMap.get(LATITUDE_SECONDS));
485 String direction = CdmUtils.Nz(valueMap.get(NORTH_OR_SOUTH));
486 String latitude = latDegrees + "°" + latMinutes + "'" + latSeconds + "\"" + direction;
487
488 String lonDegrees = CdmUtils.Nz(valueMap.get(LATITUDE_DEGREES));
489 String lonMinutes = CdmUtils.Nz(valueMap.get(LATITUDE_MINUTES));
490 String lonSeconds = CdmUtils.Nz(valueMap.get(LATITUDE_SECONDS));
491 direction = CdmUtils.Nz(valueMap.get(EAST_OR_WEST));
492 String longitude = lonDegrees + "°" + lonMinutes + "'" + lonSeconds + "\"" + direction;
493
494
495 specimen.setExactLocationByParsing(longitude, latitude, null, null);
496 } catch (ParseException e) {
497 logger.info("Parsing exception occurred when trying to parse type exact location." + e.getMessage());
498 } catch (Exception e) {
499 logger.info("Exception occurred when trying to read type exact location." + e.getMessage());
500 }
501
502
503 //type annotation
504 Annotation typeAnnotation = Annotation.NewInstance(TYPE_REMARKS, AnnotationType.EDITORIAL(), Language.DEFAULT());
505 specimen.addAnnotation(typeAnnotation);
506
507
508 //TODO Type name
509 //TODO "Type locations" , eg. holotype CAT ,isotype CAT ,isotype FI
510
511 //TODO Geographic unit as text
512
513
514
515
516
517 //source
518 ReferenceBase citation = getIpniCitation(appConfig);
519 name.addSource(valueMap.get(ID), "Name", citation, valueMap.get(VERSION));
520
521
522 // //TODO
523 //SHORT Family, Infra family, Hybrid genus, Hybrid, Collation, Nomenclatural synonym, Distribution, Citation type
524 /* EXTENDED
525 * Species author,
526 * Standardised basionym author flag,
527 * Standardised publishing author flag
528 Full name
529 Full name without family
530 Full name without authors
531
532 Reference
533 Standardised publication flag
534 Publication year
535 publication year note
536 Publication year text
537 Volume
538 Start page
539 End page
540 Primary pagination
541 Secondary pagination
542 Reference remarks
543 Hybrid parents
544 Replaced synonym Author team
545 Other links
546 Same citation as
547 Bibliographic reference
548 Bibliographic type info
549
550 Original taxon name
551 Original taxon name author team
552 Original replaced synonym
553 Original replaced synonym author team
554 Original basionym
555 Original basionym author team
556 Original parent citation taxon name author team
557 Original taxon distribution
558 Original hybrid parentage
559 Original cited type
560 Original remarks
561
562 */
563 return name;
564 }
565
566 /**
567 * @param valueMap
568 * @return
569 */
570 private Integer getIntegerDateValueOrNull(Map<String, String> valueMap, String key) {
571 try {
572 Integer result = Integer.valueOf(valueMap.get(key));
573 if (result == 0){
574 result = null;
575 }
576 return result;
577 } catch (NumberFormatException e) {
578 if (logger.isDebugEnabled()){
579 logger.debug("Number Format exception for " + valueMap.get(key));
580 }
581 return null;
582 }
583 }
584
585
586 private String nomalizeRank(String string) {
587 String result = string.replace("spec.", "sp.");
588 return result;
589 }
590
591
592 private List<Person> buildAuthorList(InputStream content, ICdmApplicationConfiguration services, IIpniServiceConfigurator iConfig) throws IOException {
593 IpniServiceAuthorConfigurator config = (IpniServiceAuthorConfigurator)iConfig;
594 List<Person> result = new ArrayList<Person>();
595 BufferedReader reader = new BufferedReader (new InputStreamReader(content));
596
597 String headerLine = reader.readLine();
598 if (headerLine != null){
599 Map<Integer, String> parameterMap = getParameterMap(headerLine);
600
601 String line = reader.readLine();
602 while (StringUtils.isNotBlank(line)){
603 Person author = getAuthorFromLine(line,parameterMap, services, config);
604 result.add(author);
605 line = reader.readLine();
606 }
607 }
608
609 return result;
610 }
611
612
613
614 private Map<Integer, String> getParameterMap(String headerLine) {
615 Map<Integer, String> result = new HashMap<Integer, String>();
616 String[] splits = headerLine.split("%");
617 for (int i = 0; i < splits.length ; i ++){
618 result.put(i, splits[i]);
619 }
620 return result;
621 }
622
623
624 private Person getAuthorFromLine(String line, Map<Integer, String> categoryMap, ICdmApplicationConfiguration appConfig, IpniServiceAuthorConfigurator config) {
625 //Id%Version%Standard form%Default author forename%Default author surname%Taxon groups%Dates%Alternative names
626 String[] splits = line.split("%");
627 Map<String, String> valueMap = new HashMap<String, String>();
628
629 for (int i = 0; i < splits.length; i++){
630 valueMap.put(categoryMap.get(i), splits[i]);
631 }
632
633 Person person = Person.NewInstance();
634
635 person.setNomenclaturalTitle(valueMap.get(STANDARD_FORM));
636 person.setFirstname(valueMap.get(DEFAULT_AUTHOR_FORENAME));
637 person.setLastname(valueMap.get(DEFAULT_AUTHOR_SURNAME));
638
639 ReferenceBase citation = getIpniCitation(appConfig);
640
641 //id, version
642 person.addSource(valueMap.get(ID), "Author", citation, valueMap.get(VERSION));
643
644 //dates
645 TimePeriod lifespan = TimePeriod.parseString(valueMap.get(DATES));
646 person.setLifespan(lifespan);
647
648 //alternative_names
649 String alternativeNames = valueMap.get(ALTERNATIVE_NAMES);
650 if (StringUtils.isNotBlank(alternativeNames)){
651 String[] alternativeNameSplits = alternativeNames.split("%");
652 for (String alternativeName : alternativeNameSplits){
653 if (alternativeName.startsWith(">")){
654 alternativeName = alternativeName.substring(1);
655 }
656 Extension.NewInstance(person, alternativeName, ExtensionType.INFORMAL_CATEGORY());
657 }
658 }
659
660 //TODO taxonGroups
661
662 return person;
663 }
664
665
666 private ReferenceBase getIpniCitation(ICdmApplicationConfiguration appConfig) {
667 ReferenceBase ipniReference;
668 if (appConfig != null){
669 ipniReference = appConfig.getReferenceService().find(uuidIpni);
670 if (ipniReference == null){
671 ipniReference = getNewIpniReference();
672 ipniReference.setUuid(uuidIpni);
673 appConfig.getReferenceService().save(ipniReference);
674 }
675 }else{
676 ipniReference = getNewIpniReference();
677 }
678 return ipniReference;
679 }
680
681 /**
682 * @return
683 */
684 private ReferenceBase getNewIpniReference() {
685 ReferenceBase ipniReference;
686 ipniReference = ReferenceFactory.newDatabase();
687 ipniReference.setTitleCache("The International Plant Names Index (IPNI)");
688 return ipniReference;
689 }
690
691
692 /**
693 * @param parameter
694 */
695 private String normalizeParameter(String parameter) {
696 String result = CdmUtils.Nz(parameter).replace(" ", "+");
697 return result;
698 }
699
700 public List<BotanicalName> getNamesAdvanced(String family, String genus, String species, String infraFamily,
701 String infraGenus, String infraSpecies, String authorAbbrev, Boolean includePublicationAuthors,
702 Boolean includeBasionymAuthors,
703 String publicationTitle,
704 Boolean isAPNIRecord,
705 Boolean isGCIRecord,
706 Boolean isIKRecord,
707 Rank rankInRangeToReturn,
708 Boolean sortByFamily,
709 IpniServiceNamesConfigurator config,
710 ICdmApplicationConfiguration services){
711 IpniRank ipniRank = IpniRank.valueOf(rankInRangeToReturn);
712 return getNamesAdvanced(family, genus, species, infraFamily, infraGenus, infraSpecies, authorAbbrev, includePublicationAuthors, includeBasionymAuthors, publicationTitle, isAPNIRecord, isGCIRecord, isIKRecord, ipniRank, sortByFamily, config, services);
713 }
714
715 public List<BotanicalName> getNamesAdvanced(String family, String genus, String species, String infraFamily,
716 String infraGenus, String infraSpecies, String authorAbbrev, Boolean includePublicationAuthors,
717 Boolean includeBasionymAuthors,
718 String publicationTitle,
719 Boolean isAPNIRecord,
720 Boolean isGCIRecord,
721 Boolean isIKRecord,
722 IpniRank rankToReturn,
723 Boolean sortByFamily,
724 IpniServiceNamesConfigurator config,
725 ICdmApplicationConfiguration services) {
726
727 // find_rankToReturn=all&output_format=normal&find_sortByFamily=on&find_sortByFamily=off&query_type=by_query&back_page=plantsearch
728
729 //config
730 if (config == null){
731 config = new IpniServiceNamesConfigurator();
732 }
733
734
735 family = normalizeParameter(family);
736 genus = normalizeParameter(genus);
737 species = normalizeParameter(species);
738 infraFamily = normalizeParameter(infraFamily);
739 infraGenus = normalizeParameter(infraGenus);
740 infraSpecies = normalizeParameter(infraSpecies);
741 authorAbbrev = normalizeParameter(authorAbbrev);
742
743 publicationTitle = normalizeParameter(publicationTitle);
744
745 DelimitedFormat format = config.getFormat();
746
747 String request =
748 "find_family=" + family +
749 "&find_genus=" + genus +
750 "&find_species=" + species +
751 "&find_infrafamily=" + infraFamily +
752 "&find_infragenus=" + infraGenus +
753 "&find_infraspecies=" + infraSpecies +
754 "&find_authorAbbrev=" + authorAbbrev +
755 getBooleanParameter("&find_includePublicationAuthors=", includePublicationAuthors, "on", "off") +
756 getBooleanParameter("&find_includeBasionymAuthors=", includePublicationAuthors, "on", "off") +
757 getBooleanParameter("&find_find_isAPNIRecord=", includePublicationAuthors, "on", "false") +
758 getBooleanParameter("&find_isGCIRecord=", includePublicationAuthors, "on", "false") +
759 getBooleanParameter("&find_isIKRecord=", includePublicationAuthors, "on", "false") +
760
761
762 "&find_publicationTitle=" + publicationTitle +
763 "&output_format=" + format.parameter;
764
765 return (List)queryService(request, services, getServiceUrl(IIpniService.ADVANCED_NAME_SERVICE_URL), config, ServiceType.NAME);
766 }
767
768
769 private String getBooleanParameter(String urlParamString, Boolean booleanParameter, String trueString, String falseString) {
770 String result;
771 if (booleanParameter == null){
772 result = getBooleanParameter(urlParamString, true, trueString, falseString) + getBooleanParameter(urlParamString, false, trueString, falseString);
773 }else if (booleanParameter == true){
774 result = urlParamString + trueString;
775 }else {
776 result = urlParamString + falseString;
777 }
778 return result;
779 }
780
781
782 /* (non-Javadoc)
783 * @see eu.etaxonomy.cdm.ext.IIpniService#getNamesSimple(java.lang.String, eu.etaxonomy.cdm.ext.IIpniService.DelimitedFormat, eu.etaxonomy.cdm.api.application.ICdmApplicationConfiguration)
784 */
785 public List<BotanicalName> getNamesSimple(String wholeName, ICdmApplicationConfiguration services, IpniServiceNamesConfigurator config){
786 if (config == null){
787 config = new IpniServiceNamesConfigurator();
788 }
789
790
791 // query_type=by_query&back_page=query_ipni.html
792
793 wholeName = normalizeParameter(wholeName);
794
795 DelimitedFormat format = config.getFormat();
796
797 String request = "find_wholeName=" + wholeName +
798 "&output_format=" + format.parameter;
799
800 return (List)queryService(request, services, getServiceUrl(IIpniService.SIMPLE_NAME_SERVICE_URL), config, ServiceType.NAME);
801 }
802
803 /* (non-Javadoc)
804 * @see eu.etaxonomy.cdm.ext.IIpniService#getPublications(java.lang.String, java.lang.String, boolean, eu.etaxonomy.cdm.api.application.ICdmApplicationConfiguration)
805 */
806 public List<ReferenceBase> getPublications(String title, String abbreviation, ICdmApplicationConfiguration services, IpniServicePublicationConfigurator config){
807 // http://www.uk.ipni.org/ipni/advPublicationSearch.do?find_title=Spe*plant*&find_abbreviation=&output_format=normal&query_type=by_query&back_page=publicationsearch
808 // http://www.uk.ipni.org/ipni/advPublicationSearch.do?find_title=*Hortus+Britannicus*&find_abbreviation=&output_format=delimited-classic&output_format=delimited
809
810 if (config == null){
811 config = new IpniServicePublicationConfigurator();
812 }
813
814 title = normalizeParameter(title);
815 abbreviation = normalizeParameter(abbreviation);
816
817 String request = "find_title=" + title +
818 "&find_abbreviation=" + abbreviation +
819 "&output_format=" + DelimitedFormat.CLASSIC.parameter;
820
821 List<ReferenceBase> result = (List)queryService(request, services, getServiceUrl(IIpniService.PUBLICATION_SERVICE_URL), config, ServiceType.PUBLICATION);
822 return result;
823 }
824
825
826
827 /**
828 * @return
829 */
830 private DelimitedFormat getDefaultFormat() {
831 return DelimitedFormat.SHORT;
832 }
833
834
835 /**
836 * The service url
837 *
838 * @return the serviceUrl
839 */
840 public URL getServiceUrl(String url) {
841 URL serviceUrl;
842 try {
843 serviceUrl = new URL(url);
844 } catch (MalformedURLException e) {
845 throw new RuntimeException("This should not happen", e);
846 }
847 return serviceUrl;
848 }
849
850
851
852 }