3 * Copyright (C) 2009 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
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.
10 package eu
.etaxonomy
.cdm
.ext
.ipni
;
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
;
19 import java
.net
.URISyntaxException
;
21 import java
.text
.ParseException
;
22 import java
.util
.ArrayList
;
23 import java
.util
.HashMap
;
24 import java
.util
.List
;
27 import org
.apache
.commons
.lang
.StringUtils
;
28 import org
.apache
.http
.HttpResponse
;
29 import org
.apache
.log4j
.Logger
;
30 import org
.springframework
.stereotype
.Component
;
32 import eu
.etaxonomy
.cdm
.api
.application
.ICdmApplicationConfiguration
;
33 import eu
.etaxonomy
.cdm
.api
.facade
.DerivedUnitFacade
;
34 import eu
.etaxonomy
.cdm
.api
.facade
.DerivedUnitFacade
.DerivedUnitType
;
35 import eu
.etaxonomy
.cdm
.common
.CdmUtils
;
36 import eu
.etaxonomy
.cdm
.common
.UriUtils
;
37 import eu
.etaxonomy
.cdm
.model
.agent
.Person
;
38 import eu
.etaxonomy
.cdm
.model
.agent
.Team
;
39 import eu
.etaxonomy
.cdm
.model
.common
.Annotation
;
40 import eu
.etaxonomy
.cdm
.model
.common
.AnnotationType
;
41 import eu
.etaxonomy
.cdm
.model
.common
.Extension
;
42 import eu
.etaxonomy
.cdm
.model
.common
.ExtensionType
;
43 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableEntity
;
44 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
45 import eu
.etaxonomy
.cdm
.model
.common
.TimePeriod
;
46 import eu
.etaxonomy
.cdm
.model
.name
.BotanicalName
;
47 import eu
.etaxonomy
.cdm
.model
.name
.NomenclaturalCode
;
48 import eu
.etaxonomy
.cdm
.model
.name
.NomenclaturalStatus
;
49 import eu
.etaxonomy
.cdm
.model
.name
.NomenclaturalStatusType
;
50 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
51 import eu
.etaxonomy
.cdm
.model
.reference
.Reference
;
52 import eu
.etaxonomy
.cdm
.model
.reference
.ReferenceFactory
;
53 import eu
.etaxonomy
.cdm
.strategy
.exceptions
.UnknownCdmTypeException
;
58 * @created Aug 16, 2010
61 * TODO the whole ipni service should be refactored to use UriUtils. I did this for the queryService method only because we ran into timeout
62 * problems in tests. UriUtils handles these problems already.
66 public class IpniService
implements IIpniService
{
67 private static final String EAST_OR_WEST
= "East or west";
69 private static final String NORTH_OR_SOUTH
= "North or south";
71 private static final String LATITUDE_SECONDS
= "Latitude seconds";
73 private static final String LATITUDE_MINUTES
= "Latitude minutes";
75 private static final String LATITUDE_DEGREES
= "Latitude degrees";
77 private static final String COLLECTION_DATE_AS_TEXT
= "Collection date as text";
79 private static final String COLLECTION_DAY1
= "Collection day1";
81 private static final String COLLECTION_MONTH1
= "Collection month1";
83 private static final String COLLECTION_YEAR1
= "Collection year1";
85 private static final String COLLECTION_DAY2
= "Collection day2";
87 private static final String COLLECTION_MONTH2
= "Collection month2";
89 private static final String COLLECTION_YEAR2
= "Collection year2";
91 private static final String COLLECTION_NUMBER
= "Collection number";
93 private static final String COLLECTOR_TEAM_AS_TEXT
= "Collector team as text";
95 private static final String LOCALITY
= "Locality";
97 private static final String TYPE_REMARKS
= "Type remarks";
99 private static final Logger logger
= Logger
.getLogger(IpniService
.class);
102 public static String ID
= "Id";
103 public static String VERSION
= "Version";
104 public static final String REMARKS
= "Remarks";
107 public static final String FULL_NAME_WITHOUT_FAMILY_AND_AUTHORS
= "Full name without family and authors";
108 public static final String AUTHORS
= "Authors";
109 public static final String FAMILY
= "Family";
110 public static final String GENUS
= "Genus";
111 public static final String INFRA_GENUS
= "Infra genus";
112 public static final String SPECIES
= "Species";
113 public static final String INFRA_SPECIFIC
= "Infra species";
114 public static final String RANK
= "Rank";
115 public static final String BASIONYM_AUTHOR
= "Basionym author";
116 public static final String PUBLISHING_AUTHOR
= "Publishing author";
117 public static final String PUBLICATION
= "Publication";
118 public static final String PUBLICATION_YEAR_FULL
= "Publication year full";
119 public static final String NAME_STATUS
= "Name status";
120 public static final String BASIONYM
= "Basionym";
121 public static final String REPLACED_SYNONYM
= "Replaced synonym";
126 public static final String STANDARD_FORM
= "Standard Form";
128 public static final String DEFAULT_AUTHOR_FORENAME
= "Default author forename";
129 public static final String DEFAULT_AUTHOR_SURNAME
= "Default author surname";
130 public static final String TAXON_GROUPS
= "Taxon groups";
131 public static final String DATES
= "Dates";
132 public static final String ALTERNATIVE_NAMES
= "Alternative names";
134 public static final String DEFAULT_AUTHOR_NAME
= "Default author name";
136 public static final String NAME_NOTES
= "Name notes";
137 public static final String NAME_SOURCE
= "Name source";
138 public static final String DATE_TYPE_CODE
= "Date type code";
139 public static final String DATE_TYPE_STRING
= "Date type string";
141 public static final String ALTERNATIVE_ABBREVIATIONS
= "Alternative abbreviations";
142 public static final String EXAMPLE_OF_NAME_PUBLISHED
= "Example of name published";
147 public static final String ABBREVIATION
= "Abbreviation";
148 public static final String TITLE
= "Title";
149 public static final String BPH_NUMBER
= "BPH number";
150 public static final String ISBN
= "ISBN";
151 public static final String ISSN
= "ISSN";
152 public static final String AUTHORS_ROLE
= "Authors role";
153 public static final String EDITION
= "Edition";
154 public static final String DATE
= "Date";
155 public static final String IN_PUBLICATION_FACADE
= "In publication facade";
156 public static final String LC_NUMBER
= "LC number";
157 public static final String PLACE
= "Place";
158 public static final String PUBLICATION_AUTHOR_TEAM
= "Publication author team";
159 public static final String PRECEDED_BY
= "Preceded";
160 public static final String TL2_AUTHOR
= "TL2 author";
161 public static final String TL2_NUMBER
= "TL2 number";
162 public static final String TDWG_ABBREVIATION
= "TDWG abbreviation";
164 private enum ServiceType
{
170 public enum IpniRank
{
172 FAMILIAL ("Familial"),
173 INFRA_FAMILIAL ("Infrafamilial"),
175 INFRA_GENERIC("Infrageneric"),
176 SPECIFIC ("Specific"),
177 INFRA_SPECIFIC("InfraSpecific");
180 IpniRank(String strRank
){
181 this.strRank
= strRank
;
184 public static IpniRank
valueOf(Rank rank
){
187 }else if (rank
.isInfraSpecific()){
188 return INFRA_SPECIFIC
;
189 }else if (rank
.isSpecies()){
191 }else if (rank
.isInfraGeneric()){
192 return INFRA_GENERIC
;
193 }else if (rank
.isGenus()){
195 }else if (rank
.isLower(Rank
.FAMILY())){
196 return INFRA_FAMILIAL
;
197 }else if (rank
.isHigher(Rank
.SUBFAMILY())){
200 logger
.warn("Rank could not be transformed to ipni rank. Use ALL instead");
207 // private URL serviceUrl;
209 // ******************************** CONSTRUCTOR **************************************
211 // ****************************** METHODS ****************************************************/
215 * @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)
217 public List
<Person
> getAuthors(String abbreviation
, String surname
, String forename
, String isoCountry
, ICdmApplicationConfiguration services
, IpniServiceAuthorConfigurator config
){
220 config
= new IpniServiceAuthorConfigurator();
224 abbreviation
= normalizeParameter(abbreviation
);
225 surname
= normalizeParameter(surname
);
226 isoCountry
= normalizeParameter(isoCountry
);
227 forename
= normalizeParameter(forename
);
229 DelimitedFormat format
= config
.getFormat();
231 String request
= "find_abbreviation=" + abbreviation
+
232 "&find_surname=" + surname
+
233 "&find_isoCountry=" + isoCountry
+
234 "&find_forename=" + forename
+
235 "&output_format=" + format
.parameter
;
237 return (List
)queryService(request
, services
, getServiceUrl(IIpniService
.AUTHOR_SERVICE_URL
), config
, ServiceType
.AUTHOR
);
242 * FIXME rewrote this method to rely on {@link UriUtils}. The whole class should be adjusted to reflect this change.
243 * Also see comments in the class' documentation block.
248 private List
<?
extends IdentifiableEntity
> queryService(String request
, ICdmApplicationConfiguration services
, URL serviceUrl
, IIpniServiceConfigurator config
, ServiceType serviceType
){
250 throw new NullPointerException("Ipni service configurator should not be null");
254 // create the request url
255 URL newUrl
= new URL(serviceUrl
.getProtocol(),
256 serviceUrl
.getHost(),
257 serviceUrl
.getPort(),
262 URI newUri
= newUrl
.toURI();
264 logger
.info("Firing request for URI: " + newUri
);
266 HttpResponse response
= UriUtils
.getResponse(newUri
, null);
268 int responseCode
= response
.getStatusLine().getStatusCode();
270 // get the content at the resource
271 InputStream content
= response
.getEntity().getContent();
273 List
<?
extends IdentifiableEntity
> result
;
274 if (serviceType
.equals(ServiceType
.AUTHOR
)){
275 result
= buildAuthorList(content
, services
, config
);
276 }else if (serviceType
.equals(ServiceType
.NAME
)){
277 result
= buildNameList(content
, services
, config
);
279 result
= buildPublicationList(content
, services
, config
);
281 if(responseCode
== HttpURLConnection
.HTTP_OK
){
284 //TODO error handling
285 logger
.error("No Http_OK");
288 } catch (IOException e
) {
289 logger
.error("No content for request: " + request
);
290 } catch (URISyntaxException e
) {
291 logger
.error("Given URL could not be transformed into URI", e
);
298 private List
<Reference
> buildPublicationList( InputStream content
, ICdmApplicationConfiguration services
, IIpniServiceConfigurator iConfig
) throws IOException
{
299 IpniServicePublicationConfigurator config
= (IpniServicePublicationConfigurator
)iConfig
;
301 List
<Reference
> result
= new ArrayList
<Reference
>();
302 BufferedReader reader
= new BufferedReader (new InputStreamReader(content
));
304 String headerLine
= reader
.readLine();
305 Map
<Integer
, String
> parameterMap
= getParameterMap(headerLine
);
307 String line
= reader
.readLine();
308 while (StringUtils
.isNotBlank(line
)){
309 Reference reference
= getPublicationFromLine(line
, parameterMap
, services
, config
);
310 result
.add(reference
);
311 line
= reader
.readLine();
320 * @param parameterMap
325 private Reference
getPublicationFromLine(String line
, Map
<Integer
, String
> parameterMap
, ICdmApplicationConfiguration appConfig
, IpniServicePublicationConfigurator config
) {
327 String
[] splits
= line
.split("%");
329 Map
<String
, String
> valueMap
= new HashMap
<String
, String
>();
330 for (int i
= 0; i
< splits
.length
; i
++){
331 valueMap
.put(parameterMap
.get(i
), splits
[i
]);
334 //create reference object
335 Reference ref
= ReferenceFactory
.newGeneric();
338 if (config
.isUseAbbreviationAsTitle() == true){
339 ref
.setTitle(valueMap
.get(ABBREVIATION
));
340 //TODO handle title as extension
342 ref
.setTitle(valueMap
.get(TITLE
));
343 //TODO handle abbreviation as extension
345 ref
.setIsbn(valueMap
.get(ISBN
));
346 ref
.setIssn(valueMap
.get(ISSN
));
347 ref
.setEdition(valueMap
.get(EDITION
));
348 ref
.setPlacePublished(valueMap
.get(PLACE
));
350 String author
= valueMap
.get(PUBLICATION_AUTHOR_TEAM
);
351 if (StringUtils
.isNotBlank(author
)){
352 Team team
= Team
.NewTitledInstance(author
, author
);
353 ref
.setAuthorTeam(team
);
357 String remarks
= valueMap
.get(REMARKS
);
358 Annotation annotation
= Annotation
.NewInstance(remarks
, AnnotationType
.EDITORIAL(), Language
.ENGLISH());
359 ref
.addAnnotation(annotation
);
362 String tl2AuthorString
= valueMap
.get(TL2_AUTHOR
);
363 if (ref
.getAuthorTeam() == null){
364 Team tl2Author
= Team
.NewTitledInstance(tl2AuthorString
, null);
365 ref
.setAuthorTeam(tl2Author
);
368 ref
.getAuthorTeam().setTitleCache(tl2AuthorString
, true);
369 ref
.addAnnotation(Annotation
.NewInstance(tl2AuthorString
, AnnotationType
.EDITORIAL(), Language
.ENGLISH()));
374 TimePeriod date
= TimePeriod
.parseString(valueMap
.get(DATE
));
375 ref
.setDatePublished(date
);
379 Reference citation
= getIpniCitation(appConfig
);
380 ref
.addSource(valueMap
.get(ID
), "Publication", citation
, valueMap
.get(VERSION
));
387 In publication facade
398 private List
<BotanicalName
> buildNameList( InputStream content
, ICdmApplicationConfiguration appConfig
, IIpniServiceConfigurator iConfig
) throws IOException
{
399 IpniServiceNamesConfigurator config
= (IpniServiceNamesConfigurator
)iConfig
;
400 List
<BotanicalName
> result
= new ArrayList
<BotanicalName
>();
401 BufferedReader reader
= new BufferedReader (new InputStreamReader(content
));
403 String headerLine
= reader
.readLine();
404 Map
<Integer
, String
> parameterMap
= getParameterMap(headerLine
);
406 String line
= reader
.readLine();
407 while (StringUtils
.isNotBlank(line
)){
408 BotanicalName name
= getNameFromLine(line
,parameterMap
, appConfig
);
410 line
= reader
.readLine();
418 private BotanicalName
getNameFromLine(String line
, Map
<Integer
, String
> parameterMap
, ICdmApplicationConfiguration appConfig
) {
419 //Id%Version%Standard form%Default author forename%Default author surname%Taxon groups%Dates%Alternative names
420 String
[] splits
= line
.split("%");
421 Map
<String
, String
> valueMap
= new HashMap
<String
, String
>();
423 for (int i
= 0; i
< splits
.length
; i
++){
424 valueMap
.put(parameterMap
.get(i
), splits
[i
]);
427 BotanicalName name
= BotanicalName
.NewInstance(null);
430 name
.setNameCache(valueMap
.get(FULL_NAME_WITHOUT_FAMILY_AND_AUTHORS
), true);
431 name
.setAuthorshipCache(valueMap
.get(AUTHORS
), true);
434 name
.setGenusOrUninomial(valueMap
.get(GENUS
));
435 name
.setInfraGenericEpithet(valueMap
.get(INFRA_GENUS
));
436 name
.setSpecificEpithet(valueMap
.get(SPECIES
));
437 name
.setInfraSpecificEpithet(valueMap
.get(INFRA_SPECIFIC
));
441 String rankStr
= nomalizeRank(valueMap
.get(RANK
));
442 name
.setRank(Rank
.getRankByNameOrAbbreviation(rankStr
, NomenclaturalCode
.ICNAFP
, true));
443 } catch (UnknownCdmTypeException e
) {
444 logger
.warn("Rank was unknown");
448 name
.setBasionymAuthorTeam(Team
.NewTitledInstance(valueMap
.get(BASIONYM_AUTHOR
), valueMap
.get(BASIONYM_AUTHOR
)));
449 name
.setCombinationAuthorTeam(Team
.NewTitledInstance(valueMap
.get(PUBLISHING_AUTHOR
), valueMap
.get(PUBLISHING_AUTHOR
)));
452 Reference ref
= ReferenceFactory
.newGeneric();
453 ref
.setTitleCache(valueMap
.get(PUBLICATION
));
454 TimePeriod datePublished
= TimePeriod
.parseString(valueMap
.get(PUBLICATION_YEAR_FULL
));
455 name
.setNomenclaturalReference(ref
);
458 NomenclaturalStatusType statusType
= null;
459 String statusString
= valueMap
.get(NAME_STATUS
);
460 if (StringUtils
.isNotBlank(statusString
)){
462 statusType
= NomenclaturalStatusType
.getNomenclaturalStatusTypeByAbbreviation(statusString
);
463 NomenclaturalStatus nomStatus
= NomenclaturalStatus
.NewInstance(statusType
);
464 name
.addStatus(nomStatus
);
465 } catch (UnknownCdmTypeException e
) {
466 logger
.warn("Name status not recognized: " + statusString
);
471 String remarks
= valueMap
.get(REMARKS
);
472 Annotation annotation
= Annotation
.NewInstance(remarks
, AnnotationType
.EDITORIAL(), Language
.ENGLISH());
473 name
.addAnnotation(annotation
);
476 BotanicalName basionym
= BotanicalName
.NewInstance(null);
477 basionym
.setTitleCache(valueMap
.get(BASIONYM
), true);
478 name
.addBasionym(basionym
);
481 BotanicalName replacedSynoynm
= BotanicalName
.NewInstance(null);
482 replacedSynoynm
.setTitleCache(valueMap
.get(REPLACED_SYNONYM
), true);
483 name
.addReplacedSynonym(replacedSynoynm
, null, null, null);
486 DerivedUnitFacade specimen
= DerivedUnitFacade
.NewInstance(DerivedUnitType
.Specimen
);
490 String collectionDateAsText
= valueMap
.get(COLLECTION_DATE_AS_TEXT
);
491 TimePeriod gatheringPeriod
= TimePeriod
.parseString(collectionDateAsText
);
494 gatheringPeriod
.setStartDay(getIntegerDateValueOrNull(valueMap
, COLLECTION_DAY1
));
495 gatheringPeriod
.setStartMonth(getIntegerDateValueOrNull(valueMap
, COLLECTION_MONTH1
));
496 gatheringPeriod
.setStartYear(getIntegerDateValueOrNull(valueMap
, COLLECTION_YEAR1
));
497 gatheringPeriod
.setEndDay(getIntegerDateValueOrNull(valueMap
, COLLECTION_DAY2
));
498 gatheringPeriod
.setEndMonth(getIntegerDateValueOrNull(valueMap
, COLLECTION_MONTH2
));
499 gatheringPeriod
.setEndYear(getIntegerDateValueOrNull(valueMap
, COLLECTION_YEAR2
));
500 } catch (IndexOutOfBoundsException e
) {
501 logger
.info("Exception occurred when trying to fill gathering period");
503 specimen
.setGatheringPeriod(gatheringPeriod
);
505 specimen
.setFieldNumber(valueMap
.get(COLLECTION_NUMBER
));
508 String team
= valueMap
.get(COLLECTOR_TEAM_AS_TEXT
);
509 Team collectorTeam
= Team
.NewTitledInstance(team
, team
);
510 specimen
.setCollector(collectorTeam
);
512 specimen
.setLocality(valueMap
.get(LOCALITY
));
515 String latDegrees
= CdmUtils
.Nz(valueMap
.get(LATITUDE_DEGREES
));
516 String latMinutes
= CdmUtils
.Nz(valueMap
.get(LATITUDE_MINUTES
));
517 String latSeconds
= CdmUtils
.Nz(valueMap
.get(LATITUDE_SECONDS
));
518 String direction
= CdmUtils
.Nz(valueMap
.get(NORTH_OR_SOUTH
));
519 String latitude
= latDegrees
+ "°" + latMinutes
+ "'" + latSeconds
+ "\"" + direction
;
521 String lonDegrees
= CdmUtils
.Nz(valueMap
.get(LATITUDE_DEGREES
));
522 String lonMinutes
= CdmUtils
.Nz(valueMap
.get(LATITUDE_MINUTES
));
523 String lonSeconds
= CdmUtils
.Nz(valueMap
.get(LATITUDE_SECONDS
));
524 direction
= CdmUtils
.Nz(valueMap
.get(EAST_OR_WEST
));
525 String longitude
= lonDegrees
+ "°" + lonMinutes
+ "'" + lonSeconds
+ "\"" + direction
;
528 specimen
.setExactLocationByParsing(longitude
, latitude
, null, null);
529 } catch (ParseException e
) {
530 logger
.info("Parsing exception occurred when trying to parse type exact location." + e
.getMessage());
531 } catch (Exception e
) {
532 logger
.info("Exception occurred when trying to read type exact location." + e
.getMessage());
537 Annotation typeAnnotation
= Annotation
.NewInstance(TYPE_REMARKS
, AnnotationType
.EDITORIAL(), Language
.DEFAULT());
538 specimen
.addAnnotation(typeAnnotation
);
542 //TODO "Type locations" , eg. holotype CAT ,isotype CAT ,isotype FI
544 //TODO Geographic unit as text
551 Reference citation
= getIpniCitation(appConfig
);
552 name
.addSource(valueMap
.get(ID
), "Name", citation
, valueMap
.get(VERSION
));
556 //SHORT Family, Infra family, Hybrid genus, Hybrid, Collation, Nomenclatural synonym, Distribution, Citation type
559 * Standardised basionym author flag,
560 * Standardised publishing author flag
562 Full name without family
563 Full name without authors
566 Standardised publication flag
568 publication year note
569 Publication year text
577 Replaced synonym Author team
580 Bibliographic reference
581 Bibliographic type info
584 Original taxon name author team
585 Original replaced synonym
586 Original replaced synonym author team
588 Original basionym author team
589 Original parent citation taxon name author team
590 Original taxon distribution
591 Original hybrid parentage
603 private Integer
getIntegerDateValueOrNull(Map
<String
, String
> valueMap
, String key
) {
605 Integer result
= Integer
.valueOf(valueMap
.get(key
));
610 } catch (NumberFormatException e
) {
611 if (logger
.isDebugEnabled()){
612 logger
.debug("Number Format exception for " + valueMap
.get(key
));
619 private String
nomalizeRank(String string
) {
620 String result
= string
.replace("spec.", "sp.");
625 private List
<Person
> buildAuthorList(InputStream content
, ICdmApplicationConfiguration services
, IIpniServiceConfigurator iConfig
) throws IOException
{
626 IpniServiceAuthorConfigurator config
= (IpniServiceAuthorConfigurator
)iConfig
;
627 List
<Person
> result
= new ArrayList
<Person
>();
628 BufferedReader reader
= new BufferedReader (new InputStreamReader(content
));
630 String headerLine
= reader
.readLine();
631 if (headerLine
!= null){
632 Map
<Integer
, String
> parameterMap
= getParameterMap(headerLine
);
634 String line
= reader
.readLine();
635 while (StringUtils
.isNotBlank(line
)){
636 Person author
= getAuthorFromLine(line
,parameterMap
, services
, config
);
638 line
= reader
.readLine();
647 private Map
<Integer
, String
> getParameterMap(String headerLine
) {
648 Map
<Integer
, String
> result
= new HashMap
<Integer
, String
>();
649 if ( headerLine
!= null ){
650 String
[] splits
= headerLine
.split("%");
651 for (int i
= 0; i
< splits
.length
; i
++){
652 result
.put(i
, splits
[i
]);
659 private Person
getAuthorFromLine(String line
, Map
<Integer
, String
> categoryMap
, ICdmApplicationConfiguration appConfig
, IpniServiceAuthorConfigurator config
) {
660 //Id%Version%Standard form%Default author forename%Default author surname%Taxon groups%Dates%Alternative names
661 String
[] splits
= line
.split("%");
662 Map
<String
, String
> valueMap
= new HashMap
<String
, String
>();
664 for (int i
= 0; i
< splits
.length
; i
++){
665 valueMap
.put(categoryMap
.get(i
), splits
[i
]);
668 Person person
= Person
.NewInstance();
670 person
.setNomenclaturalTitle(valueMap
.get(STANDARD_FORM
));
671 person
.setFirstname(valueMap
.get(DEFAULT_AUTHOR_FORENAME
));
672 person
.setLastname(valueMap
.get(DEFAULT_AUTHOR_SURNAME
));
674 Reference citation
= getIpniCitation(appConfig
);
677 person
.addSource(valueMap
.get(ID
), "Author", citation
, valueMap
.get(VERSION
));
680 TimePeriod lifespan
= TimePeriod
.parseString(valueMap
.get(DATES
));
681 person
.setLifespan(lifespan
);
684 String alternativeNames
= valueMap
.get(ALTERNATIVE_NAMES
);
685 if (StringUtils
.isNotBlank(alternativeNames
)){
686 String
[] alternativeNameSplits
= alternativeNames
.split("%");
687 for (String alternativeName
: alternativeNameSplits
){
688 if (alternativeName
.startsWith(">")){
689 alternativeName
= alternativeName
.substring(1);
691 Extension
.NewInstance(person
, alternativeName
, ExtensionType
.INFORMAL_CATEGORY());
701 private Reference
getIpniCitation(ICdmApplicationConfiguration appConfig
) {
702 Reference ipniReference
;
703 if (appConfig
!= null){
704 ipniReference
= appConfig
.getReferenceService().find(uuidIpni
);
705 if (ipniReference
== null){
706 ipniReference
= getNewIpniReference();
707 ipniReference
.setUuid(uuidIpni
);
708 appConfig
.getReferenceService().save(ipniReference
);
711 ipniReference
= getNewIpniReference();
713 return ipniReference
;
719 private Reference
getNewIpniReference() {
720 Reference ipniReference
;
721 ipniReference
= ReferenceFactory
.newDatabase();
722 ipniReference
.setTitleCache("The International Plant Names Index (IPNI)");
723 return ipniReference
;
730 private String
normalizeParameter(String parameter
) {
731 String result
= CdmUtils
.Nz(parameter
).replace(" ", "+");
735 public List
<BotanicalName
> getNamesAdvanced(String family
, String genus
, String species
, String infraFamily
,
736 String infraGenus
, String infraSpecies
, String authorAbbrev
, Boolean includePublicationAuthors
,
737 Boolean includeBasionymAuthors
,
738 String publicationTitle
,
739 Boolean isAPNIRecord
,
742 Rank rankInRangeToReturn
,
743 Boolean sortByFamily
,
744 IpniServiceNamesConfigurator config
,
745 ICdmApplicationConfiguration services
){
746 IpniRank ipniRank
= IpniRank
.valueOf(rankInRangeToReturn
);
747 return getNamesAdvanced(family
, genus
, species
, infraFamily
, infraGenus
, infraSpecies
, authorAbbrev
, includePublicationAuthors
, includeBasionymAuthors
, publicationTitle
, isAPNIRecord
, isGCIRecord
, isIKRecord
, ipniRank
, sortByFamily
, config
, services
);
750 public List
<BotanicalName
> getNamesAdvanced(String family
, String genus
, String species
, String infraFamily
,
751 String infraGenus
, String infraSpecies
, String authorAbbrev
, Boolean includePublicationAuthors
,
752 Boolean includeBasionymAuthors
,
753 String publicationTitle
,
754 Boolean isAPNIRecord
,
757 IpniRank rankToReturn
,
758 Boolean sortByFamily
,
759 IpniServiceNamesConfigurator config
,
760 ICdmApplicationConfiguration services
) {
762 // find_rankToReturn=all&output_format=normal&find_sortByFamily=on&find_sortByFamily=off&query_type=by_query&back_page=plantsearch
766 config
= new IpniServiceNamesConfigurator();
770 family
= normalizeParameter(family
);
771 genus
= normalizeParameter(genus
);
772 species
= normalizeParameter(species
);
773 infraFamily
= normalizeParameter(infraFamily
);
774 infraGenus
= normalizeParameter(infraGenus
);
775 infraSpecies
= normalizeParameter(infraSpecies
);
776 authorAbbrev
= normalizeParameter(authorAbbrev
);
778 publicationTitle
= normalizeParameter(publicationTitle
);
780 DelimitedFormat format
= config
.getFormat();
783 "find_family=" + family
+
784 "&find_genus=" + genus
+
785 "&find_species=" + species
+
786 "&find_infrafamily=" + infraFamily
+
787 "&find_infragenus=" + infraGenus
+
788 "&find_infraspecies=" + infraSpecies
+
789 "&find_authorAbbrev=" + authorAbbrev
+
790 getBooleanParameter("&find_includePublicationAuthors=", includePublicationAuthors
, "on", "off") +
791 getBooleanParameter("&find_includeBasionymAuthors=", includePublicationAuthors
, "on", "off") +
792 getBooleanParameter("&find_find_isAPNIRecord=", includePublicationAuthors
, "on", "false") +
793 getBooleanParameter("&find_isGCIRecord=", includePublicationAuthors
, "on", "false") +
794 getBooleanParameter("&find_isIKRecord=", includePublicationAuthors
, "on", "false") +
797 "&find_publicationTitle=" + publicationTitle
+
798 "&output_format=" + format
.parameter
;
800 return (List
)queryService(request
, services
, getServiceUrl(IIpniService
.ADVANCED_NAME_SERVICE_URL
), config
, ServiceType
.NAME
);
804 private String
getBooleanParameter(String urlParamString
, Boolean booleanParameter
, String trueString
, String falseString
) {
806 if (booleanParameter
== null){
807 result
= getBooleanParameter(urlParamString
, true, trueString
, falseString
) + getBooleanParameter(urlParamString
, false, trueString
, falseString
);
808 }else if (booleanParameter
== true){
809 result
= urlParamString
+ trueString
;
811 result
= urlParamString
+ falseString
;
818 * @see eu.etaxonomy.cdm.ext.IIpniService#getNamesSimple(java.lang.String, eu.etaxonomy.cdm.ext.IIpniService.DelimitedFormat, eu.etaxonomy.cdm.api.application.ICdmApplicationConfiguration)
820 public List
<BotanicalName
> getNamesSimple(String wholeName
, ICdmApplicationConfiguration services
, IpniServiceNamesConfigurator config
){
822 config
= new IpniServiceNamesConfigurator();
826 // query_type=by_query&back_page=query_ipni.html
828 wholeName
= normalizeParameter(wholeName
);
830 DelimitedFormat format
= config
.getFormat();
832 String request
= "find_wholeName=" + wholeName
+
833 "&output_format=" + format
.parameter
;
835 return (List
)queryService(request
, services
, getServiceUrl(IIpniService
.SIMPLE_NAME_SERVICE_URL
), config
, ServiceType
.NAME
);
839 * @see eu.etaxonomy.cdm.ext.IIpniService#getPublications(java.lang.String, java.lang.String, boolean, eu.etaxonomy.cdm.api.application.ICdmApplicationConfiguration)
841 public List
<Reference
> getPublications(String title
, String abbreviation
, ICdmApplicationConfiguration services
, IpniServicePublicationConfigurator config
){
842 // http://www.uk.ipni.org/ipni/advPublicationSearch.do?find_title=Spe*plant*&find_abbreviation=&output_format=normal&query_type=by_query&back_page=publicationsearch
843 // http://www.uk.ipni.org/ipni/advPublicationSearch.do?find_title=*Hortus+Britannicus*&find_abbreviation=&output_format=delimited-classic&output_format=delimited
846 config
= new IpniServicePublicationConfigurator();
849 title
= normalizeParameter(title
);
850 abbreviation
= normalizeParameter(abbreviation
);
852 String request
= "find_title=" + title
+
853 "&find_abbreviation=" + abbreviation
+
854 "&output_format=" + DelimitedFormat
.CLASSIC
.parameter
;
856 List
<Reference
> result
= (List
)queryService(request
, services
, getServiceUrl(IIpniService
.PUBLICATION_SERVICE_URL
), config
, ServiceType
.PUBLICATION
);
865 private DelimitedFormat
getDefaultFormat() {
866 return DelimitedFormat
.SHORT
;
873 * @return the serviceUrl
875 public URL
getServiceUrl(String url
) {
878 serviceUrl
= new URL(url
);
879 } catch (MalformedURLException e
) {
880 throw new RuntimeException("This should not happen", e
);