fbbd960cbf716894ed5061ee9696fe10658a0165
[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 if ( headerLine != null ){
617 String[] splits = headerLine.split("%");
618 for (int i = 0; i < splits.length ; i ++){
619 result.put(i, splits[i]);
620 }
621 }
622 return result;
623 }
624
625
626 private Person getAuthorFromLine(String line, Map<Integer, String> categoryMap, ICdmApplicationConfiguration appConfig, IpniServiceAuthorConfigurator config) {
627 //Id%Version%Standard form%Default author forename%Default author surname%Taxon groups%Dates%Alternative names
628 String[] splits = line.split("%");
629 Map<String, String> valueMap = new HashMap<String, String>();
630
631 for (int i = 0; i < splits.length; i++){
632 valueMap.put(categoryMap.get(i), splits[i]);
633 }
634
635 Person person = Person.NewInstance();
636
637 person.setNomenclaturalTitle(valueMap.get(STANDARD_FORM));
638 person.setFirstname(valueMap.get(DEFAULT_AUTHOR_FORENAME));
639 person.setLastname(valueMap.get(DEFAULT_AUTHOR_SURNAME));
640
641 ReferenceBase citation = getIpniCitation(appConfig);
642
643 //id, version
644 person.addSource(valueMap.get(ID), "Author", citation, valueMap.get(VERSION));
645
646 //dates
647 TimePeriod lifespan = TimePeriod.parseString(valueMap.get(DATES));
648 person.setLifespan(lifespan);
649
650 //alternative_names
651 String alternativeNames = valueMap.get(ALTERNATIVE_NAMES);
652 if (StringUtils.isNotBlank(alternativeNames)){
653 String[] alternativeNameSplits = alternativeNames.split("%");
654 for (String alternativeName : alternativeNameSplits){
655 if (alternativeName.startsWith(">")){
656 alternativeName = alternativeName.substring(1);
657 }
658 Extension.NewInstance(person, alternativeName, ExtensionType.INFORMAL_CATEGORY());
659 }
660 }
661
662 //TODO taxonGroups
663
664 return person;
665 }
666
667
668 private ReferenceBase getIpniCitation(ICdmApplicationConfiguration appConfig) {
669 ReferenceBase ipniReference;
670 if (appConfig != null){
671 ipniReference = appConfig.getReferenceService().find(uuidIpni);
672 if (ipniReference == null){
673 ipniReference = getNewIpniReference();
674 ipniReference.setUuid(uuidIpni);
675 appConfig.getReferenceService().save(ipniReference);
676 }
677 }else{
678 ipniReference = getNewIpniReference();
679 }
680 return ipniReference;
681 }
682
683 /**
684 * @return
685 */
686 private ReferenceBase getNewIpniReference() {
687 ReferenceBase ipniReference;
688 ipniReference = ReferenceFactory.newDatabase();
689 ipniReference.setTitleCache("The International Plant Names Index (IPNI)");
690 return ipniReference;
691 }
692
693
694 /**
695 * @param parameter
696 */
697 private String normalizeParameter(String parameter) {
698 String result = CdmUtils.Nz(parameter).replace(" ", "+");
699 return result;
700 }
701
702 public List<BotanicalName> getNamesAdvanced(String family, String genus, String species, String infraFamily,
703 String infraGenus, String infraSpecies, String authorAbbrev, Boolean includePublicationAuthors,
704 Boolean includeBasionymAuthors,
705 String publicationTitle,
706 Boolean isAPNIRecord,
707 Boolean isGCIRecord,
708 Boolean isIKRecord,
709 Rank rankInRangeToReturn,
710 Boolean sortByFamily,
711 IpniServiceNamesConfigurator config,
712 ICdmApplicationConfiguration services){
713 IpniRank ipniRank = IpniRank.valueOf(rankInRangeToReturn);
714 return getNamesAdvanced(family, genus, species, infraFamily, infraGenus, infraSpecies, authorAbbrev, includePublicationAuthors, includeBasionymAuthors, publicationTitle, isAPNIRecord, isGCIRecord, isIKRecord, ipniRank, sortByFamily, config, services);
715 }
716
717 public List<BotanicalName> getNamesAdvanced(String family, String genus, String species, String infraFamily,
718 String infraGenus, String infraSpecies, String authorAbbrev, Boolean includePublicationAuthors,
719 Boolean includeBasionymAuthors,
720 String publicationTitle,
721 Boolean isAPNIRecord,
722 Boolean isGCIRecord,
723 Boolean isIKRecord,
724 IpniRank rankToReturn,
725 Boolean sortByFamily,
726 IpniServiceNamesConfigurator config,
727 ICdmApplicationConfiguration services) {
728
729 // find_rankToReturn=all&output_format=normal&find_sortByFamily=on&find_sortByFamily=off&query_type=by_query&back_page=plantsearch
730
731 //config
732 if (config == null){
733 config = new IpniServiceNamesConfigurator();
734 }
735
736
737 family = normalizeParameter(family);
738 genus = normalizeParameter(genus);
739 species = normalizeParameter(species);
740 infraFamily = normalizeParameter(infraFamily);
741 infraGenus = normalizeParameter(infraGenus);
742 infraSpecies = normalizeParameter(infraSpecies);
743 authorAbbrev = normalizeParameter(authorAbbrev);
744
745 publicationTitle = normalizeParameter(publicationTitle);
746
747 DelimitedFormat format = config.getFormat();
748
749 String request =
750 "find_family=" + family +
751 "&find_genus=" + genus +
752 "&find_species=" + species +
753 "&find_infrafamily=" + infraFamily +
754 "&find_infragenus=" + infraGenus +
755 "&find_infraspecies=" + infraSpecies +
756 "&find_authorAbbrev=" + authorAbbrev +
757 getBooleanParameter("&find_includePublicationAuthors=", includePublicationAuthors, "on", "off") +
758 getBooleanParameter("&find_includeBasionymAuthors=", includePublicationAuthors, "on", "off") +
759 getBooleanParameter("&find_find_isAPNIRecord=", includePublicationAuthors, "on", "false") +
760 getBooleanParameter("&find_isGCIRecord=", includePublicationAuthors, "on", "false") +
761 getBooleanParameter("&find_isIKRecord=", includePublicationAuthors, "on", "false") +
762
763
764 "&find_publicationTitle=" + publicationTitle +
765 "&output_format=" + format.parameter;
766
767 return (List)queryService(request, services, getServiceUrl(IIpniService.ADVANCED_NAME_SERVICE_URL), config, ServiceType.NAME);
768 }
769
770
771 private String getBooleanParameter(String urlParamString, Boolean booleanParameter, String trueString, String falseString) {
772 String result;
773 if (booleanParameter == null){
774 result = getBooleanParameter(urlParamString, true, trueString, falseString) + getBooleanParameter(urlParamString, false, trueString, falseString);
775 }else if (booleanParameter == true){
776 result = urlParamString + trueString;
777 }else {
778 result = urlParamString + falseString;
779 }
780 return result;
781 }
782
783
784 /* (non-Javadoc)
785 * @see eu.etaxonomy.cdm.ext.IIpniService#getNamesSimple(java.lang.String, eu.etaxonomy.cdm.ext.IIpniService.DelimitedFormat, eu.etaxonomy.cdm.api.application.ICdmApplicationConfiguration)
786 */
787 public List<BotanicalName> getNamesSimple(String wholeName, ICdmApplicationConfiguration services, IpniServiceNamesConfigurator config){
788 if (config == null){
789 config = new IpniServiceNamesConfigurator();
790 }
791
792
793 // query_type=by_query&back_page=query_ipni.html
794
795 wholeName = normalizeParameter(wholeName);
796
797 DelimitedFormat format = config.getFormat();
798
799 String request = "find_wholeName=" + wholeName +
800 "&output_format=" + format.parameter;
801
802 return (List)queryService(request, services, getServiceUrl(IIpniService.SIMPLE_NAME_SERVICE_URL), config, ServiceType.NAME);
803 }
804
805 /* (non-Javadoc)
806 * @see eu.etaxonomy.cdm.ext.IIpniService#getPublications(java.lang.String, java.lang.String, boolean, eu.etaxonomy.cdm.api.application.ICdmApplicationConfiguration)
807 */
808 public List<ReferenceBase> getPublications(String title, String abbreviation, ICdmApplicationConfiguration services, IpniServicePublicationConfigurator config){
809 // http://www.uk.ipni.org/ipni/advPublicationSearch.do?find_title=Spe*plant*&find_abbreviation=&output_format=normal&query_type=by_query&back_page=publicationsearch
810 // http://www.uk.ipni.org/ipni/advPublicationSearch.do?find_title=*Hortus+Britannicus*&find_abbreviation=&output_format=delimited-classic&output_format=delimited
811
812 if (config == null){
813 config = new IpniServicePublicationConfigurator();
814 }
815
816 title = normalizeParameter(title);
817 abbreviation = normalizeParameter(abbreviation);
818
819 String request = "find_title=" + title +
820 "&find_abbreviation=" + abbreviation +
821 "&output_format=" + DelimitedFormat.CLASSIC.parameter;
822
823 List<ReferenceBase> result = (List)queryService(request, services, getServiceUrl(IIpniService.PUBLICATION_SERVICE_URL), config, ServiceType.PUBLICATION);
824 return result;
825 }
826
827
828
829 /**
830 * @return
831 */
832 private DelimitedFormat getDefaultFormat() {
833 return DelimitedFormat.SHORT;
834 }
835
836
837 /**
838 * The service url
839 *
840 * @return the serviceUrl
841 */
842 public URL getServiceUrl(String url) {
843 URL serviceUrl;
844 try {
845 serviceUrl = new URL(url);
846 } catch (MalformedURLException e) {
847 throw new RuntimeException("This should not happen", e);
848 }
849 return serviceUrl;
850 }
851
852
853
854 }