Project

General

Profile

Download (105 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
 * Copyright (C) 2007 EDIT
3
 * 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 1.1
7
 * See LICENSE.TXT at the top of this package for the full license terms.
8
 */
9

    
10
package eu.etaxonomy.cdm.io.specimen.abcd206.in;
11

    
12
import java.io.ByteArrayOutputStream;
13
import java.io.PrintStream;
14
import java.net.MalformedURLException;
15
import java.util.ArrayList;
16
import java.util.HashMap;
17
import java.util.HashSet;
18
import java.util.List;
19
import java.util.Map;
20
import java.util.Set;
21
import java.util.UUID;
22

    
23
import org.apache.commons.lang.StringUtils;
24
import org.apache.log4j.Logger;
25
import org.springframework.stereotype.Component;
26
import org.w3c.dom.Element;
27
import org.w3c.dom.NodeList;
28

    
29
import eu.etaxonomy.cdm.api.application.ICdmApplicationConfiguration;
30
import eu.etaxonomy.cdm.api.facade.DerivedUnitFacade;
31
import eu.etaxonomy.cdm.api.service.config.FindOccurrencesConfigurator;
32
import eu.etaxonomy.cdm.api.service.pager.Pager;
33
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
34
import eu.etaxonomy.cdm.io.specimen.SpecimenImportBase;
35
import eu.etaxonomy.cdm.io.specimen.SpecimenUserInteraction;
36
import eu.etaxonomy.cdm.io.specimen.UnitsGatheringArea;
37
import eu.etaxonomy.cdm.io.specimen.UnitsGatheringEvent;
38
import eu.etaxonomy.cdm.io.specimen.abcd206.in.molecular.AbcdDnaParser;
39
import eu.etaxonomy.cdm.model.agent.AgentBase;
40
import eu.etaxonomy.cdm.model.agent.Institution;
41
import eu.etaxonomy.cdm.model.agent.Person;
42
import eu.etaxonomy.cdm.model.agent.Team;
43
import eu.etaxonomy.cdm.model.common.CdmBase;
44
import eu.etaxonomy.cdm.model.common.DefinedTerm;
45
import eu.etaxonomy.cdm.model.common.DefinedTermBase;
46
import eu.etaxonomy.cdm.model.common.IdentifiableSource;
47
import eu.etaxonomy.cdm.model.common.Language;
48
import eu.etaxonomy.cdm.model.common.LanguageString;
49
import eu.etaxonomy.cdm.model.common.OriginalSourceBase;
50
import eu.etaxonomy.cdm.model.common.OriginalSourceType;
51
import eu.etaxonomy.cdm.model.description.DescriptionBase;
52
import eu.etaxonomy.cdm.model.description.DescriptionElementSource;
53
import eu.etaxonomy.cdm.model.description.Feature;
54
import eu.etaxonomy.cdm.model.description.IndividualsAssociation;
55
import eu.etaxonomy.cdm.model.description.TaxonDescription;
56
import eu.etaxonomy.cdm.model.location.NamedArea;
57
import eu.etaxonomy.cdm.model.media.Media;
58
import eu.etaxonomy.cdm.model.molecular.DnaSample;
59
import eu.etaxonomy.cdm.model.name.BacterialName;
60
import eu.etaxonomy.cdm.model.name.BotanicalName;
61
import eu.etaxonomy.cdm.model.name.CultivarPlantName;
62
import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
63
import eu.etaxonomy.cdm.model.name.NonViralName;
64
import eu.etaxonomy.cdm.model.name.Rank;
65
import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;
66
import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignationStatus;
67
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
68
import eu.etaxonomy.cdm.model.name.ZoologicalName;
69
import eu.etaxonomy.cdm.model.occurrence.Collection;
70
import eu.etaxonomy.cdm.model.occurrence.DerivationEvent;
71
import eu.etaxonomy.cdm.model.occurrence.DerivationEventType;
72
import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
73
import eu.etaxonomy.cdm.model.occurrence.DeterminationEvent;
74
import eu.etaxonomy.cdm.model.occurrence.FieldUnit;
75
import eu.etaxonomy.cdm.model.occurrence.GatheringEvent;
76
import eu.etaxonomy.cdm.model.occurrence.MediaSpecimen;
77
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
78
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationType;
79
import eu.etaxonomy.cdm.model.reference.Reference;
80
import eu.etaxonomy.cdm.model.reference.ReferenceFactory;
81
import eu.etaxonomy.cdm.model.taxon.Classification;
82
import eu.etaxonomy.cdm.model.taxon.Synonym;
83
import eu.etaxonomy.cdm.model.taxon.Taxon;
84
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
85
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
86
import eu.etaxonomy.cdm.persistence.dto.UuidAndTitleCache;
87
import eu.etaxonomy.cdm.persistence.query.MatchMode;
88
import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImpl;
89
import eu.etaxonomy.cdm.strategy.parser.ParserProblem;
90

    
91
/**
92
 * @author p.kelbert
93
 * @author pplitzner
94
 * @created 20.10.2008
95
 */
96
@Component
97
public class Abcd206Import extends SpecimenImportBase<Abcd206ImportConfigurator, Abcd206ImportState> {
98
    private static final Logger logger = Logger.getLogger(Abcd206Import.class);
99

    
100
    private final boolean DEBUG = true;
101

    
102
    private static final String COLON = ":";
103

    
104
    private Abcd206ImportReport report;
105

    
106

    
107
    public Abcd206Import() {
108
        super();
109
    }
110

    
111
    @Override
112
    protected boolean doCheck(Abcd206ImportState state) {
113
        logger.warn("Checking not yet implemented for " + this.getClass().getSimpleName());
114
        return true;
115
    }
116

    
117

    
118
    @Override
119
    @SuppressWarnings("rawtypes")
120
    public void doInvoke(Abcd206ImportState state) {
121
        report = new Abcd206ImportReport();
122
        try{
123
            state.setTx(startTransaction());
124
            logger.info("INVOKE Specimen Import from ABCD2.06 XML ");
125

    
126
            //init cd repository
127
            if(state.getCdmRepository()==null){
128
                state.setCdmRepository(this);
129
            }
130

    
131
            SpecimenUserInteraction sui = state.getConfig().getSpecimenUserInteraction();
132

    
133
            //init import reference
134
            List<Reference> references = getReferenceService().list(Reference.class, null, null, null, null);
135

    
136
            if (state.getConfig().isInteractWithUser()){
137
                Map<String,Reference> refMap = new HashMap<String, Reference>();
138
                for (Reference reference : references) {
139
                    if (! StringUtils.isBlank(reference.getTitleCache())) {
140
                        refMap.put(reference.getTitleCache(),reference);
141
                    }
142
                }
143
                state.setRef(sui.askForReference(refMap));
144

    
145
                if (state.getRef() == null){
146
                    String cla = sui.createNewReference();
147
                    if (refMap.get(cla)!= null) {
148
                        state.setRef(refMap.get(cla));
149
                    } else {
150
                        state.setRef(ReferenceFactory.newGeneric());
151
                        state.getRef().setTitle(cla);
152
                    }
153
                }
154
                else{
155
                    state.setRef(getReferenceService().find(state.getRef().getUuid()));
156
                }
157
            }else{
158
                if (state.getRef()==null){
159
                    String name = NB(state.getConfig().getSourceReferenceTitle());
160
                    for (Reference reference : references) {
161
                        if (! StringUtils.isBlank(reference.getTitleCache())) {
162
                            if (reference.getTitleCache().equalsIgnoreCase(name)) {
163
                                state.setRef(reference);
164
                            }
165
                        }
166
                    }
167
                    if (state.getRef() == null){
168
                        state.setRef(ReferenceFactory.newGeneric());
169
                        state.getRef().setTitle("ABCD classic");
170
                    }
171
                }
172
            }
173
            save(state.getRef(), state);
174
            state.getConfig().setSourceReference(state.getRef());
175

    
176
            if(state.getConfig().getClassificationUuid()!=null){
177
                //load classification from config if it exists
178
                state.setClassification(getClassificationService().load(state.getConfig().getClassificationUuid()));
179
            }
180
            if(state.getClassification()==null){//no existing classification was set in config
181
                List<Classification> classificationList = getClassificationService().list(Classification.class, null, null, null, null);
182
                //get classification via user interaction
183
                if (state.getConfig().isUseClassification() && state.getConfig().isInteractWithUser()){
184
                    Map<String,Classification> classMap = new HashMap<String, Classification>();
185
                    for (Classification tree : classificationList) {
186
                        if (! StringUtils.isBlank(tree.getTitleCache())) {
187
                            classMap.put(tree.getTitleCache(),tree);
188
                        }
189
                    }
190
                    state.setClassification(sui.askForClassification(classMap));
191
                    if (state.getClassification() == null){
192
                        String cla = sui.createNewClassification();
193
                        if (classMap.get(cla)!= null) {
194
                            state.setClassification(classMap.get(cla));
195
                        } else {
196
                            state.setClassification(Classification.NewInstance(cla, state.getRef(), Language.DEFAULT()));
197
                        }
198
                    }
199
                    save(state.getClassification(), state);
200
                }
201
                // use default classification as the classification to import into
202
                if (state.getClassification() == null) {
203
                    String name = NB(state.getConfig().getClassificationName());
204
                    for (Classification classif : classificationList){
205
                        if (classif.getTitleCache() != null && classif.getCitation() != null
206
                                && classif.getTitleCache().equalsIgnoreCase(name) && classif.getCitation().equals(state.getRef())) {
207
                            state.setClassification(classif);
208
                        }
209
                    }
210
                    if (state.getClassification() == null){
211
                        state.setClassification(Classification.NewInstance(name, state.getRef(), Language.DEFAULT()));
212
                        //we do not need a default classification when creating an empty new one
213
                        state.setDefaultClassification(state.getClassification());
214
                        save(state.getDefaultClassification(), state);
215
                    }
216
                    save(state.getClassification(), state);
217
                }
218
            }
219

    
220
            UnitAssociationWrapper unitAssociationWrapper = AbcdParseUtility.parseUnitsNodeList(state.getConfig().getSource(), report);
221
            NodeList unitsList = unitAssociationWrapper.getAssociatedUnits();
222
            state.setPrefix(unitAssociationWrapper.getPrefix());
223

    
224
            if (unitsList != null) {
225
                String message = "nb units to insert: " + unitsList.getLength();
226
                logger.info(message);
227
                state.getConfig().getProgressMonitor().beginTask("Importing ABCD file", unitsList.getLength() + 2);
228
                updateProgress(state, message);
229

    
230
                state.setDataHolder(new Abcd206DataHolder());
231
                state.getDataHolder().reset();
232

    
233
                Abcd206XMLFieldGetter abcdFieldGetter = new Abcd206XMLFieldGetter(state.getDataHolder(), state.getPrefix());
234

    
235
                prepareCollectors(state, unitsList, abcdFieldGetter);
236

    
237
                state.setAssociationRefs(new ArrayList<OriginalSourceBase<?>>());
238
                state.setDescriptionRefs(new ArrayList<OriginalSourceBase<?>>());
239
                state.setDerivedUnitSources(new ArrayList<OriginalSourceBase<?>>());
240

    
241
                for (int i = 0; i < unitsList.getLength(); i++) {
242
                    if(state.getConfig().getProgressMonitor().isCanceled()){
243
                        break;
244
                    }
245

    
246
                    state.reset();
247

    
248
                    Element item = (Element) unitsList.item(i);
249
                    this.setUnitPropertiesXML( item, abcdFieldGetter, state);
250
                    updateProgress(state, "Importing data for unit "+state.getDataHolder().unitID+" ("+i+"/"+unitsList.getLength()+")");
251

    
252
                    //import unit + field unit data
253
                    this.handleSingleUnit(state, item);
254

    
255
                }
256
                if(state.getConfig().isDeduplicateReferences()){
257
                    getReferenceService().deduplicate(Reference.class, null, null);
258
                }
259
                if(state.getConfig().isDeduplicateClassifications()){
260
                    getClassificationService().deduplicate(Classification.class, null, null);
261
                }
262
            }
263
            commitTransaction(state.getTx());
264
        }
265
        catch(Exception e){
266
            String errorDuringImport = "Exception during import!";
267
            logger.error(errorDuringImport, e);
268
            report.addException(errorDuringImport, e);
269
        }
270
        finally{
271
            report.printReport(state.getConfig().getReportUri());
272
        }
273
        return;
274
    }
275

    
276
    /**
277
     * Handle a single unit
278
     * @param state
279
     * @param item
280
     */
281
    @SuppressWarnings("rawtypes")
282
    private void handleSingleUnit(Abcd206ImportState state, Element item) {
283
        if (DEBUG) {
284
            logger.info("handleSingleUnit "+state.getRef());
285
        }
286
        try {
287
            ICdmApplicationConfiguration cdmAppController = state.getConfig().getCdmAppController();
288
            if(cdmAppController==null){
289
                cdmAppController = this;
290
            }
291
            //check if unit already exists
292
            DerivedUnitFacade derivedUnitFacade = null;
293
            if(state.getConfig().isIgnoreImportOfExistingSpecimens()){
294
                SpecimenOrObservationBase<?> existingSpecimen = findExistingSpecimen(state.getDataHolder().unitID, state);
295
                if(existingSpecimen!=null && existingSpecimen.isInstanceOf(DerivedUnit.class)){
296
                    DerivedUnit derivedUnit = HibernateProxyHelper.deproxy(existingSpecimen, DerivedUnit.class);
297
                    state.setDerivedUnitBase(derivedUnit);
298
                    derivedUnitFacade = DerivedUnitFacade.NewInstance(state.getDerivedUnitBase());
299
                    importAssociatedUnits(state, item, derivedUnitFacade);
300
                    report.addAlreadyExistingSpecimen(AbcdImportUtility.getUnitID(derivedUnit, state.getConfig()), derivedUnit);
301
                    return;
302
                }
303
            }
304
            // TODO: implement overwrite/merge specimen
305
//            else if(state.getConfig().isOverwriteExistingSpecimens()){
306
//                Pager<SpecimenOrObservationBase> existingSpecimens = cdmAppController.getOccurrenceService().findByTitle(config);
307
//                if(!existingSpecimens.getRecords().isEmpty()){
308
//                    derivedUnitFacade = DerivedUnitFacade.NewInstance(derivedUnit);
309
//                    derivedUnitBase = derivedUnitFacade.innerDerivedUnit();
310
//                    fieldUnit = derivedUnitFacade.getFieldUnit(true);
311
//                }
312
//            }
313
            //import new specimen
314

    
315
            // import DNA unit
316
            if(state.getDataHolder().kindOfUnit!=null && state.getDataHolder().kindOfUnit.equalsIgnoreCase("dna")){
317
                AbcdDnaParser dnaParser = new AbcdDnaParser(state.getPrefix(), report, state.getCdmRepository());
318
                DnaSample dnaSample = dnaParser.parse(item, state);
319
                save(dnaSample, state);
320
                //set dna as derived unit to avoid creating an extra specimen for this dna sample (instead just the field unit will be created)
321
                state.setDerivedUnitBase(dnaSample);
322
                derivedUnitFacade = DerivedUnitFacade.NewInstance(state.getDerivedUnitBase());
323
            }
324
            else{
325
                // create facade
326
                derivedUnitFacade = getFacade(state);
327
                state.setDerivedUnitBase(derivedUnitFacade.innerDerivedUnit());
328
            }
329

    
330
            /**
331
             * GATHERING EVENT
332
             */
333
            // gathering event
334
            UnitsGatheringEvent unitsGatheringEvent = new UnitsGatheringEvent(cdmAppController.getTermService(),
335
                    state.getDataHolder().locality, state.getDataHolder().languageIso, state.getDataHolder().longitude, state.getDataHolder().latitude,
336
                    state.getDataHolder().gatheringElevationText, state.getDataHolder().gatheringElevationMin,
337
                    state.getDataHolder().gatheringElevationMax, state.getDataHolder().gatheringElevationUnit, state.getDataHolder().gatheringDateText,
338
                    state.getDataHolder().gatheringAgentList, state.getDataHolder().gatheringTeamList, state.getConfig());
339

    
340
            // country
341
            UnitsGatheringArea unitsGatheringArea = new UnitsGatheringArea();
342
            //  unitsGatheringArea.setConfig(state.getConfig(),getOccurrenceService(), getTermService());
343
            unitsGatheringArea.setParams(state.getDataHolder().isocountry, state.getDataHolder().country, state.getConfig(), cdmAppController.getTermService(), cdmAppController.getOccurrenceService());
344

    
345
            DefinedTermBase<?> areaCountry =  unitsGatheringArea.getCountry();
346

    
347
            // other areas
348
            unitsGatheringArea = new UnitsGatheringArea();
349
            //            unitsGatheringArea.setConfig(state.getConfig(),getOccurrenceService(),getTermService());
350
            unitsGatheringArea.setAreas(state.getDataHolder().namedAreaList,state.getConfig(), cdmAppController.getTermService(), cdmAppController.getVocabularyService());
351
            ArrayList<DefinedTermBase> nas = unitsGatheringArea.getAreas();
352
            for (DefinedTermBase namedArea : nas) {
353
                unitsGatheringEvent.addArea(namedArea);
354
            }
355

    
356
            // copy gathering event to facade
357
            GatheringEvent gatheringEvent = unitsGatheringEvent.getGatheringEvent();
358
            derivedUnitFacade.setLocality(gatheringEvent.getLocality());
359
            derivedUnitFacade.setExactLocation(gatheringEvent.getExactLocation());
360
            derivedUnitFacade.setCollector(gatheringEvent.getCollector());
361
            derivedUnitFacade.setCountry((NamedArea)areaCountry);
362
            derivedUnitFacade.setAbsoluteElevationText(gatheringEvent.getAbsoluteElevationText());
363
            derivedUnitFacade.setAbsoluteElevation(gatheringEvent.getAbsoluteElevation());
364
            derivedUnitFacade.setAbsoluteElevationMax(gatheringEvent.getAbsoluteElevationMax());
365
            derivedUnitFacade.setGatheringPeriod(gatheringEvent.getTimeperiod());
366

    
367
            for(DefinedTermBase<?> area:unitsGatheringArea.getAreas()){
368
                derivedUnitFacade.addCollectingArea((NamedArea) area);
369
            }
370
            //            derivedUnitFacade.addCollectingAreas(unitsGatheringArea.getAreas());
371
            // TODO exsiccatum
372

    
373
            // add fieldNumber
374
            derivedUnitFacade.setFieldNumber(NB(state.getDataHolder().fieldNumber));
375

    
376
            // //add Multimedia URLs
377
            if (state.getDataHolder().multimediaObjects.size() != -1) {
378
                for (String multimediaObject : state.getDataHolder().multimediaObjects) {
379
                    Media media;
380
                    try {
381
                        media = getImageMedia(multimediaObject, READ_MEDIA_DATA);
382
                        derivedUnitFacade.addDerivedUnitMedia(media);
383
                        if(state.getConfig().isAddMediaAsMediaSpecimen()){
384
                            //add media also as specimen scan
385
                            MediaSpecimen mediaSpecimen = MediaSpecimen.NewInstance(SpecimenOrObservationType.Media);
386
                            mediaSpecimen.setMediaSpecimen(media);
387
                            DefinedTermBase specimenScanTerm = getTermService().load(UUID.fromString("acda15be-c0e2-4ea8-8783-b9b0c4ad7f03"));
388
                            if(specimenScanTerm instanceof DefinedTerm){
389
                                mediaSpecimen.setKindOfUnit((DefinedTerm) specimenScanTerm);
390
                            }
391
                            DerivationEvent derivationEvent = DerivationEvent.NewInstance(DerivationEventType.PREPARATION());
392
                            derivationEvent.addDerivative(mediaSpecimen);
393
                            derivedUnitFacade.innerDerivedUnit().addDerivationEvent(derivationEvent);
394
                        }
395

    
396
                    } catch (MalformedURLException e) {
397
                        // TODO Auto-generated catch block
398
                        e.printStackTrace();
399
                    }
400

    
401
                }
402
            }
403

    
404
            //			/*
405
            //			 * merge AND STORE DATA
406
            //			 */
407
            //			getTermService().saveOrUpdate(areaCountry);// TODO save area sooner
408
            //
409
            //			for (NamedArea area : otherAreas) {
410
            //				getTermService().saveOrUpdate(area);// merge it sooner (foreach area)
411
            //			}
412

    
413
            save(unitsGatheringEvent.getLocality(), state);
414

    
415
            // handle collection data
416
            setCollectionData(state, derivedUnitFacade);
417

    
418
            //Reference stuff
419
            SpecimenUserInteraction sui = state.getConfig().getSpecimenUserInteraction();
420
            Map<String,OriginalSourceBase<?>> sourceMap = new HashMap<String, OriginalSourceBase<?>>();
421

    
422
            state.getDataHolder().docSources = new ArrayList<String>();
423
            for (String[] fullReference : state.getDataHolder().referenceList) {
424
                String strReference=fullReference[0];
425
                String citationDetail = fullReference[1];
426
                String citationURL = fullReference[2];
427

    
428
                if (!citationURL.isEmpty()) {
429
                    citationDetail+=", "+citationURL;
430
                }
431

    
432
                Reference<?> reference;
433
                if(strReference.equals(state.getRef().getTitleCache())){
434
                    reference = state.getRef();
435
                }
436
                else{
437
                    reference = ReferenceFactory.newGeneric();
438
                    reference.setTitle(strReference);
439
                }
440

    
441
                IdentifiableSource sour = getIdentifiableSource(reference,citationDetail);
442

    
443
                try{
444
                    if (sour.getCitation() != null){
445
                        if(StringUtils.isNotBlank(sour.getCitationMicroReference())) {
446
                            state.getDataHolder().docSources.add(sour.getCitation().getTitleCache()+ "---"+sour.getCitationMicroReference());
447
                        } else {
448
                            state.getDataHolder().docSources.add(sour.getCitation().getTitleCache());
449
                        }
450
                    }
451
                }catch(Exception e){
452
                    logger.warn("oups");
453
                }
454
                reference.addSource(sour);
455
                save(reference, state);
456
            }
457

    
458
            List<IdentifiableSource> issTmp = getCommonService().list(IdentifiableSource.class, null, null, null, null);
459
            List<DescriptionElementSource> issTmp2 = getCommonService().list(DescriptionElementSource.class, null, null, null, null);
460

    
461
            Set<OriginalSourceBase> osbSet = new HashSet<OriginalSourceBase>();
462
            if(issTmp2!=null) {
463
                osbSet.addAll(issTmp2);
464
            }
465
            if(issTmp!=null) {
466
                osbSet.addAll(issTmp);
467
            }
468

    
469
            addToSourceMap(sourceMap, osbSet);
470

    
471
            if( state.getConfig().isInteractWithUser()){
472
                List<OriginalSourceBase<?>>sources=null;
473
                if(!state.isDerivedUnitSourcesSet()){
474
                    sources= sui.askForSource(sourceMap, "the unit itself","",getReferenceService(), state.getDataHolder().docSources);
475
                    state.setDerivedUnitSources(sources);
476
                    state.setDerivedUnitSourcesSet(true);
477
                }
478
                else{
479
                    sources=state.getDerivedUnitSources();
480
                }
481
//                System.out.println("nb sources: "+sources.size());
482
//                System.out.println("derivedunitfacade : "+derivedUnitFacade.getTitleCache());
483
                for (OriginalSourceBase<?> sour:sources){
484
                    if(sour.isInstanceOf(IdentifiableSource.class)){
485
                        if(sourceNotLinkedToElement(derivedUnitFacade,sour)) {
486
//                            System.out.println("add source to derivedunitfacade1 "+derivedUnitFacade.getTitleCache());
487
                            derivedUnitFacade.addSource((IdentifiableSource)sour.clone());
488
                        }
489
                    }else{
490
                        if(sourceNotLinkedToElement(derivedUnitFacade,sour)) {
491
//                            System.out.println("add source to derivedunitfacade2 "+derivedUnitFacade.getTitleCache());
492
                            derivedUnitFacade.addSource(OriginalSourceType.Import,sour.getCitation(),sour.getCitationMicroReference(), ioName);
493
                        }
494
                    }
495
                }
496
            }else{
497
                for (OriginalSourceBase<?> sr : sourceMap.values()){
498
                    if(sr.isInstanceOf(IdentifiableSource.class)){
499
                        if(sourceNotLinkedToElement(derivedUnitFacade,sr)) {
500
//                            System.out.println("add source to derivedunitfacade3 "+derivedUnitFacade.getTitleCache());
501
                            derivedUnitFacade.addSource((IdentifiableSource)sr.clone());
502
                        }
503
                    }else{
504
                        if(sourceNotLinkedToElement(derivedUnitFacade,sr)) {
505
//                            System.out.println("add source to derivedunitfacade4 "+derivedUnitFacade.getTitleCache());
506
                            derivedUnitFacade.addSource(OriginalSourceType.Import,sr.getCitation(),sr.getCitationMicroReference(), ioName);
507
                        }
508
                    }
509
                }
510
            }
511

    
512
            save(state.getDerivedUnitBase(), state);
513

    
514
            if(DEBUG) {
515
                logger.info("saved ABCD specimen ...");
516
            }
517

    
518
            // handle identifications
519
            handleIdentifications(state, derivedUnitFacade);
520

    
521
            //associatedUnits
522
            importAssociatedUnits(state, item, derivedUnitFacade);
523

    
524

    
525

    
526
        } catch (Exception e) {
527
            String message = "Error when reading record!";
528
            logger.warn(message);
529
            report.addException(message, e);
530
            e.printStackTrace();
531
            state.setUnsuccessfull();
532
        }
533

    
534
        return;
535
    }
536

    
537
    private void importAssociatedUnits(Abcd206ImportState state, Element item, DerivedUnitFacade derivedUnitFacade) {
538
        //import associated units
539
        FieldUnit currentFieldUnit = derivedUnitFacade.innerFieldUnit();
540
        //TODO: push state (think of implementing stack architecture for state
541
        DerivedUnit currentUnit = state.getDerivedUnitBase();
542
        DerivationEvent currentDerivedFrom = currentUnit.getDerivedFrom();
543
        String currentPrefix = state.getPrefix();
544
        NodeList unitAssociationList = item.getElementsByTagName(currentPrefix+"UnitAssociation");
545
        for(int k=0;k<unitAssociationList.getLength();k++){
546
            if(unitAssociationList.item(k) instanceof Element){
547
                Element unitAssociation = (Element)unitAssociationList.item(k);
548
                UnitAssociationParser unitAssociationParser = new UnitAssociationParser(currentPrefix, report, state.getCdmRepository());
549
                UnitAssociationWrapper associationWrapper = unitAssociationParser.parse(unitAssociation);
550
                if(associationWrapper!=null){
551
                    NodeList associatedUnits = associationWrapper.getAssociatedUnits();
552
                    for(int m=0;m<associatedUnits.getLength();m++){
553
                        if(associatedUnits.item(m) instanceof Element){
554
                            state.reset();
555
                            state.setPrefix(associationWrapper.getPrefix());
556
                            this.setUnitPropertiesXML((Element) associatedUnits.item(m), new Abcd206XMLFieldGetter(state.getDataHolder(), state.getPrefix()), state);
557
                            handleSingleUnit(state, (Element) associatedUnits.item(m));
558

    
559
                            DerivedUnit associatedUnit = state.getDerivedUnitBase();
560
                            FieldUnit associatedFieldUnit = null;
561
                            java.util.Collection<FieldUnit> associatedFieldUnits = state.getCdmRepository().getOccurrenceService().getFieldUnits(associatedUnit.getUuid());
562
                            //ignore field unit if associated unit has more than one
563
                            if(associatedFieldUnits.size()>1){
564
                                report.addInfoMessage(String.format("%s has more than one field unit.", associatedUnit));
565
                            }
566
                            else if(associatedFieldUnits.size()==1){
567
                                associatedFieldUnit = associatedFieldUnits.iterator().next();
568
                            }
569

    
570
                            //attach current unit and associated unit depending on association type
571

    
572
                            //parent-child relation:
573
                            //copy derivation event and connect parent and sub derivative
574
                            if(associationWrapper.getAssociationType().contains("individual")){
575
                                if(currentDerivedFrom==null){
576
                                    report.addInfoMessage(String.format("No derivation event found for unit %s. Defaulting to ACCESSIONING event.",AbcdImportUtility.getUnitID(currentUnit, state.getConfig())));
577
                                    DerivationEvent.NewSimpleInstance(associatedUnit, currentUnit, DerivationEventType.ACCESSIONING());
578
                                }
579
                                else{
580
                                    DerivationEvent updatedDerivationEvent = DerivationEvent.NewSimpleInstance(associatedUnit, currentUnit, currentDerivedFrom.getType());
581
                                    updatedDerivationEvent.setActor(currentDerivedFrom.getActor());
582
                                    updatedDerivationEvent.setDescription(currentDerivedFrom.getDescription());
583
                                    updatedDerivationEvent.setInstitution(currentDerivedFrom.getInstitution());
584
                                    updatedDerivationEvent.setTimeperiod(currentDerivedFrom.getTimeperiod());
585
                                }
586
                                report.addDerivate(associatedUnit, currentUnit, state.getConfig());
587
                            }
588
                            //siblings relation
589
                            //connect current unit to field unit of associated unit
590
                            else if(associationWrapper.getAssociationType().contains("population")){
591
                                //no associated field unit -> using current one
592
                                if(associatedFieldUnit==null){
593
                                    if(currentFieldUnit!=null){
594
                                        DerivationEvent.NewSimpleInstance(currentFieldUnit, associatedUnit, DerivationEventType.ACCESSIONING());
595
                                    }
596
                                }
597
                                else{
598
                                    if(currentDerivedFrom==null){
599
                                        report.addInfoMessage("No derivation event found for unit "+AbcdImportUtility.getUnitID(currentUnit, state.getConfig())+". Defaulting to ACCESIONING event.");
600
                                        DerivationEvent.NewSimpleInstance(associatedFieldUnit, currentUnit, DerivationEventType.ACCESSIONING());
601
                                    }
602
                                    if(currentDerivedFrom!=null && associatedFieldUnit!=currentFieldUnit){
603
                                        DerivationEvent updatedDerivationEvent = DerivationEvent.NewSimpleInstance(associatedFieldUnit, currentUnit, currentDerivedFrom.getType());
604
                                        updatedDerivationEvent.setActor(currentDerivedFrom.getActor());
605
                                        updatedDerivationEvent.setDescription(currentDerivedFrom.getDescription());
606
                                        updatedDerivationEvent.setInstitution(currentDerivedFrom.getInstitution());
607
                                        updatedDerivationEvent.setTimeperiod(currentDerivedFrom.getTimeperiod());
608
                                    }
609
                                }
610
                            }
611

    
612
                            //delete current field unit if replaced
613
                            if(currentFieldUnit!=null && currentDerivedFrom!=null
614
                                    && currentFieldUnit.getDerivationEvents().size()==1  && currentFieldUnit.getDerivationEvents().contains(currentDerivedFrom) //making sure that the field unit
615
                                    && currentDerivedFrom.getDerivatives().size()==1 && currentDerivedFrom.getDerivatives().contains(currentUnit) //is not attached to other derived units
616
                                    && currentDerivedFrom!=currentUnit.getDerivedFrom() // <- derivation has been replaced and can be deleted
617
                                    ){
618
                                currentFieldUnit.removeDerivationEvent(currentDerivedFrom);
619
                                state.getCdmRepository().getOccurrenceService().delete(currentFieldUnit);
620
                            }
621

    
622
                            save(associatedUnit, state);
623
                        }
624
                    }
625
                }
626
            }
627
        }
628
        //TODO: pop state
629
        state.reset();
630
        state.setDerivedUnitBase(currentUnit);
631
        state.setPrefix(currentPrefix);
632
    }
633

    
634
    private SpecimenOrObservationBase findExistingSpecimen(String unitId, Abcd206ImportState state){
635
        ICdmApplicationConfiguration cdmAppController = state.getConfig().getCdmAppController();
636
        if(cdmAppController==null){
637
            cdmAppController = this;
638
        }
639
        FindOccurrencesConfigurator config = new FindOccurrencesConfigurator();
640
        config.setSignificantIdentifier(unitId);
641
        Pager<SpecimenOrObservationBase> existingSpecimens = cdmAppController.getOccurrenceService().findByTitle(config);
642
        if(!existingSpecimens.getRecords().isEmpty()){
643
            if(existingSpecimens.getRecords().size()==1){
644
                return existingSpecimens.getRecords().iterator().next();
645
            }
646
        }
647
        return null;
648
    }
649

    
650
    /**
651
     * @param sourceMap
652
     * @param osbSet
653
     */
654
    private void addToSourceMap(Map<String, OriginalSourceBase<?>> sourceMap, Set<OriginalSourceBase> osbSet) {
655
        for( OriginalSourceBase<?> osb:osbSet) {
656
            if(osb.getCitation()!=null && osb.getCitationMicroReference() !=null  && !osb.getCitationMicroReference().isEmpty()) {
657
                try{
658
                    sourceMap.put(osb.getCitation().getTitleCache()+ "---"+osb.getCitationMicroReference(),osb);
659
                }catch(NullPointerException e){logger.warn("null pointer problem (no ref?) with "+osb);}
660
            } else if(osb.getCitation()!=null){
661
                try{
662
                    sourceMap.put(osb.getCitation().getTitleCache(),osb);
663
                }catch(NullPointerException e){logger.warn("null pointer problem (no ref?) with "+osb);}
664
            }
665
        }
666
    }
667

    
668
    /**
669
     * @param derivedUnitFacade
670
     * @param sour
671
     * @return
672
     */
673
    private boolean sourceNotLinkedToElement(DerivedUnitFacade derivedUnitFacade, OriginalSourceBase<?> source) {
674
        Set<IdentifiableSource> linkedSources = derivedUnitFacade.getSources();
675
        for (IdentifiableSource is:linkedSources){
676
            if (is.getCitation()!=null && source.getCitation()!=null &&
677
                    is.getCitation().getTitleCache().equalsIgnoreCase(source.getCitation().getTitleCache())){
678
                String isDetail =  is.getCitationMicroReference();
679
                if ((StringUtils.isBlank(isDetail) && StringUtils.isBlank(source.getCitationMicroReference()))
680
                        || (isDetail != null && isDetail.equalsIgnoreCase(source.getCitationMicroReference())) ) {
681
                    return false;
682
                }
683
            }
684
        }
685
        return true;
686
    }
687

    
688
    /**
689
     * @param reference
690
     * @param citationDetail
691
     * @return
692
     */
693
    //FIXME this method is highly critical, because
694
    //  * it will have serious performance and memory problems with large databases
695
    //        (databases may easily have >1 Mio source records)
696
    //  * it does not make sense to search for existing sources and then clone them
697
    //    we need to search for existing references instead and use them (if exist)
698
    //    for our new source.
699
    private IdentifiableSource getIdentifiableSource(Reference<?> reference, String citationDetail) {
700

    
701
        List<IdentifiableSource> issTmp = getCommonService().list(IdentifiableSource.class, null, null, null, null);
702

    
703

    
704
        if (reference != null){
705
            try {
706
                for (OriginalSourceBase<?> osb: issTmp){
707
                    if (osb.getCitation() != null && osb.getCitation().getTitleCache().equalsIgnoreCase(reference.getTitleCache())){
708
                        String osbDetail = osb.getCitationMicroReference();
709
                        if ((StringUtils.isBlank(osbDetail) && StringUtils.isBlank(citationDetail))
710
                                || (osbDetail != null && osbDetail.equalsIgnoreCase(citationDetail)) ) {
711
//                            System.out.println("REFERENCE FOUND RETURN EXISTING SOURCE");
712
                            return (IdentifiableSource) osb.clone();
713
                        }
714
                    }
715
                }
716
            } catch (CloneNotSupportedException e) {
717
                throw new RuntimeException(e);
718
            } catch (Exception e1){
719
                e1.printStackTrace();
720
            }
721
        }
722

    
723
        IdentifiableSource sour = IdentifiableSource.NewInstance(OriginalSourceType.Import,null,null, reference,citationDetail);
724
        return sour;
725
    }
726

    
727
    //    /**
728
    //     * @param reference
729
    //     * @param citationDetail
730
    //     * @return
731
    //     */
732
    //    private DescriptionElementSource getDescriptionSource(Reference<?> reference, String citationDetail) {
733
    //
734
    //        List<OriginalSourceBase> issTmp2 = getCommonService().list(DescriptionElementSource.class, null, null, null, null);
735
    //
736
    //        try {
737
    //            for (OriginalSourceBase<?> osb:issTmp2){
738
    //                if (osb.getCitation().equals(reference) && osb.getCitationMicroReference().equalsIgnoreCase(citationDetail)) {
739
    //                    return (DescriptionElementSource) osb.clone();
740
    //                }
741
    //            }
742
    //        } catch (CloneNotSupportedException e) {
743
    //            // TODO Auto-generated catch block
744
    //            e.printStackTrace();
745
    //        }
746
    //
747
    //        DescriptionElementSource sour = DescriptionElementSource.NewInstance(OriginalSourceType.Import,null,null, reference,citationDetail);
748
    //        return sour;
749
    //    }
750

    
751

    
752
    /**
753
     * Very fast and dirty implementation to allow handling of transient objects as described in
754
     * https://dev.e-taxonomy.eu/trac/ticket/3726
755
     *
756
     * Not yet complete.
757
     *
758
     * @param cdmBase
759
     * @param state
760
     */
761
    private void save(CdmBase cdmBase, Abcd206ImportState state) {
762
        ICdmApplicationConfiguration cdmRepository = state.getConfig().getCdmAppController();
763
        if (cdmRepository == null){
764
            cdmRepository = this;
765
        }
766

    
767
        if (cdmBase.isInstanceOf(LanguageString.class)){
768
            cdmRepository.getTermService().saveLanguageData(CdmBase.deproxy(cdmBase, LanguageString.class));
769
        }else if (cdmBase.isInstanceOf(SpecimenOrObservationBase.class)){
770
            cdmRepository.getOccurrenceService().saveOrUpdate(CdmBase.deproxy(cdmBase, SpecimenOrObservationBase.class));
771
        }else if (cdmBase.isInstanceOf(Reference.class)){
772
            cdmRepository.getReferenceService().saveOrUpdate(CdmBase.deproxy(cdmBase, Reference.class));
773
        }else if (cdmBase.isInstanceOf(Classification.class)){
774
            cdmRepository.getClassificationService().saveOrUpdate(CdmBase.deproxy(cdmBase, Classification.class));
775
        }else if (cdmBase.isInstanceOf(AgentBase.class)){
776
            cdmRepository.getAgentService().saveOrUpdate(CdmBase.deproxy(cdmBase, AgentBase.class));
777
        }else if (cdmBase.isInstanceOf(Collection.class)){
778
            cdmRepository.getCollectionService().saveOrUpdate(CdmBase.deproxy(cdmBase, Collection.class));
779
        }else if (cdmBase.isInstanceOf(DescriptionBase.class)){
780
            cdmRepository.getDescriptionService().saveOrUpdate(CdmBase.deproxy(cdmBase, DescriptionBase.class));
781
        }else if (cdmBase.isInstanceOf(TaxonBase.class)){
782
            cdmRepository.getTaxonService().saveOrUpdate(CdmBase.deproxy(cdmBase, TaxonBase.class));
783
        }else if (cdmBase.isInstanceOf(TaxonNameBase.class)){
784
            cdmRepository.getNameService().saveOrUpdate(CdmBase.deproxy(cdmBase, TaxonNameBase.class));
785
        }else{
786
            throw new IllegalArgumentException("Class not supported in save method: " + CdmBase.deproxy(cdmBase, CdmBase.class).getClass().getSimpleName());
787
        }
788

    
789
    }
790

    
791
    /**
792
     * setCollectionData : store the collection object into the
793
     * derivedUnitFacade
794
     *
795
     * @param state
796
     */
797
    private void setCollectionData(Abcd206ImportState state, DerivedUnitFacade derivedUnitFacade) {
798
        Abcd206ImportConfigurator config = state.getConfig();
799
        AbcdImportUtility.setUnitID(derivedUnitFacade.innerDerivedUnit(), state.getDataHolder().unitID, config);
800
        if(!config.isMapUnitIdToAccessionNumber()){
801
            derivedUnitFacade.setAccessionNumber(NB(state.getDataHolder().accessionNumber));
802
        }
803
        // derivedUnitFacade.setCollectorsNumber(NB(state.getDataHolder().collectorsNumber));
804

    
805
        /*
806
         * INSTITUTION & COLLECTION
807
         */
808
        // manage institution
809
        Institution institution = this.getInstitution(NB(state.getDataHolder().institutionCode), state);
810
        // manage collection
811
        Collection collection = this.getCollection(institution, NB(state.getDataHolder().collectionCode), state);
812
        // link specimen & collection
813
        derivedUnitFacade.setCollection(collection);
814
    }
815

    
816
    /**
817
     * getFacade : get the DerivedUnitFacade based on the recordBasis
818
     * @param state
819
     *
820
     * @return DerivedUnitFacade
821
     */
822
    private DerivedUnitFacade getFacade(Abcd206ImportState state) {
823
        if(DEBUG) {
824
            logger.info("getFacade()");
825
        }
826
        SpecimenOrObservationType type = null;
827

    
828
        // create specimen
829
        if (NB((state.getDataHolder().recordBasis)) != null) {
830
            if (state.getDataHolder().recordBasis.toLowerCase().startsWith("s") || state.getDataHolder().recordBasis.toLowerCase().indexOf("specimen")>-1) {// specimen
831
                type = SpecimenOrObservationType.PreservedSpecimen;
832
            }
833
            if (state.getDataHolder().recordBasis.toLowerCase().startsWith("o") ||state.getDataHolder().recordBasis.toLowerCase().indexOf("observation")>-1 ) {
834
                type = SpecimenOrObservationType.Observation;
835
            }
836
            if (state.getDataHolder().recordBasis.toLowerCase().indexOf("fossil")>-1){
837
                type = SpecimenOrObservationType.Fossil;
838
            }
839
            if (state.getDataHolder().recordBasis.toLowerCase().indexOf("living")>-1) {
840
                type = SpecimenOrObservationType.LivingSpecimen;
841
            }
842
            if (type == null) {
843
                logger.info("The basis of record does not seem to be known: " + state.getDataHolder().recordBasis);
844
                type = SpecimenOrObservationType.DerivedUnit;
845
            }
846
            // TODO fossils?
847
        } else {
848
            logger.info("The basis of record is null");
849
            type = SpecimenOrObservationType.DerivedUnit;
850
        }
851
        DerivedUnitFacade derivedUnitFacade = DerivedUnitFacade.NewInstance(type);
852
        return derivedUnitFacade;
853
    }
854

    
855
    private void getCollectorsFromXML(Element root, Abcd206XMLFieldGetter abcdFieldGetter, Abcd206ImportState state) {
856
        NodeList group;
857

    
858
        group = root.getChildNodes();
859
        for (int i = 0; i < group.getLength(); i++) {
860
            if (group.item(i).getNodeName().equals(state.getPrefix() + "Identifications")) {
861
                group = group.item(i).getChildNodes();
862
                break;
863
            }
864
        }
865
        state.getDataHolder().gatheringAgentList = new ArrayList<String>();
866
        state.getDataHolder().gatheringTeamList = new ArrayList<String>();
867
        abcdFieldGetter.getType(root);
868
        abcdFieldGetter.getGatheringPeople(root);
869
    }
870

    
871
    /**
872
     * Store the unit's properties into variables Look which unit is the
873
     * preferred one Look what kind of name it is supposed to be, for the
874
     * parsing (Botanical, Zoological)
875
     * @param state
876
     *
877
     * @param racine: the root node for a single unit
878
     */
879
    private void setUnitPropertiesXML(Element root, Abcd206XMLFieldGetter abcdFieldGetter, Abcd206ImportState state) {
880
        try {
881
            NodeList group;
882

    
883
            group = root.getChildNodes();
884
            for (int i = 0; i < group.getLength(); i++) {
885
                if (group.item(i).getNodeName().equals(state.getPrefix() + "Identifications")) {
886
                    group = group.item(i).getChildNodes();
887
                    break;
888
                }
889
            }
890
            state.getDataHolder().identificationList = new ArrayList<Identification>();
891
            state.getDataHolder().statusList = new ArrayList<SpecimenTypeDesignationStatus>();
892
            state.getDataHolder().atomisedIdentificationList = new ArrayList<HashMap<String, String>>();
893
            state.getDataHolder().referenceList = new ArrayList<String[]>();
894
            state.getDataHolder().multimediaObjects = new ArrayList<String>();
895

    
896
            abcdFieldGetter.getScientificNames(group);
897
            abcdFieldGetter.getType(root);
898

    
899
            if(DEBUG) {
900
                logger.info("this.identificationList "+state.getDataHolder().identificationList.toString());
901
            }
902
            abcdFieldGetter.getIDs(root);
903
            abcdFieldGetter.getRecordBasis(root);
904
            abcdFieldGetter.getKindOfUnit(root);
905
            abcdFieldGetter.getMultimedia(root);
906
            abcdFieldGetter.getNumbers(root);
907
            abcdFieldGetter.getGeolocation(root, state);
908
            abcdFieldGetter.getGatheringPeople(root);
909
            abcdFieldGetter.getGatheringDate(root);
910
            abcdFieldGetter.getGatheringElevation(root);
911
            abcdFieldGetter.getAssociatedUnitIds(root);
912
            boolean referencefound = abcdFieldGetter.getReferences(root);
913
            if (!referencefound) {
914
                String[]a = {state.getRef().getTitleCache(),"",""};
915
                state.getDataHolder().referenceList.add(a);
916
            }
917

    
918
        } catch (Exception e) {
919
            logger.info("Error occured while parsing XML file" + e);
920
        }
921
    }
922

    
923
    /**
924
     * Look if the Institution does already exist
925
     * @param institutionCode: a string with the institutioncode
926
     * @param config : the configurator
927
     * @return the Institution (existing or new)
928
     */
929
    private Institution getInstitution(String institutionCode, Abcd206ImportState state) {
930
        Institution institution=null;
931
        List<Institution> institutions;
932
        try {
933
            institutions = getAgentService().list(Institution.class, null, null, null, null);
934
        } catch (Exception e) {
935
            institutions = new ArrayList<Institution>();
936
            logger.warn(e);
937
        }
938
        if (institutions.size() > 0 && state.getConfig().isReUseExistingMetadata()) {
939
            for (Institution institut:institutions){
940
                try{
941
                    if (institut.getCode().equalsIgnoreCase(institutionCode)) {
942
                        institution=institut;
943
                    }
944
                }catch(Exception e){logger.warn("no institution code in the db");}
945
            }
946
        }
947
        if(DEBUG) {
948
            if(institution !=null) {
949
                logger.info("getinstitution " + institution.toString());
950
            }
951
        }
952
        if (institution == null){
953
            // create institution
954
            institution = Institution.NewInstance();
955
            institution.setCode(institutionCode);
956
            institution.setTitleCache(institutionCode, true);
957
        }
958
        save(institution, state);
959
        return institution;
960
    }
961

    
962
    /**
963
     * Look if the Collection does already exist
964
     * @param collectionCode
965
     * @param collectionCode: a string
966
     * @param config : the configurator
967
     * @return the Collection (existing or new)
968
     */
969
    private Collection getCollection(Institution institution, String collectionCode, Abcd206ImportState state) {
970
        Collection collection = null;
971
        List<Collection> collections;
972
        try {
973
            collections = getCollectionService().list(Collection.class, null, null, null, null);
974
        } catch (Exception e) {
975
            collections = new ArrayList<Collection>();
976
        }
977
        if (collections.size() > 0 && state.getConfig().isReUseExistingMetadata()) {
978
            for (Collection coll:collections){
979
                if (coll.getCode() != null && coll.getInstitute() != null
980
                        && coll.getCode().equalsIgnoreCase(collectionCode) && coll.getInstitute().equals(institution)) {
981
                    collection = coll;
982
                    break;
983
                }
984
            }
985
        }
986

    
987
        if(collection == null){
988
            collection =Collection.NewInstance();
989
            collection.setCode(collectionCode);
990
            collection.setInstitute(institution);
991
            collection.setTitleCache(collectionCode);
992
        }
993
        save(collection, state);
994
        return collection;
995
    }
996

    
997

    
998
    /**
999
     * join DeterminationEvent to the Taxon Object
1000
     * @param state : the ABCD import state
1001
     * @param taxon: the current Taxon
1002
     * @param preferredFlag :if the current name is preferred
1003
     * @param derivedFacade : the derived Unit Facade
1004
     */
1005
    @SuppressWarnings("rawtypes")
1006
    private void linkDeterminationEvent(Abcd206ImportState state, Taxon taxon, boolean preferredFlag,  DerivedUnitFacade derivedFacade) {
1007
        Abcd206ImportConfigurator config = state.getConfig();
1008
        if(DEBUG){
1009
            logger.info("start linkdetermination with taxon:" + taxon.getUuid()+", "+taxon);
1010
        }
1011

    
1012
        DeterminationEvent determinationEvent = DeterminationEvent.NewInstance();
1013
        determinationEvent.setTaxonName(taxon.getName());
1014
        determinationEvent.setPreferredFlag(preferredFlag);
1015

    
1016
        determinationEvent.setIdentifiedUnit(state.getDerivedUnitBase());
1017
        state.getDerivedUnitBase().addDetermination(determinationEvent);
1018

    
1019
        if(DEBUG){
1020
            logger.info("NB TYPES INFO: "+ state.getDataHolder().statusList.size());
1021
        }
1022
        for (SpecimenTypeDesignationStatus specimenTypeDesignationstatus : state.getDataHolder().statusList) {
1023
            if (specimenTypeDesignationstatus != null) {
1024
                if(DEBUG){
1025
                    logger.info("specimenTypeDesignationstatus :"+ specimenTypeDesignationstatus);
1026
                }
1027

    
1028
                ICdmApplicationConfiguration cdmAppController = config.getCdmAppController();
1029
                if(cdmAppController == null){
1030
                    cdmAppController = this;
1031
                }
1032
                specimenTypeDesignationstatus = (SpecimenTypeDesignationStatus) cdmAppController.getTermService().find(specimenTypeDesignationstatus.getUuid());
1033
                //Designation
1034
                TaxonNameBase<?,?> name = taxon.getName();
1035
                SpecimenTypeDesignation designation = SpecimenTypeDesignation.NewInstance();
1036

    
1037
                designation.setTypeStatus(specimenTypeDesignationstatus);
1038
                designation.setTypeSpecimen(state.getDerivedUnitBase());
1039
                name.addTypeDesignation(designation, true);
1040
            }
1041
        }
1042

    
1043
        for (String[] fullReference : state.getDataHolder().referenceList) {
1044
            List<Reference> references = getReferenceService().list(Reference.class, null, null, null, null);
1045

    
1046
            String strReference=fullReference[0];
1047
            String citationDetail = fullReference[1];
1048
            String citationURL = fullReference[2];
1049

    
1050
            if (isNotBlank(strReference)){
1051
                Reference<?> reference = null;
1052
                for (Reference<?> refe: references) {
1053
                    if (refe.getTitleCache().equalsIgnoreCase(strReference)) {
1054
                        reference =refe;
1055
                        break;
1056
                    }
1057
                }
1058
                if (reference ==null){
1059
                    reference = ReferenceFactory.newGeneric();
1060
                    reference.setTitleCache(strReference, true);
1061
                    save(reference, state);
1062
                }
1063
                determinationEvent.addReference(reference);
1064
            }
1065
        }
1066
        save(state.getDerivedUnitBase(), state);
1067

    
1068
        if (config.isAddIndividualsAssociationsSuchAsSpecimenAndObservations() && preferredFlag) {
1069
            //do not add IndividualsAssociation to non-preferred taxa
1070
            if(DEBUG){
1071
                logger.info("isDoCreateIndividualsAssociations");
1072
            }
1073

    
1074
            makeIndividualsAssociation(state, taxon, determinationEvent);
1075

    
1076
            save(state.getDerivedUnitBase(), state);
1077
        }
1078
    }
1079

    
1080
    /**
1081
     * create and link each association (specimen, observation..) to the accepted taxon
1082
     * @param state : the ABCD import state
1083
     * @param taxon: the current Taxon
1084
     * @param determinationEvent:the determinationevent
1085
     */
1086
    private void makeIndividualsAssociation(Abcd206ImportState state, Taxon taxon, DeterminationEvent determinationEvent) {
1087
        SpecimenUserInteraction sui = state.getConfig().getSpecimenUserInteraction();
1088

    
1089
        if (DEBUG) {
1090
            logger.info("MAKE INDIVIDUALS ASSOCIATION");
1091
        }
1092

    
1093
        TaxonDescription taxonDescription = null;
1094
        Set<TaxonDescription> descriptions= taxon.getDescriptions();
1095
        if (state.getConfig().isInteractWithUser()){
1096
            if(!state.isDescriptionGroupSet()){
1097
                taxonDescription = sui.askForDescriptionGroup(descriptions);
1098
                state.setDescriptionGroup(taxonDescription);
1099
                state.setDescriptionGroupSet(true);
1100
            }else{
1101
                taxonDescription=state.getDescriptionGroup();
1102
            }
1103
        } else {
1104
            for (TaxonDescription description : descriptions){
1105
                Set<IdentifiableSource> sources =  description.getTaxon().getSources();
1106
                sources.addAll(description.getSources());
1107
                for (IdentifiableSource source:sources){
1108
                    if(state.getRef().equals(source.getCitation())) {
1109
                        taxonDescription = description;
1110
                    }
1111
                }
1112
            }
1113
        }
1114
        if (taxonDescription == null){
1115
            taxonDescription = TaxonDescription.NewInstance(taxon, false);
1116
            if(sourceNotLinkedToElement(taxonDescription,state.getRef(),null)) {
1117
                taxonDescription.addSource(OriginalSourceType.Import, null, null, state.getRef(), null);
1118
            }
1119
            state.setDescriptionGroup(taxonDescription);
1120
            taxon.addDescription(taxonDescription);
1121
        }
1122

    
1123
        //PREPARE REFERENCE QUESTIONS
1124

    
1125
        Map<String,OriginalSourceBase<?>> sourceMap = new HashMap<String, OriginalSourceBase<?>>();
1126

    
1127
        List<IdentifiableSource> issTmp = getCommonService().list(IdentifiableSource.class, null, null, null, null);
1128
        List<DescriptionElementSource> issTmp2 = getCommonService().list(DescriptionElementSource.class, null, null, null, null);
1129

    
1130
        Set<OriginalSourceBase> osbSet = new HashSet<OriginalSourceBase>();
1131
        if(issTmp2!=null) {
1132
            osbSet.addAll(issTmp2);
1133
        }
1134
        if(issTmp!=null) {
1135
            osbSet.addAll(issTmp);
1136
        }
1137

    
1138

    
1139
        addToSourceMap(sourceMap, osbSet);
1140

    
1141
        if (state.getConfig().isInteractWithUser()){
1142
            List<OriginalSourceBase<?>> res = null;
1143
            if(!state.isDescriptionSourcesSet()){
1144
                res = sui.askForSource(sourceMap, "the description group ("+taxon+")",
1145
                        "The current reference is "+state.getRef().getTitleCache(),getReferenceService(), state.getDataHolder().docSources);
1146
                state.setDescriptionRefs(res);
1147
                state.setDescriptionSourcesSet(true);
1148
            }
1149
            else{
1150
                res=state.getDescriptionRefs();
1151
            }
1152
            if(res !=null) {
1153
                for (OriginalSourceBase<?> sour:res){
1154
                    if(sour.isInstanceOf(IdentifiableSource.class)){
1155
                        try {
1156
                            if(sourceNotLinkedToElement(taxonDescription,sour)) {
1157
                                taxonDescription.addSource((IdentifiableSource)sour.clone());
1158
                            }
1159
                        } catch (CloneNotSupportedException e) {
1160
                            logger.warn("no cloning?");
1161
                        }
1162
                    }else{
1163
                        if(sourceNotLinkedToElement(taxonDescription,sour)) {
1164
                            taxonDescription.addSource(OriginalSourceType.Import,null, null, sour.getCitation(),sour.getCitationMicroReference());
1165
                        }
1166
                    }
1167
                }
1168
            }
1169
        }
1170
        else {
1171
            if(sourceNotLinkedToElement(taxonDescription,state.getRef(),null)) {
1172
                taxonDescription.addSource(OriginalSourceType.Import,null, null, state.getRef(), null);
1173
            }
1174
        }
1175
        state.setDescriptionGroup(taxonDescription);
1176

    
1177
        IndividualsAssociation indAssociation = IndividualsAssociation.NewInstance();
1178
        Feature feature = makeFeature(state.getDerivedUnitBase());
1179
        indAssociation.setAssociatedSpecimenOrObservation(state.getDerivedUnitBase());
1180
        indAssociation.setFeature(feature);
1181

    
1182
        if (state.getConfig().isInteractWithUser()){
1183
            sourceMap = new HashMap<String, OriginalSourceBase<?>>();
1184

    
1185
            issTmp = getCommonService().list(IdentifiableSource.class, null, null, null, null);
1186
            issTmp2 = getCommonService().list(DescriptionElementSource.class, null, null, null, null);
1187

    
1188
            osbSet = new HashSet<OriginalSourceBase>();
1189
            if(issTmp2!=null) {
1190
                osbSet.addAll(issTmp2);
1191
            }
1192
            if(issTmp!=null) {
1193
                osbSet.addAll(issTmp);
1194
            }
1195

    
1196

    
1197
            addToSourceMap(sourceMap, osbSet);
1198

    
1199
            List<OriginalSourceBase<?>> sources =null;
1200
            if(!state.isAssociationSourcesSet()) {
1201
                sources = sui.askForSource(sourceMap,  "descriptive element (association) ",taxon.toString(),
1202
                        getReferenceService(),state.getDataHolder().docSources);
1203
                state.setAssociationRefs(sources);
1204
                state.setAssociationSourcesSet(true);
1205
            }
1206
            else{
1207
                sources=state.getAssociationRefs();
1208
            }
1209
            if(sources !=null) {
1210
                for (OriginalSourceBase<?> source: sources) {
1211
                    if(source !=null) {
1212
                        if(source.isInstanceOf(DescriptionElementSource.class)){
1213
                            try {
1214
                                if(sourceNotLinkedToElement(indAssociation,source)) {
1215
                                    indAssociation.addSource((DescriptionElementSource)source.clone());
1216
                                }
1217
                            } catch (CloneNotSupportedException e) {
1218
                                logger.warn("clone forbidden?");
1219
                            }
1220
                        }else{
1221
                            if(sourceNotLinkedToElement(indAssociation,source)) {
1222
                                indAssociation.addSource(OriginalSourceType.Import,null, null, source.getCitation(),source.getCitationMicroReference());
1223
                            }
1224
                            try {
1225
                                if(sourceNotLinkedToElement(state.getDerivedUnitBase(), source)) {
1226
                                    state.getDerivedUnitBase().addSource((IdentifiableSource) source.clone());
1227
                                }
1228
                            } catch (CloneNotSupportedException e) {
1229
                                // TODO Auto-generated catch block
1230
                                e.printStackTrace();
1231
                            }
1232
                        }
1233

    
1234
                    }
1235
                }
1236
            }
1237
        }else {
1238
            if(sourceNotLinkedToElement(indAssociation,state.getRef(),null)) {
1239
                indAssociation.addSource(OriginalSourceType.Import,null, null, state.getRef(), null);
1240
            }
1241
            if(sourceNotLinkedToElement(state.getDerivedUnitBase(), state.getRef(),null)) {
1242
                state.getDerivedUnitBase().addSource(OriginalSourceType.Import,null, null, state.getRef(), null);
1243
            }
1244
            for (Reference<?> citation : determinationEvent.getReferences()) {
1245
                if(sourceNotLinkedToElement(indAssociation,citation,null))
1246
                {
1247
                    indAssociation.addSource(DescriptionElementSource.NewInstance(OriginalSourceType.Import, null, null, citation, null));
1248
                }
1249
                if(sourceNotLinkedToElement(state.getDerivedUnitBase(), state.getRef(),null)) {
1250
                    state.getDerivedUnitBase().addSource(OriginalSourceType.Import,null, null, state.getRef(), null);
1251
                }
1252
            }
1253
        }
1254

    
1255
        taxonDescription.addElement(indAssociation);
1256

    
1257
        save(taxonDescription, state);
1258
        save(taxon, state);
1259
        report.addDerivate(state.getDerivedUnitBase(), state.getConfig());
1260
        report.addIndividualAssociation(taxon, state.getDataHolder().unitID, state.getDerivedUnitBase());
1261
    }
1262

    
1263
    /**
1264
     * @param derivedUnitBase2
1265
     * @param ref2
1266
     * @param object
1267
     * @return
1268
     */
1269
    private boolean sourceNotLinkedToElement(DerivedUnit derivedUnitBase2, Reference<?> b, String d) {
1270
        Set<IdentifiableSource> linkedSources = derivedUnitBase2.getSources();
1271
        for (IdentifiableSource is:linkedSources){
1272
            Reference<?> a = is.getCitation();
1273
            String c = is.getCitationMicroReference();
1274

    
1275
            boolean refMatch=false;
1276
            boolean microMatch=false;
1277

    
1278
            try{
1279
                if (a==null && b==null) {
1280
                    refMatch=true;
1281
                }
1282
                if (a!=null && b!=null) {
1283
                    if (a.getTitleCache().equalsIgnoreCase(b.getTitleCache())) {
1284
                        refMatch=true;
1285
                    }
1286
                }
1287
            }catch(Exception e){}
1288

    
1289

    
1290
            try{
1291
                if (c==null && d==null) {
1292
                    microMatch=true;
1293
                }
1294
                if(c!=null && d!=null) {
1295
                    if(c.equalsIgnoreCase(d)) {
1296
                        microMatch=true;
1297
                    }
1298
                }
1299
            }
1300
            catch(Exception e){}
1301

    
1302
            if (microMatch && refMatch) {
1303
                return false;
1304
            }
1305

    
1306

    
1307
        }
1308
        return true;
1309
    }
1310

    
1311
    /**
1312
     * @param specimen
1313
     * @param source
1314
     * @return
1315
     */
1316
    private boolean sourceNotLinkedToElement(SpecimenOrObservationBase<?> specimen, OriginalSourceBase<?> source) {
1317
        Set<IdentifiableSource> linkedSources = specimen.getSources();
1318
        for (IdentifiableSource is:linkedSources){
1319
            Reference<?> a = is.getCitation();
1320
            Reference<?> b = source.getCitation();
1321
            String c = is.getCitationMicroReference();
1322
            String d = source.getCitationMicroReference();
1323

    
1324
            boolean refMatch=false;
1325
            boolean microMatch=false;
1326

    
1327
            try{
1328
                if (a==null && b==null) {
1329
                    refMatch=true;
1330
                }
1331
                if (a!=null && b!=null) {
1332
                    if (a.getTitleCache().equalsIgnoreCase(b.getTitleCache())) {
1333
                        refMatch=true;
1334
                    }
1335
                }
1336
            }catch(Exception e){}
1337

    
1338

    
1339
            try{
1340
                if (c==null && d==null) {
1341
                    microMatch=true;
1342
                }
1343
                if(c!=null && d!=null) {
1344
                    if(c.equalsIgnoreCase(d)) {
1345
                        microMatch=true;
1346
                    }
1347
                }
1348
            }
1349
            catch(Exception e){}
1350

    
1351
            if (microMatch && refMatch) {
1352
                return false;
1353
            }
1354

    
1355

    
1356
        }
1357
        return true;
1358
    }
1359

    
1360
    /**
1361
     * @param indAssociation
1362
     * @param ref2
1363
     * @param object
1364
     * @return
1365
     */
1366
    private boolean sourceNotLinkedToElement(IndividualsAssociation indAssociation, Reference<?> a, String d) {
1367
        Set<DescriptionElementSource> linkedSources = indAssociation.getSources();
1368
        for (DescriptionElementSource is:linkedSources){
1369
            Reference<?> b = is.getCitation();
1370
            String c = is.getCitationMicroReference();
1371

    
1372
            boolean refMatch=false;
1373
            boolean microMatch=false;
1374

    
1375
            try{
1376
                if (a==null && b==null) {
1377
                    refMatch=true;
1378
                }
1379
                if (a!=null && b!=null) {
1380
                    if (a.getTitleCache().equalsIgnoreCase(b.getTitleCache())) {
1381
                        refMatch=true;
1382
                    }
1383
                }
1384
            }catch(Exception e){}
1385

    
1386

    
1387
            try{
1388
                if (c==null && d==null) {
1389
                    microMatch=true;
1390
                }
1391
                if(c!=null && d!=null) {
1392
                    if(c.equalsIgnoreCase(d)) {
1393
                        microMatch=true;
1394
                    }
1395
                }
1396
            }
1397
            catch(Exception e){}
1398

    
1399
            if (microMatch && refMatch) {
1400
                return false;
1401
            }
1402
        }
1403
        return true;
1404
    }
1405

    
1406
    /**
1407
     * @param taxonDescription
1408
     * @param ref2
1409
     * @param object
1410
     * @return
1411
     */
1412
    private boolean sourceNotLinkedToElement(TaxonDescription taxonDescription, Reference<?> a, String d) {
1413
        Set<IdentifiableSource> linkedSources = taxonDescription.getSources();
1414
        for (IdentifiableSource is:linkedSources){
1415
            Reference<?> b = is.getCitation();
1416
            String c = is.getCitationMicroReference();
1417

    
1418
            boolean refMatch=false;
1419
            boolean microMatch=false;
1420

    
1421
            try{
1422
                if (a==null && b==null) {
1423
                    refMatch=true;
1424
                }
1425
                if (a!=null && b!=null) {
1426
                    if (a.getTitleCache().equalsIgnoreCase(b.getTitleCache())) {
1427
                        refMatch=true;
1428
                    }
1429
                }
1430
            }catch(Exception e){}
1431

    
1432

    
1433
            try{
1434
                if (c==null && d==null) {
1435
                    microMatch=true;
1436
                }
1437
                if(c!=null && d!=null) {
1438
                    if(c.equalsIgnoreCase(d)) {
1439
                        microMatch=true;
1440
                    }
1441
                }
1442
            }
1443
            catch(Exception e){}
1444

    
1445
            if (microMatch && refMatch) {
1446
                return false;
1447
            }
1448
        }
1449
        return true;
1450
    }
1451

    
1452
    /**
1453
     * @param indAssociation
1454
     * @param source
1455
     * @return
1456
     */
1457
    private boolean sourceNotLinkedToElement(IndividualsAssociation indAssociation, OriginalSourceBase<?> source) {
1458
        Set<DescriptionElementSource> linkedSources = indAssociation.getSources();
1459
        for (DescriptionElementSource is:linkedSources){
1460
            Reference<?> a = is.getCitation();
1461
            Reference<?> b = source.getCitation();
1462
            String c = is.getCitationMicroReference();
1463
            String d = source.getCitationMicroReference();
1464

    
1465
            boolean refMatch=false;
1466
            boolean microMatch=false;
1467

    
1468
            try{
1469
                if (a==null && b==null) {
1470
                    refMatch=true;
1471
                }
1472
                if (a!=null && b!=null) {
1473
                    if (a.getTitleCache().equalsIgnoreCase(b.getTitleCache())) {
1474
                        refMatch=true;
1475
                    }
1476
                }
1477
            }catch(Exception e){}
1478

    
1479

    
1480
            try{
1481
                if (c==null && d==null) {
1482
                    microMatch=true;
1483
                }
1484
                if(c!=null && d!=null) {
1485
                    if(c.equalsIgnoreCase(d)) {
1486
                        microMatch=true;
1487
                    }
1488
                }
1489
            }
1490
            catch(Exception e){}
1491

    
1492
            if (microMatch && refMatch) {
1493
                return false;
1494
            }
1495
        }
1496
        return true;
1497
    }
1498

    
1499
    /**
1500
     * @param taxonDescription
1501
     * @param sour
1502
     * @return
1503
     */
1504
    private boolean sourceNotLinkedToElement(TaxonDescription taxonDescription, OriginalSourceBase<?> sour) {
1505
        Set<IdentifiableSource> linkedSources = taxonDescription.getSources();
1506
        for (IdentifiableSource is:linkedSources){
1507
            Reference<?> a = is.getCitation();
1508
            Reference<?> b = sour.getCitation();
1509
            String c = is.getCitationMicroReference();
1510
            String d = sour.getCitationMicroReference();
1511

    
1512
            boolean refMatch=false;
1513
            boolean microMatch=false;
1514

    
1515
            try{
1516
                if (a==null && b==null) {
1517
                    refMatch=true;
1518
                }
1519
                if (a!=null && b!=null) {
1520
                    if (a.getTitleCache().equalsIgnoreCase(b.getTitleCache())) {
1521
                        refMatch=true;
1522
                    }
1523
                }
1524
            }catch(Exception e){}
1525

    
1526

    
1527
            try{
1528
                if (c==null && d==null) {
1529
                    microMatch=true;
1530
                }
1531
                if(c!=null && d!=null) {
1532
                    if(c.equalsIgnoreCase(d)) {
1533
                        microMatch=true;
1534
                    }
1535
                }
1536
            }
1537
            catch(Exception e){}
1538

    
1539
            if (microMatch && refMatch) {
1540
                return false;
1541
            }
1542

    
1543

    
1544
        }
1545
        return true;
1546
    }
1547

    
1548
    /**
1549
     * look for the Feature object (FieldObs, Specimen,...)
1550
     * @param unit : a specimen or obersvation base
1551
     * @return the corresponding Feature
1552
     */
1553
    private Feature makeFeature(SpecimenOrObservationBase<?> unit) {
1554
        SpecimenOrObservationType type = unit.getRecordBasis();
1555

    
1556

    
1557

    
1558
        if (type.isFeatureObservation()){
1559
            return Feature.OBSERVATION();
1560
        }else if (type.isFeatureSpecimen()){
1561
            return Feature.SPECIMEN();
1562
        }else if (type == SpecimenOrObservationType.DerivedUnit){
1563
            return Feature.OBSERVATION();
1564
            //            return getFeature("Specimen or observation");
1565
        }else{
1566
            String message = "Unhandled record basis '%s' for defining individuals association feature type. Use default.";
1567
            logger.warn(String.format(message, type.getMessage()));
1568
            return Feature.OBSERVATION();
1569
            //            return getFeature("Specimen or observation");
1570

    
1571
        }
1572
    }
1573

    
1574
    /**
1575
     * HandleIdentifications : get the scientific names present in the ABCD
1576
     * document and store link them with the observation/specimen data
1577
     * @param state: the current ABCD import state
1578
     * @param derivedUnitFacade : the current derivedunitfacade
1579
     */
1580
    private void handleIdentifications(Abcd206ImportState state, DerivedUnitFacade derivedUnitFacade) {
1581
        Abcd206ImportConfigurator config = state.getConfig();
1582

    
1583

    
1584
        String scientificName = "";
1585
        boolean preferredFlag = false;
1586

    
1587
        if (state.getDataHolder().nomenclatureCode == ""){
1588
            state.getDataHolder().nomenclatureCode = config.getNomenclaturalCode().toString();
1589
        }
1590

    
1591
        for (int i = 0; i < state.getDataHolder().identificationList.size(); i++) {
1592
            Identification identification = state.getDataHolder().identificationList.get(i);
1593
            scientificName = identification.getScientificName().replaceAll(" et ", " & ");
1594

    
1595
            String preferred = identification.getPreferred();
1596
            if (preferred.equals("1") || preferred.toLowerCase().indexOf("true") != -1 || state.getDataHolder().identificationList.size()==1) {
1597
                preferredFlag = true;
1598
            }
1599
            else {
1600
                preferredFlag = false;
1601
            }
1602

    
1603
            if (identification.getCode().indexOf(':') != -1) {
1604
                state.getDataHolder().nomenclatureCode = identification.getCode().split(COLON)[1];
1605
            }
1606
            else{
1607
                state.getDataHolder().nomenclatureCode = identification.getCode();
1608
            }
1609
            TaxonNameBase<?,?> taxonName = getOrCreateTaxonName(scientificName, null, preferredFlag, state, i);
1610
            Taxon taxon = getOrCreateTaxonForName(taxonName, state);
1611
            addTaxonNode(taxon, state,preferredFlag);
1612
            linkDeterminationEvent(state, taxon, preferredFlag, derivedUnitFacade);
1613
        }
1614
    }
1615

    
1616

    
1617
    private TaxonNameBase<?, ?> getOrCreateTaxonName(String scientificName, Rank rank, boolean preferredFlag, Abcd206ImportState state, int unitIndexInAbcdFile){
1618
        TaxonNameBase<?, ?> taxonName = null;
1619
        Abcd206ImportConfigurator config = state.getConfig();
1620

    
1621
        //check atomised name data for rank
1622
        //new name will be created
1623
        NonViralName<?> atomisedTaxonName = null;
1624
        if (rank==null && unitIndexInAbcdFile>=0 && (state.getDataHolder().atomisedIdentificationList != null || state.getDataHolder().atomisedIdentificationList.size() > 0)) {
1625
            atomisedTaxonName = setTaxonNameByType(state.getDataHolder().atomisedIdentificationList.get(unitIndexInAbcdFile), scientificName, state);
1626
            if(atomisedTaxonName!=null){
1627
                rank = atomisedTaxonName.getRank();
1628
            }
1629
        }
1630
        if(config.isReuseExistingTaxaWhenPossible()){
1631
            NonViralName<?> parsedName = atomisedTaxonName;
1632
            if(parsedName==null){
1633
                parsedName = parseScientificName(scientificName, state, report);
1634
            }
1635
            if(config.isIgnoreAuthorship() && parsedName!=null && preferredFlag){
1636
                // do not ignore authorship for non-preferred names because they need
1637
                // to be created for the determination history
1638
                String nameCache = parsedName.getNameCache();
1639
                List<NonViralName> names = getNameService().findNamesByNameCache(nameCache, MatchMode.EXACT, null);
1640
                taxonName = getBestMatchingName(scientificName, new ArrayList<TaxonNameBase>(names));
1641
            }
1642
            else {
1643
                //search for existing names
1644
                List<TaxonNameBase> names = getNameService().listByTitle(TaxonNameBase.class, scientificName, MatchMode.EXACT, null, null, null, null, null);
1645
                taxonName = getBestMatchingName(scientificName, names);
1646
                //still nothing found -> try with the atomised name full title cache
1647
                if(taxonName==null && atomisedTaxonName!=null){
1648
                    names = getNameService().listByTitle(TaxonNameBase.class, atomisedTaxonName.getFullTitleCache(), MatchMode.EXACT, null, null, null, null, null);
1649
                    taxonName = getBestMatchingName(atomisedTaxonName.getTitleCache(), names);
1650
                    //still nothing found -> try with the atomised name title cache
1651
                    if(taxonName==null){
1652
                        names = getNameService().listByTitle(TaxonNameBase.class, atomisedTaxonName.getTitleCache(), MatchMode.EXACT, null, null, null, null, null);
1653
                        taxonName = getBestMatchingName(atomisedTaxonName.getTitleCache(), names);
1654
                    }
1655
                }
1656
            }
1657
        }
1658

    
1659
        if(taxonName==null && atomisedTaxonName!=null){
1660
            taxonName = atomisedTaxonName;
1661
            report.addName(taxonName);
1662
            logger.info("Created new taxon name "+taxonName);
1663
            if(taxonName.hasProblem()){
1664
                report.addInfoMessage(String.format("Created %s with parsing problems", taxonName));
1665
            }
1666
            if(!atomisedTaxonName.getTitleCache().equals(scientificName)){
1667
                report.addInfoMessage(String.format("Taxon %s was parsed as %s", scientificName, atomisedTaxonName.getTitleCache()));
1668
            }
1669
        }
1670
        else if(taxonName==null){
1671
            //create new taxon name
1672
            taxonName = NonViralName.NewInstance(rank);
1673
            taxonName.setFullTitleCache(scientificName,true);
1674
            taxonName.setTitleCache(scientificName, true);
1675
            report.addName(taxonName);
1676
            logger.info("Created new taxon name "+taxonName);
1677
        }
1678
        save(taxonName, state);
1679
        return taxonName;
1680
    }
1681

    
1682
    private TaxonNameBase<?, ?> getBestMatchingName(String scientificName, java.util.Collection<TaxonNameBase> names){
1683
        List<TaxonNameBase> namesWithAcceptedTaxa = new ArrayList<TaxonNameBase>();
1684
        for (TaxonNameBase name : names) {
1685
            if(!name.getTaxa().isEmpty()){
1686
                namesWithAcceptedTaxa.add(name);
1687
            }
1688
        }
1689
        String message = "More than one taxon name was found for "+scientificName+"!";
1690
        //check for names with accepted taxa
1691
        if(namesWithAcceptedTaxa.size()>0){
1692
            if(namesWithAcceptedTaxa.size()>1){
1693
                report.addInfoMessage(message);
1694
                logger.warn(message);
1695
                return null;
1696
            }
1697
            return namesWithAcceptedTaxa.iterator().next();
1698
        }
1699
        //no names with accepted taxa found -> check accepted taxa of synonyms
1700
        List<Taxon> taxaFromSynonyms = new ArrayList<Taxon>();
1701
        for (TaxonNameBase name : names) {
1702
            Set<TaxonBase> taxonBases = name.getTaxonBases();
1703
            for (TaxonBase taxonBase : taxonBases) {
1704
                if(taxonBase.isInstanceOf(Synonym.class)){
1705
                    Synonym synonym = HibernateProxyHelper.deproxy(taxonBase, Synonym.class);
1706
                    taxaFromSynonyms.addAll(synonym.getAcceptedTaxa());
1707
                }
1708
            }
1709
        }
1710
        if(taxaFromSynonyms.size()>0){
1711
            if(taxaFromSynonyms.size()>1){
1712
                report.addInfoMessage(message);
1713
                logger.warn(message);
1714
                return null;
1715
            }
1716
            return taxaFromSynonyms.iterator().next().getName();
1717
        }
1718
        return null;
1719
    }
1720

    
1721
    private Taxon getOrCreateTaxonForName(TaxonNameBase<?, ?> taxonNameBase, Abcd206ImportState state){
1722
        Set<Taxon> acceptedTaxa = taxonNameBase.getTaxa();
1723
        if(acceptedTaxa.size()>0){
1724
            Taxon firstAcceptedTaxon = acceptedTaxa.iterator().next();
1725
            if(acceptedTaxa.size()>1){
1726
                String message = "More than one accepted taxon was found for taxon name: "
1727
                        + taxonNameBase.getTitleCache() + "!\n" + firstAcceptedTaxon + "was chosen for "+state.getDerivedUnitBase();
1728
                report.addInfoMessage(message);
1729
                logger.warn(message);
1730
            }
1731
            else{
1732
                return firstAcceptedTaxon;
1733
            }
1734
        }
1735
        else{
1736
            Set<TaxonBase> taxonAndSynonyms = taxonNameBase.getTaxonBases();
1737
            for (TaxonBase taxonBase : taxonAndSynonyms) {
1738
                if(taxonBase.isInstanceOf(Synonym.class)){
1739
                    Synonym synonym = HibernateProxyHelper.deproxy(taxonBase, Synonym.class);
1740
                    Set<Taxon> acceptedTaxaOfSynonym = synonym.getAcceptedTaxa();
1741
                    if(acceptedTaxaOfSynonym.size()!=1){
1742
                        String message = "No accepted taxa could be found for taxon name: "
1743
                                + taxonNameBase.getTitleCache()
1744
                                + "!\nEither it is a pro parte synonym or has no accepted taxa";
1745
                        report.addInfoMessage(message);
1746
                        logger.warn(message);
1747
                    }
1748
                    else{
1749
                        return acceptedTaxaOfSynonym.iterator().next();
1750
                    }
1751
                }
1752
            }
1753
        }
1754
        Taxon taxon = Taxon.NewInstance(taxonNameBase, state.getRef());
1755
        save(taxon, state);
1756
        report.addTaxon(taxon);
1757
        logger.info("Created new taxon "+ taxon);
1758
        return taxon;
1759
    }
1760

    
1761
    /**
1762
     * @param taxon : a taxon to add as a node
1763
     * @param state : the ABCD import state
1764
     */
1765
    private void addTaxonNode(Taxon taxon, Abcd206ImportState state, boolean preferredFlag) {
1766
        logger.info("link taxon to a taxonNode "+taxon.getTitleCache());
1767
        //only add nodes if not already existing in current classification or default classification
1768

    
1769
        //check if node exists in current classification
1770
        //NOTE: we cannot use hasTaxonNodeInClassification() here because we are first creating it here
1771
        if (!existsInClassification(taxon, state.getClassification())){
1772
            if(state.getConfig().isMoveNewTaxaToDefaultClassification()){
1773
                //check if node exists in default classification
1774
                if(!existsInClassification(taxon, state.getDefaultClassification())){
1775
                    addParentTaxon(taxon, state, preferredFlag, state.getDefaultClassification());
1776
                }
1777
            }
1778
            else {
1779
                //add non-existing taxon to current classification
1780
                addParentTaxon(taxon, state, preferredFlag, state.getClassification());
1781
            }
1782
        }
1783
    }
1784

    
1785
    private boolean existsInClassification(Taxon taxon, Classification classification){
1786
        boolean exist = false;
1787
        Set<TaxonNode> allNodes = classification.getAllNodes();
1788
        for (TaxonNode p : allNodes){
1789
            try{
1790
                if(p.getTaxon().equals(taxon)) {
1791
                    exist = true;
1792
                }
1793
            }
1794
            catch(Exception e){
1795
                logger.warn("TaxonNode doesn't seem to have a taxon");
1796
            }
1797
        }
1798
        return exist;
1799
    }
1800

    
1801
    private boolean hasTaxonNodeInClassification(Taxon taxon, Classification classification){
1802
        if(taxon.getTaxonNodes()!=null){
1803
            for (TaxonNode node : taxon.getTaxonNodes()){
1804
                if(node.getClassification().equals(classification)){
1805
                    return true;
1806
                }
1807
            }
1808
        }
1809
        return false;
1810
    }
1811

    
1812
    /**
1813
     * Add the hierarchy for a Taxon(add higher taxa)
1814
     * @param classification
1815
     * @param taxon: a taxon to add as a node
1816
     * @param state: the ABCD import state
1817
     */
1818
    private void addParentTaxon(Taxon taxon, Abcd206ImportState state, boolean preferredFlag, Classification classification){
1819
        NonViralName<?>  nvname = CdmBase.deproxy(taxon.getName(), NonViralName.class);
1820
        Rank rank = nvname.getRank();
1821
        Taxon genus =null;
1822
        Taxon subgenus =null;
1823
        Taxon species = null;
1824
        Taxon subspecies = null;
1825
        Taxon parent = null;
1826
        if(rank!=null){
1827
            if (rank.isLower(Rank.GENUS() )){
1828
                String genusOrUninomial = nvname.getGenusOrUninomial();
1829
                TaxonNameBase<?,?> taxonName = getOrCreateTaxonName(genusOrUninomial, Rank.GENUS(), preferredFlag, state, -1);
1830
                genus = getOrCreateTaxonForName(taxonName, state);
1831
                if (preferredFlag) {
1832
                    parent = linkParentChildNode(null, genus, classification, state);
1833
                }
1834

    
1835
            }
1836
            if (rank.isLower(Rank.SUBGENUS())){
1837
                String prefix = nvname.getGenusOrUninomial();
1838
                String name = nvname.getInfraGenericEpithet();
1839
                if (name != null){
1840
                    TaxonNameBase<?,?> taxonName = getOrCreateTaxonName(prefix+" "+name, Rank.SUBGENUS(), preferredFlag, state, -1);
1841
                    subgenus = getOrCreateTaxonForName(taxonName, state);
1842
                    if (preferredFlag) {
1843
                        parent = linkParentChildNode(genus, subgenus, classification, state);
1844
                    }            }
1845
            }
1846
            if (rank.isLower(Rank.SPECIES())){
1847
                if (subgenus!=null){
1848
                    String prefix = nvname.getGenusOrUninomial();
1849
                    String name = nvname.getInfraGenericEpithet();
1850
                    String spe = nvname.getSpecificEpithet();
1851
                    if (spe != null){
1852
                        TaxonNameBase<?,?> taxonName = getOrCreateTaxonName(prefix+" "+name+" "+spe, Rank.SPECIES(), preferredFlag, state, -1);
1853
                        species = getOrCreateTaxonForName(taxonName, state);
1854
                        if (preferredFlag) {
1855
                            parent = linkParentChildNode(subgenus, species, classification, state);
1856
                        }
1857
                    }
1858
                }
1859
                else{
1860
                    String prefix = nvname.getGenusOrUninomial();
1861
                    String name = nvname.getSpecificEpithet();
1862
                    if (name != null){
1863
                        TaxonNameBase<?,?> taxonName = getOrCreateTaxonName(prefix+" "+name, Rank.SPECIES(), preferredFlag, state, -1);
1864
                        species = getOrCreateTaxonForName(taxonName, state);
1865
                        if (preferredFlag) {
1866
                            parent = linkParentChildNode(genus, species, classification, state);
1867
                        }
1868
                    }
1869
                }
1870
            }
1871
            if (rank.isLower(Rank.INFRASPECIES())){
1872
                TaxonNameBase<?,?> taxonName = getOrCreateTaxonName(nvname.getFullTitleCache(), Rank.SUBSPECIES(), preferredFlag, state, -1);
1873
                subspecies = getOrCreateTaxonForName(taxonName, state);
1874
                if (preferredFlag) {
1875
                    parent = linkParentChildNode(species, subspecies, classification, state);
1876
                }
1877
            }
1878
        }
1879
        if (preferredFlag && parent!=taxon) {
1880
            linkParentChildNode(parent, taxon, classification, state);
1881
        }
1882
    }
1883

    
1884
    /**
1885
     * Link a parent to a child and save it in the current classification
1886
     * @param parent: the higher Taxon
1887
     * @param child : the lower (or current) Taxon
1888
     * return the Taxon from the new created Node
1889
     * @param classification
1890
     * @param state
1891
     */
1892
    private Taxon linkParentChildNode(Taxon parent, Taxon child, Classification classification, Abcd206ImportState state) {
1893
        TaxonNode node =null;
1894
        if (parent != null) {
1895
            parent = (Taxon) getTaxonService().find(parent.getUuid());
1896
            child = (Taxon) getTaxonService().find(child.getUuid());
1897
            //here we do not have to check if the taxon nodes already exists
1898
            //this is done by classification.addParentChild()
1899
            //do not add child node if it already exists
1900
            if(hasTaxonNodeInClassification(child, classification)){
1901
                return child;
1902
            }
1903
            else{
1904
                node = classification.addParentChild(parent, child, state.getRef(), "");
1905
                save(classification, state);
1906
            }
1907
        }
1908
        else {
1909
            child = (Taxon) getTaxonService().find(child.getUuid());
1910
            //do not add child node if it already exists
1911
            if(hasTaxonNodeInClassification(child, classification)){
1912
                return child;
1913
            }
1914
            else{
1915
                node = classification.addChildTaxon(child, state.getRef(), null);
1916
                save(classification, state);
1917
            }
1918
        }
1919
        if(node!=null){
1920
            report.addTaxonNode(node);
1921
            return node.getTaxon();
1922
        }
1923
        String message = "Could not create taxon node for " +child;
1924
        report.addInfoMessage(message);
1925
        logger.warn(message);
1926
        return null;
1927
    }
1928

    
1929
    /**
1930
     * Parse automatically the scientific name
1931
     * @param scientificName the scientific name to parse
1932
     * @param state the current import state
1933
     * @param report the import report
1934
     * @return a parsed name
1935
     */
1936
    private NonViralName<?> parseScientificName(String scientificName, Abcd206ImportState state, Abcd206ImportReport report) {
1937
        NonViralNameParserImpl nvnpi = NonViralNameParserImpl.NewInstance();
1938
        NonViralName<?> taxonName = null;
1939
        boolean problem = false;
1940

    
1941
        if(DEBUG){
1942
            logger.info("parseScientificName " + state.getDataHolder().nomenclatureCode.toString());
1943
        }
1944

    
1945
        if (state.getDataHolder().nomenclatureCode.toString().equals("Zoological") || state.getDataHolder().nomenclatureCode.toString().contains("ICZN")) {
1946
            taxonName = nvnpi.parseFullName(scientificName, NomenclaturalCode.ICZN, null);
1947
            if (taxonName.hasProblem()) {
1948
                problem = true;
1949
            }
1950
        }
1951
        else if (state.getDataHolder().nomenclatureCode.toString().equals("Botanical") || state.getDataHolder().nomenclatureCode.toString().contains("ICBN")) {
1952
            taxonName = nvnpi.parseFullName(scientificName, NomenclaturalCode.ICNAFP, null);
1953
            if (taxonName.hasProblem()) {
1954
                problem = true;
1955
            }
1956
        }
1957
        else if (state.getDataHolder().nomenclatureCode.toString().equals("Bacterial") || state.getDataHolder().nomenclatureCode.toString().contains("ICBN")) {
1958
            taxonName = nvnpi.parseFullName(scientificName, NomenclaturalCode.ICNB, null);
1959
            if (taxonName.hasProblem()) {
1960
                problem = true;
1961
            }
1962
        }
1963
        else if (state.getDataHolder().nomenclatureCode.toString().equals("Cultivar") || state.getDataHolder().nomenclatureCode.toString().contains("ICNCP")) {
1964
            taxonName = nvnpi.parseFullName(scientificName, NomenclaturalCode.ICNCP, null);
1965
            if (taxonName.hasProblem()) {
1966
                problem = true;
1967
            }
1968
        }
1969
        if (problem) {
1970
            String message = String.format("Parsing problems for %s", scientificName);
1971
            if(taxonName!=null){
1972
                for (ParserProblem parserProblem : taxonName.getParsingProblems()) {
1973
                    message += "\n\t- "+parserProblem;
1974
                }
1975
            }
1976
            report.addInfoMessage(message);
1977
            logger.info(message);
1978
        }
1979
        return taxonName;
1980

    
1981
    }
1982

    
1983
    /**
1984
     * Create the name without automatic parsing, either because it failed, or because the user deactivated it.
1985
     * The name is built upon the ABCD fields
1986
     * @param atomisedMap : the ABCD atomised fields
1987
     * @param fullName : the full scientific name
1988
     * @param state
1989
     * @return the corresponding Botanical or Zoological or... name
1990
     */
1991
    private NonViralName<?> setTaxonNameByType(
1992
            HashMap<String, String> atomisedMap, String fullName, Abcd206ImportState state) {
1993
        boolean problem = false;
1994
        if(DEBUG) {
1995
            logger.info("settaxonnamebytype " + state.getDataHolder().nomenclatureCode.toString());
1996
        }
1997

    
1998
        if (state.getDataHolder().nomenclatureCode.equals("Zoological")) {
1999
            NonViralName<ZoologicalName> taxonName = ZoologicalName.NewInstance(null);
2000
            taxonName.setFullTitleCache(fullName, true);
2001
            taxonName.setGenusOrUninomial(NB(getFromMap(atomisedMap, "Genus")));
2002
            taxonName.setInfraGenericEpithet(NB(getFromMap(atomisedMap, "SubGenus")));
2003
            taxonName.setSpecificEpithet(NB(getFromMap(atomisedMap,"SpeciesEpithet")));
2004
            taxonName.setInfraSpecificEpithet(NB(getFromMap(atomisedMap,"SubspeciesEpithet")));
2005

    
2006
            if (taxonName.getGenusOrUninomial() != null){
2007
                taxonName.setRank(Rank.GENUS());
2008
            }
2009

    
2010
            if (taxonName.getInfraGenericEpithet() != null){
2011
                taxonName.setRank(Rank.SUBGENUS());
2012
            }
2013

    
2014
            if (taxonName.getSpecificEpithet() != null){
2015
                taxonName.setRank(Rank.SPECIES());
2016
            }
2017

    
2018
            if (taxonName.getInfraSpecificEpithet() != null){
2019
                taxonName.setRank(Rank.SUBSPECIES());
2020
            }
2021

    
2022
            Team team = null;
2023
            if (getFromMap(atomisedMap, "AuthorTeamParenthesis") != null) {
2024
                team = Team.NewInstance();
2025
                team.setTitleCache(getFromMap(atomisedMap, "AuthorTeamParenthesis"), true);
2026
            }
2027
            else {
2028
                if (getFromMap(atomisedMap, "AuthorTeamAndYear") != null) {
2029
                    team = Team.NewInstance();
2030
                    team.setTitleCache(getFromMap(atomisedMap, "AuthorTeamAndYear"), true);
2031
                }
2032
            }
2033
            if (team != null) {
2034
                taxonName.setBasionymAuthorship(team);
2035
            }
2036
            else {
2037
                if (getFromMap(atomisedMap, "AuthorTeamParenthesis") != null) {
2038
                    taxonName.setAuthorshipCache(getFromMap(atomisedMap, "AuthorTeamParenthesis"));
2039
                }
2040
                else if (getFromMap(atomisedMap, "AuthorTeamAndYear") != null) {
2041
                    taxonName.setAuthorshipCache(getFromMap(atomisedMap, "AuthorTeamAndYear"));
2042
                }
2043
            }
2044
            if (getFromMap(atomisedMap, "CombinationAuthorTeamAndYear") != null) {
2045
                team = Team.NewInstance();
2046
                team.setTitleCache(getFromMap(atomisedMap, "CombinationAuthorTeamAndYear"), true);
2047
                taxonName.setCombinationAuthorship(team);
2048
            }
2049
            if (taxonName.hasProblem()) {
2050
                logger.info("pb ICZN");
2051
                problem = true;
2052
            }
2053
            else {
2054
                return taxonName;
2055
            }
2056
        }
2057
        else if (state.getDataHolder().nomenclatureCode.equals("Botanical")) {
2058
            BotanicalName taxonName = (BotanicalName) parseScientificName(fullName, state, report);
2059
            if (taxonName != null){
2060
                return taxonName;
2061
            }
2062
            else{
2063
                taxonName = BotanicalName.NewInstance(null);
2064
            }
2065
            taxonName.setFullTitleCache(fullName, true);
2066
            taxonName.setGenusOrUninomial(NB(getFromMap(atomisedMap, "Genus")));
2067
            taxonName.setSpecificEpithet(NB(getFromMap(atomisedMap, "FirstEpithet")));
2068
            taxonName.setInfraSpecificEpithet(NB(getFromMap(atomisedMap, "InfraSpeEpithet")));
2069
            try {
2070
                taxonName.setRank(Rank.getRankByName(getFromMap(atomisedMap, "Rank")));
2071
            } catch (Exception e) {
2072
                if (taxonName.getInfraSpecificEpithet() != null){
2073
                    taxonName.setRank(Rank.SUBSPECIES());
2074
                }
2075
                else if (taxonName.getSpecificEpithet() != null){
2076
                    taxonName.setRank(Rank.SPECIES());
2077
                }
2078
                else if (taxonName.getInfraGenericEpithet() != null){
2079
                    taxonName.setRank(Rank.SUBGENUS());
2080
                }
2081
                else if (taxonName.getGenusOrUninomial() != null){
2082
                    taxonName.setRank(Rank.GENUS());
2083
                }
2084
            }
2085
            Team team = null;
2086
            if (getFromMap(atomisedMap, "AuthorTeamParenthesis") != null) {
2087
                team = Team.NewInstance();
2088
                team.setTitleCache(getFromMap(atomisedMap, "AuthorTeamParenthesis"), true);
2089
                taxonName.setBasionymAuthorship(team);
2090
            }
2091
            if (getFromMap(atomisedMap, "AuthorTeam") != null) {
2092
                team = Team.NewInstance();
2093
                team.setTitleCache(getFromMap(atomisedMap, "AuthorTeam"), true);
2094
                taxonName.setCombinationAuthorship(team);
2095
            }
2096
            if (team == null) {
2097
                if (getFromMap(atomisedMap, "AuthorTeamParenthesis") != null) {
2098
                    taxonName.setAuthorshipCache(getFromMap(atomisedMap, "AuthorTeamParenthesis"));
2099
                }
2100
                else if (getFromMap(atomisedMap, "AuthorTeam") != null) {
2101
                    taxonName.setAuthorshipCache(getFromMap(atomisedMap, "AuthorTeam"));
2102
                }
2103
            }
2104
            if (getFromMap(atomisedMap, "CombinationAuthorTeamAndYear") != null) {
2105
                team = Team.NewInstance();
2106
                team.setTitleCache(getFromMap(atomisedMap, "CombinationAuthorTeamAndYear"), true);
2107
                taxonName.setCombinationAuthorship(team);
2108
            }
2109
            if (taxonName.hasProblem()) {
2110
                logger.info("pb ICBN");
2111
                problem = true;
2112
            }
2113
            else {
2114
                return taxonName;
2115
            }
2116
        }
2117
        else if (state.getDataHolder().nomenclatureCode.equals("Bacterial")) {
2118
            NonViralName<BacterialName> taxonName = BacterialName.NewInstance(null);
2119
            taxonName.setFullTitleCache(fullName, true);
2120
            taxonName.setGenusOrUninomial(getFromMap(atomisedMap, "Genus"));
2121
            taxonName.setInfraGenericEpithet(NB(getFromMap(atomisedMap, "SubGenus")));
2122
            taxonName.setSpecificEpithet(NB(getFromMap(atomisedMap, "Species")));
2123
            taxonName.setInfraSpecificEpithet(NB(getFromMap(atomisedMap, "SubspeciesEpithet")));
2124

    
2125
            if (taxonName.getGenusOrUninomial() != null){
2126
                taxonName.setRank(Rank.GENUS());
2127
            }
2128
            else if (taxonName.getInfraGenericEpithet() != null){
2129
                taxonName.setRank(Rank.SUBGENUS());
2130
            }
2131
            else if (taxonName.getSpecificEpithet() != null){
2132
                taxonName.setRank(Rank.SPECIES());
2133
            }
2134
            else if (taxonName.getInfraSpecificEpithet() != null){
2135
                taxonName.setRank(Rank.SUBSPECIES());
2136
            }
2137

    
2138
            if (getFromMap(atomisedMap, "AuthorTeamAndYear") != null) {
2139
                Team team = Team.NewInstance();
2140
                team.setTitleCache(getFromMap(atomisedMap, "AuthorTeamAndYear"), true);
2141
                taxonName.setCombinationAuthorship(team);
2142
            }
2143
            if (getFromMap(atomisedMap, "ParentheticalAuthorTeamAndYear") != null) {
2144
                Team team = Team.NewInstance();
2145
                team.setTitleCache(getFromMap(atomisedMap, "ParentheticalAuthorTeamAndYear"), true);
2146
                taxonName.setBasionymAuthorship(team);
2147
            }
2148
            if (taxonName.hasProblem()) {
2149
                logger.info("pb ICNB");
2150
                problem = true;
2151
            }
2152
            else {
2153
                return taxonName;
2154
            }
2155
        }
2156
        else if (state.getDataHolder().nomenclatureCode.equals("Cultivar")) {
2157
            CultivarPlantName taxonName = CultivarPlantName.NewInstance(null);
2158

    
2159
            if (taxonName.hasProblem()) {
2160
                logger.info("pb ICNCP");
2161
                problem = true;
2162
            }
2163
            else {
2164
                return taxonName;
2165
            }
2166
            return taxonName;
2167
        }
2168

    
2169
        if (problem) {
2170
            logger.info("Problem im setTaxonNameByType ");
2171
            NonViralName<?> taxonName = NonViralName.NewInstance(null);
2172
            taxonName.setFullTitleCache(fullName, true);
2173
            return taxonName;
2174
        }
2175
        NonViralName<?> tn = NonViralName.NewInstance(null);
2176
        return tn;
2177
    }
2178

    
2179

    
2180
    /**
2181
     * Get a formated string from a hashmap
2182
     * @param atomisedMap
2183
     * @param key
2184
     * @return
2185
     */
2186
    private String getFromMap(HashMap<String, String> atomisedMap, String key) {
2187
        String value = null;
2188
        if (atomisedMap.containsKey(key)) {
2189
            value = atomisedMap.get(key);
2190
        }
2191

    
2192
        try {
2193
            if (value != null && key.matches(".*Year.*")) {
2194
                value = value.trim();
2195
                if (value.matches("[a-z A-Z ]*[0-9]{4}$")) {
2196
                    String tmp = value.split("[0-9]{4}$")[0];
2197
                    int year = Integer.parseInt(value.split(tmp)[1]);
2198
                    if (year >= 1752) {
2199
                        value = tmp;
2200
                    }
2201
                    else {
2202
                        value = null;
2203
                    }
2204
                }
2205
                else {
2206
                    value = null;
2207
                }
2208
            }
2209
        }
2210
        catch (Exception e) {
2211
            value = null;
2212
        }
2213
        return value;
2214
    }
2215

    
2216
    //    private void compareABCDtoCDM(URI urlFileName, List<String> knownElts, Abcd206XMLFieldGetter abcdFieldGetter) {
2217
    //        try {
2218
    //            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
2219
    //            DocumentBuilder constructeur = factory.newDocumentBuilder();
2220
    //            URL url = urlFileName.toURL();
2221
    //            Object o = url.getContent();
2222
    //            InputStream is = (InputStream) o;
2223
    //            Document document = constructeur.parse(is);
2224
    //            Element root = document.getDocumentElement();
2225
    //            abcdFieldGetter.traverse(root);
2226
    //        }
2227
    //        catch (ParserConfigurationException e){
2228
    //            e.printStackTrace();
2229
    //        }
2230
    //        catch (SAXException e) {
2231
    //            e.printStackTrace();
2232
    //        }
2233
    //        catch (IOException e) {
2234
    //            e.printStackTrace();
2235
    //        }
2236
    //        Set<String> elts = state.getDataHolder().allABCDelements.keySet();
2237
    //        Iterator<String> it = elts.iterator();
2238
    //        String elt;
2239
    //        while (it.hasNext()) {
2240
    //            elt = it.next();
2241
    //            if (knownElts.indexOf(elt) == -1) {
2242
    //                if(DEBUG) {
2243
    //                    logger.info("Unmerged ABCD element: " + elt + " - "+ state.getDataHolder().allABCDelements.get(elt));
2244
    //                }
2245
    //            }
2246
    //        }
2247
    //    }
2248

    
2249
    /**
2250
     * Load the list of names from the ABCD file and save them
2251
     * @param state : the current ABCD import state
2252
     * @param unitsList : the unit list from the ABCD file
2253
     * @param abcdFieldGetter : the ABCD parser
2254
     */
2255
    private void prepareCollectors(Abcd206ImportState state, NodeList unitsList, Abcd206XMLFieldGetter abcdFieldGetter) {
2256
        List<String> collectors = new ArrayList<String>();
2257
        List<String> teams = new ArrayList<String>();
2258
        List<List<String>> collectorinteams = new ArrayList<List<String>>();
2259

    
2260
        for (int i = 0; i < unitsList.getLength(); i++) {
2261
            this.getCollectorsFromXML((Element) unitsList.item(i), abcdFieldGetter, state);
2262
            for (String agent : state.getDataHolder().gatheringAgentList) {
2263
                collectors.add(agent);
2264
            }
2265
            List<String> tmpTeam = new ArrayList<String>(new HashSet<String>(state.getDataHolder().gatheringTeamList));
2266
            if(!tmpTeam.isEmpty()) {
2267
                teams.add(StringUtils.join(tmpTeam.toArray()," & "));
2268
            }
2269
            for (String agent:tmpTeam) {
2270
                collectors.add(agent);
2271
            }
2272
        }
2273

    
2274
        List<String> collectorsU = new ArrayList<String>(new HashSet<String>(collectors));
2275
        List<String> teamsU = new ArrayList<String>(new HashSet<String>(teams));
2276

    
2277

    
2278
        //existing teams in DB
2279
        Map<String,Team> titleCacheTeam = new HashMap<String, Team>();
2280
        List<UuidAndTitleCache<Team>> hiberTeam = getAgentService().getTeamUuidAndTitleCache();
2281

    
2282
        Set<UUID> uuids = new HashSet<UUID>();
2283
        for (UuidAndTitleCache<Team> hibernateT:hiberTeam){
2284
            uuids.add(hibernateT.getUuid());
2285
        }
2286
        if (!uuids.isEmpty()){
2287
            List<AgentBase> existingTeams = getAgentService().find(uuids);
2288
            for (AgentBase<?> existingP:existingTeams){
2289
                titleCacheTeam.put(existingP.getTitleCache(),CdmBase.deproxy(existingP,Team.class));
2290
            }
2291
        }
2292

    
2293

    
2294
        Map<String,UUID> teamMap = new HashMap<String, UUID>();
2295
        for (UuidAndTitleCache<Team> uuidt:hiberTeam){
2296
            teamMap.put(uuidt.getTitleCache(), uuidt.getUuid());
2297
        }
2298

    
2299
        //existing persons in DB
2300
        List<UuidAndTitleCache<Person>> hiberPersons = getAgentService().getPersonUuidAndTitleCache();
2301
        Map<String,Person> titleCachePerson = new HashMap<String, Person>();
2302
        uuids = new HashSet<UUID>();
2303
        for (UuidAndTitleCache<Person> hibernateP:hiberPersons){
2304
            uuids.add(hibernateP.getUuid());
2305
        }
2306

    
2307
        if (!uuids.isEmpty()){
2308
            List<AgentBase> existingPersons = getAgentService().find(uuids);
2309
            for (AgentBase<?> existingP:existingPersons){
2310
                titleCachePerson.put(existingP.getTitleCache(),CdmBase.deproxy(existingP,Person.class));
2311
            }
2312
        }
2313

    
2314
        Map<String,UUID> personMap = new HashMap<String, UUID>();
2315
        for (UuidAndTitleCache<Person> person:hiberPersons){
2316
            personMap.put(person.getTitleCache(), person.getUuid());
2317
        }
2318

    
2319
        java.util.Collection<Person> personToadd = new ArrayList<Person>();
2320
        java.util.Collection<Team> teamToAdd = new ArrayList<Team>();
2321

    
2322
        for (String collector:collectorsU){
2323
            Person p = Person.NewInstance();
2324
            p.setTitleCache(collector,true);
2325
            if (!personMap.containsKey(p.getTitleCache())){
2326
                personToadd.add(p);
2327
            }
2328
        }
2329
        for (String team:teamsU){
2330
            Team p = Team.NewInstance();
2331
            p.setTitleCache(team,true);
2332
            if (!teamMap.containsKey(p.getTitleCache())){
2333
                teamToAdd.add(p);
2334
            }
2335
        }
2336

    
2337
        if(!personToadd.isEmpty()){
2338
            for (Person agent: personToadd){
2339
                save(agent, state);
2340
                titleCachePerson.put(agent.getTitleCache(),CdmBase.deproxy(agent, Person.class) );
2341
            }
2342
        }
2343

    
2344
        Person ptmp ;
2345
        Map <String,Integer>teamdone = new HashMap<String, Integer>();
2346
        for (List<String> collteam: collectorinteams){
2347
            if (!teamdone.containsKey(StringUtils.join(collteam.toArray(),"-"))){
2348
                Team team = new Team();
2349
                boolean em =true;
2350
                for (String collector:collteam){
2351
                    ptmp = Person.NewInstance();
2352
                    ptmp.setTitleCache(collector,true);
2353
                    Person p2 = titleCachePerson.get(ptmp.getTitleCache());
2354
                    team.addTeamMember(p2);
2355
                    em=false;
2356
                }
2357
                if (!em) {
2358
                    teamToAdd.add(team);
2359
                }
2360
                teamdone.put(StringUtils.join(collteam.toArray(),"-"),0);
2361
            }
2362
        }
2363

    
2364
        if(!teamToAdd.isEmpty()){
2365
            for (Team agent: teamToAdd){
2366
                save(agent, state);
2367
                titleCacheTeam.put(agent.getTitleCache(), CdmBase.deproxy( agent,Team.class) );
2368
            }
2369
        }
2370

    
2371
        state.getConfig().setTeams(titleCacheTeam);
2372
        state.getConfig().setPersons(titleCachePerson);
2373
    }
2374

    
2375
    @Override
2376
    protected boolean isIgnore(Abcd206ImportState state) {
2377
        return false;
2378
    }
2379

    
2380
    @Override
2381
    public byte[] getByteArray() {
2382
        ByteArrayOutputStream importStream = new ByteArrayOutputStream();
2383
        report.printReport(new PrintStream(importStream));
2384
        return importStream.toByteArray();
2385
    }
2386

    
2387
}
(2-2/12)