Project

General

Profile

Download (99 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.InputStream;
13
import java.net.MalformedURLException;
14
import java.util.ArrayList;
15
import java.util.HashMap;
16
import java.util.HashSet;
17
import java.util.List;
18
import java.util.Map;
19
import java.util.Set;
20
import java.util.UUID;
21

    
22
import javax.xml.parsers.DocumentBuilder;
23
import javax.xml.parsers.DocumentBuilderFactory;
24

    
25
import org.apache.commons.lang.StringUtils;
26
import org.apache.log4j.Logger;
27
import org.springframework.stereotype.Component;
28
import org.w3c.dom.Document;
29
import org.w3c.dom.Element;
30
import org.w3c.dom.NodeList;
31

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

    
93
/**
94
 * @author p.kelbert
95
 * @created 20.10.2008
96
 */
97
@Component
98
public class Abcd206Import extends SpecimenImportBase<Abcd206ImportConfigurator, Abcd206ImportState> {
99
    private static final String DEFAULT_CLASSIFICATION_ABCD = "Default Classification ABCD";
100

    
101
    private static final Logger logger = Logger.getLogger(Abcd206Import.class);
102

    
103
    private final boolean DEBUG = true;
104

    
105
    private static final String COLON = ":";
106
    private static String prefix = "";
107

    
108
    private Abcd206ImportReport report;
109

    
110
    public Abcd206Import() {
111
        super();
112
    }
113

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

    
120

    
121
    @Override
122
    @SuppressWarnings("rawtypes")
123
    public void doInvoke(Abcd206ImportState state) {
124
        report = new Abcd206ImportReport();
125
        ICdmApplicationConfiguration cdmAppController = state.getCdmRepository()!=null?state.getCdmRepository():this;
126

    
127
        state.setTx(startTransaction());
128
        logger.info("INVOKE Specimen Import from ABCD2.06 XML ");
129

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

    
132
        List<Reference> references = getReferenceService().list(Reference.class, null, null, null, null);
133

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

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

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

    
217
        InputStream source = state.getConfig().getSource();
218
        NodeList unitsList = getUnitsNodeList(source);
219

    
220
        if (unitsList != null) {
221
            String message = "nb units to insert: " + unitsList.getLength();
222
            logger.info(message);
223
            updateProgress(state, message);
224
            state.getConfig().getProgressMonitor().beginTask("Importing ABCD file", unitsList.getLength());
225

    
226
            state.setDataHolder(new Abcd206DataHolder());
227
            state.getDataHolder().reset();
228

    
229
            Abcd206XMLFieldGetter abcdFieldGetter = new Abcd206XMLFieldGetter(state.getDataHolder(), prefix);
230

    
231
            prepareCollectors(state, unitsList, abcdFieldGetter);
232

    
233
            state.setAssociationRefs(new ArrayList<OriginalSourceBase<?>>());
234
            state.setDescriptionRefs(new ArrayList<OriginalSourceBase<?>>());
235
            state.setDerivedUnitSources(new ArrayList<OriginalSourceBase<?>>());
236

    
237
            for (int i = 0; i < unitsList.getLength(); i++) {
238
                if(state.getConfig().getProgressMonitor().isCanceled()){
239
                    break;
240
                }
241
                Element item = (Element) unitsList.item(i);
242
                this.setUnitPropertiesXML( item, abcdFieldGetter, state);
243
                updateProgress(state, "Importing data for unit "+state.getDataHolder().unitID+" ("+i+"/"+unitsList.getLength()+")");
244

    
245
//                //check if unit is associated to a specimen
246
//                SpecimenOrObservationBase<?> existingAssociatedSpecimen = null;
247
//                if(state.getDataHolder().associatedUnitIds.size()==1){
248
//                    String unitId = state.getDataHolder().associatedUnitIds.iterator().next();
249
//                    existingAssociatedSpecimen = findExistingSpecimen(unitId, state);
250
//                }
251
//                else{
252
//                    logger.warn("More than one associated unit found this unit!");
253
//                }
254
//                if(existingAssociatedSpecimen!=null && existingAssociatedSpecimen.isInstanceOf(DerivedUnit.class)){
255
//                    state.setDerivedUnitBase(HibernateProxyHelper.deproxy(existingAssociatedSpecimen, DerivedUnit.class));
256
//                    DerivedUnitFacade facade;
257
//                    try {
258
//                        facade = DerivedUnitFacade.NewInstance(state.getDerivedUnitBase());
259
//                        state.setFieldUnit(facade.getFieldUnit(true));
260
//                    } catch (DerivedUnitFacadeNotSupportedException e) {
261
//                        e.printStackTrace();
262
//                    }
263
//                }
264

    
265
                // import DNA unit
266
                if(state.getDataHolder().kindOfUnit!=null && state.getDataHolder().kindOfUnit.equalsIgnoreCase("dna")){
267
                    AbcdDnaParser dnaParser = new AbcdDnaParser(prefix, report, cdmAppController);
268
                    //parent field unit
269
                    FieldUnit fieldUnit = FieldUnit.NewInstance();
270
                    state.setFieldUnit(fieldUnit);
271
                    DnaSample dnaSample = dnaParser.parse(item, state);
272
                    save(dnaSample, state);
273
                    //set dna as derived unit to avoid creating an extra specimen for this dna sample (instead just the field unit will be created)
274
                    state.setDerivedUnitBase(dnaSample);
275
                    report.addDerivate(AbcdImportUtility.getUnitID(state.getDerivedUnitBase(), state.getConfig()), state.getDerivedUnitBase(), state.getDataHolder().unitID, dnaSample);
276
                }
277

    
278
                //import default unit + field unit data
279
                this.handleSingleUnit(state);
280

    
281
                //import associated units
282
                NodeList unitAssociationsList = item.getElementsByTagName(prefix+"UnitAssociations");
283
                if(unitAssociationsList.getLength()==1 && unitAssociationsList.item(0) instanceof Element){
284
                    UnitAssociationParser unitAssociationParser = new UnitAssociationParser(prefix, report, cdmAppController);
285
                    unitAssociationParser.parse((Element)unitAssociationsList.item(0), state);
286
                }
287

    
288
                state.reset();
289
            }
290
            if(state.getConfig().isDeduplicateReferences()){
291
                getReferenceService().deduplicate(Reference.class, null, null);
292
            }
293
            if(state.getConfig().isDeduplicateClassifications()){
294
                getClassificationService().deduplicate(Classification.class, null, null);
295
            }
296
        }
297
        commitTransaction(state.getTx());
298
        report.printReport(state.getConfig().getReportUri());
299
        return;
300
    }
301

    
302
    /**
303
     * Return the list of root nodes for an ABCD 2.06 XML file
304
     * @param fileName: the file's location
305
     * @return the list of root nodes ("Unit")
306
     */
307
    protected NodeList getUnitsNodeList(InputStream inputStream) {
308
        NodeList unitList = null;
309
        try {
310
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
311
            DocumentBuilder builder = factory.newDocumentBuilder();
312

    
313
            Document document = builder.parse(inputStream);
314
            Element root = document.getDocumentElement();
315
            unitList = root.getElementsByTagName("Unit");
316
            if (unitList.getLength() == 0) {
317
                unitList = root.getElementsByTagName("abcd:Unit");
318
                prefix = "abcd:";
319
            }
320
            if (unitList.getLength() == 0) {
321
                unitList = root.getElementsByTagName("abcd21:Unit");
322
                prefix = "abcd21:";
323
            }
324
        } catch (Exception e) {
325
            logger.warn(e);
326
        }
327
        return unitList;
328
    }
329

    
330
    /**
331
     * Handle a single unit
332
     * @param state
333
     */
334
    @SuppressWarnings("rawtypes")
335
    private void handleSingleUnit(Abcd206ImportState state) {
336
        if (DEBUG) {
337
            logger.info("handleSingleUnit "+state.getRef());
338
        }
339
        try {
340
            ICdmApplicationConfiguration cdmAppController = state.getConfig().getCdmAppController();
341
            if(cdmAppController==null){
342
                cdmAppController = this;
343
            }
344
            //check if unit already exists
345
            DerivedUnitFacade derivedUnitFacade = null;
346
            if(state.getConfig().isIgnoreImportOfExistingSpecimens()){
347
                SpecimenOrObservationBase<?> existingSpecimen = findExistingSpecimen(state.getDataHolder().unitID, state);
348
                if(existingSpecimen!=null && existingSpecimen.isInstanceOf(DerivedUnit.class)){
349
                    state.setDerivedUnitBase(HibernateProxyHelper.deproxy(existingSpecimen, DerivedUnit.class));
350
                    return;
351
                }
352
                // create facade
353
                if(state.getDerivedUnitBase()==null){
354
                    derivedUnitFacade = getFacade(state);
355
                    state.setDerivedUnitBase(derivedUnitFacade.innerDerivedUnit());
356
                }
357
                else{
358
                    derivedUnitFacade = DerivedUnitFacade.NewInstance(state.getDerivedUnitBase());
359
                }
360
            }
361
            // TODO: implement overwrite/merge specimen
362
//            else if(state.getConfig().isOverwriteExistingSpecimens()){
363
//                Pager<SpecimenOrObservationBase> existingSpecimens = cdmAppController.getOccurrenceService().findByTitle(config);
364
//                if(!existingSpecimens.getRecords().isEmpty()){
365
//                    derivedUnitFacade = DerivedUnitFacade.NewInstance(derivedUnit);
366
//                    derivedUnitBase = derivedUnitFacade.innerDerivedUnit();
367
//                    fieldUnit = derivedUnitFacade.getFieldUnit(true);
368
//                }
369
//            }
370
            else{
371
                // create facade
372
                if(state.getDerivedUnitBase()==null){
373
                    derivedUnitFacade = getFacade(state);
374
                    state.setDerivedUnitBase(derivedUnitFacade.innerDerivedUnit());
375
                }
376
                else{
377
                    derivedUnitFacade = DerivedUnitFacade.NewInstance(state.getDerivedUnitBase());
378
                }
379
            }
380

    
381
            /**
382
             * GATHERING EVENT
383
             */
384
            // gathering event
385
            UnitsGatheringEvent unitsGatheringEvent = new UnitsGatheringEvent(cdmAppController.getTermService(),
386
                    state.getDataHolder().locality, state.getDataHolder().languageIso, state.getDataHolder().longitude, state.getDataHolder().latitude,
387
                    state.getDataHolder().gatheringElevationText, state.getDataHolder().gatheringElevationMin,
388
                    state.getDataHolder().gatheringElevationMax, state.getDataHolder().gatheringElevationUnit, state.getDataHolder().gatheringDateText,
389
                    state.getDataHolder().gatheringAgentList, state.getDataHolder().gatheringTeamList, state.getConfig());
390

    
391
            // country
392
            UnitsGatheringArea unitsGatheringArea = new UnitsGatheringArea();
393
            //  unitsGatheringArea.setConfig(state.getConfig(),getOccurrenceService(), getTermService());
394
            unitsGatheringArea.setParams(state.getDataHolder().isocountry, state.getDataHolder().country, state.getConfig(), cdmAppController.getTermService(), cdmAppController.getOccurrenceService());
395

    
396
            DefinedTermBase<?> areaCountry =  unitsGatheringArea.getCountry();
397

    
398
            // other areas
399
            unitsGatheringArea = new UnitsGatheringArea();
400
            //            unitsGatheringArea.setConfig(state.getConfig(),getOccurrenceService(),getTermService());
401
            unitsGatheringArea.setAreas(state.getDataHolder().namedAreaList,state.getConfig(), cdmAppController.getTermService(), cdmAppController.getVocabularyService());
402
            ArrayList<DefinedTermBase> nas = unitsGatheringArea.getAreas();
403
            for (DefinedTermBase namedArea : nas) {
404
                unitsGatheringEvent.addArea(namedArea);
405
            }
406

    
407
            // copy gathering event to facade
408
            GatheringEvent gatheringEvent = unitsGatheringEvent.getGatheringEvent();
409
            derivedUnitFacade.setLocality(gatheringEvent.getLocality());
410
            derivedUnitFacade.setExactLocation(gatheringEvent.getExactLocation());
411
            derivedUnitFacade.setCollector(gatheringEvent.getCollector());
412
            derivedUnitFacade.setCountry((NamedArea)areaCountry);
413
            derivedUnitFacade.setAbsoluteElevationText(gatheringEvent.getAbsoluteElevationText());
414
            derivedUnitFacade.setAbsoluteElevation(gatheringEvent.getAbsoluteElevation());
415
            derivedUnitFacade.setAbsoluteElevationMax(gatheringEvent.getAbsoluteElevationMax());
416
            derivedUnitFacade.setGatheringPeriod(gatheringEvent.getTimeperiod());
417

    
418
            for(DefinedTermBase<?> area:unitsGatheringArea.getAreas()){
419
                derivedUnitFacade.addCollectingArea((NamedArea) area);
420
            }
421
            //            derivedUnitFacade.addCollectingAreas(unitsGatheringArea.getAreas());
422
            // TODO exsiccatum
423

    
424
            // add fieldNumber
425
            derivedUnitFacade.setFieldNumber(NB(state.getDataHolder().fieldNumber));
426

    
427
            // //add Multimedia URLs
428
            if (state.getDataHolder().multimediaObjects.size() != -1) {
429
                for (String multimediaObject : state.getDataHolder().multimediaObjects) {
430
                    Media media;
431
                    try {
432
                        media = getImageMedia(multimediaObject, READ_MEDIA_DATA);
433
                        derivedUnitFacade.addDerivedUnitMedia(media);
434
                        if(state.getConfig().isAddMediaAsMediaSpecimen()){
435
                            //add media also as specimen scan
436
                            MediaSpecimen mediaSpecimen = MediaSpecimen.NewInstance(SpecimenOrObservationType.Media);
437
                            mediaSpecimen.setMediaSpecimen(media);
438
                            DefinedTermBase specimenScanTerm = getTermService().load(UUID.fromString("acda15be-c0e2-4ea8-8783-b9b0c4ad7f03"));
439
                            if(specimenScanTerm instanceof DefinedTerm){
440
                                mediaSpecimen.setKindOfUnit((DefinedTerm) specimenScanTerm);
441
                            }
442
                            DerivationEvent derivationEvent = DerivationEvent.NewInstance(DerivationEventType.PREPARATION());
443
                            derivationEvent.addDerivative(mediaSpecimen);
444
                            derivedUnitFacade.innerDerivedUnit().addDerivationEvent(derivationEvent);
445
                        }
446

    
447
                    } catch (MalformedURLException e) {
448
                        // TODO Auto-generated catch block
449
                        e.printStackTrace();
450
                    }
451

    
452
                }
453
            }
454

    
455
            //			/*
456
            //			 * merge AND STORE DATA
457
            //			 */
458
            //			getTermService().saveOrUpdate(areaCountry);// TODO save area sooner
459
            //
460
            //			for (NamedArea area : otherAreas) {
461
            //				getTermService().saveOrUpdate(area);// merge it sooner (foreach area)
462
            //			}
463

    
464
            save(unitsGatheringEvent.getLocality(), state);
465

    
466
            // handle collection data
467
            setCollectionData(state, derivedUnitFacade);
468

    
469
            //Reference stuff
470
            SpecimenUserInteraction sui = state.getConfig().getSpecimenUserInteraction();
471
            Map<String,OriginalSourceBase<?>> sourceMap = new HashMap<String, OriginalSourceBase<?>>();
472

    
473
            state.getDataHolder().docSources = new ArrayList<String>();
474
            for (String[] fullReference : state.getDataHolder().referenceList) {
475
                String strReference=fullReference[0];
476
                String citationDetail = fullReference[1];
477
                String citationURL = fullReference[2];
478

    
479
                if (!citationURL.isEmpty()) {
480
                    citationDetail+=", "+citationURL;
481
                }
482

    
483
                Reference<?> reference;
484
                if(strReference.equals(state.getRef().getTitleCache())){
485
                    reference = state.getRef();
486
                }
487
                else{
488
                    reference = ReferenceFactory.newGeneric();
489
                    reference.setTitle(strReference);
490
                }
491

    
492
                IdentifiableSource sour = getIdentifiableSource(reference,citationDetail);
493

    
494
                try{
495
                    if (sour.getCitation() != null){
496
                        if(StringUtils.isNotBlank(sour.getCitationMicroReference())) {
497
                            state.getDataHolder().docSources.add(sour.getCitation().getTitleCache()+ "---"+sour.getCitationMicroReference());
498
                        } else {
499
                            state.getDataHolder().docSources.add(sour.getCitation().getTitleCache());
500
                        }
501
                    }
502
                }catch(Exception e){
503
                    logger.warn("oups");
504
                }
505
                reference.addSource(sour);
506
                save(reference, state);
507
            }
508

    
509
            List<IdentifiableSource> issTmp = getCommonService().list(IdentifiableSource.class, null, null, null, null);
510
            List<DescriptionElementSource> issTmp2 = getCommonService().list(DescriptionElementSource.class, null, null, null, null);
511

    
512
            Set<OriginalSourceBase> osbSet = new HashSet<OriginalSourceBase>();
513
            if(issTmp2!=null) {
514
                osbSet.addAll(issTmp2);
515
            }
516
            if(issTmp!=null) {
517
                osbSet.addAll(issTmp);
518
            }
519

    
520
            addToSourceMap(sourceMap, osbSet);
521

    
522
            if( state.getConfig().isInteractWithUser()){
523
                List<OriginalSourceBase<?>>sources=null;
524
                if(!state.isDerivedUnitSourcesSet()){
525
                    sources= sui.askForSource(sourceMap, "the unit itself","",getReferenceService(), state.getDataHolder().docSources);
526
                    state.setDerivedUnitSources(sources);
527
                    state.setDerivedUnitSourcesSet(true);
528
                }
529
                else{
530
                    sources=state.getDerivedUnitSources();
531
                }
532
//                System.out.println("nb sources: "+sources.size());
533
//                System.out.println("derivedunitfacade : "+derivedUnitFacade.getTitleCache());
534
                for (OriginalSourceBase<?> sour:sources){
535
                    if(sour.isInstanceOf(IdentifiableSource.class)){
536
                        if(sourceNotLinkedToElement(derivedUnitFacade,sour)) {
537
//                            System.out.println("add source to derivedunitfacade1 "+derivedUnitFacade.getTitleCache());
538
                            derivedUnitFacade.addSource((IdentifiableSource)sour.clone());
539
                        }
540
                    }else{
541
                        if(sourceNotLinkedToElement(derivedUnitFacade,sour)) {
542
//                            System.out.println("add source to derivedunitfacade2 "+derivedUnitFacade.getTitleCache());
543
                            derivedUnitFacade.addSource(OriginalSourceType.Import,sour.getCitation(),sour.getCitationMicroReference(), ioName);
544
                        }
545
                    }
546
                }
547
            }else{
548
                for (OriginalSourceBase<?> sr : sourceMap.values()){
549
                    if(sr.isInstanceOf(IdentifiableSource.class)){
550
                        if(sourceNotLinkedToElement(derivedUnitFacade,sr)) {
551
//                            System.out.println("add source to derivedunitfacade3 "+derivedUnitFacade.getTitleCache());
552
                            derivedUnitFacade.addSource((IdentifiableSource)sr.clone());
553
                        }
554
                    }else{
555
                        if(sourceNotLinkedToElement(derivedUnitFacade,sr)) {
556
//                            System.out.println("add source to derivedunitfacade4 "+derivedUnitFacade.getTitleCache());
557
                            derivedUnitFacade.addSource(OriginalSourceType.Import,sr.getCitation(),sr.getCitationMicroReference(), ioName);
558
                        }
559
                    }
560
                }
561
            }
562

    
563
            save(state.getDerivedUnitBase(), state);
564

    
565
            // handle identifications
566
            handleIdentifications(state, derivedUnitFacade);
567

    
568
            if(DEBUG) {
569
                logger.info("saved ABCD specimen ...");
570
            }
571

    
572
        } catch (Exception e) {
573
            logger.warn("Error when reading record!!");
574
            e.printStackTrace();
575
            state.setUnsuccessfull();
576
        }
577

    
578
        return;
579
    }
580

    
581
    private SpecimenOrObservationBase findExistingSpecimen(String unitId, Abcd206ImportState state){
582
        ICdmApplicationConfiguration cdmAppController = state.getConfig().getCdmAppController();
583
        if(cdmAppController==null){
584
            cdmAppController = this;
585
        }
586
        FindOccurrencesConfigurator config = new FindOccurrencesConfigurator();
587
        config.setSignificantIdentifier(unitId);
588
        Pager<SpecimenOrObservationBase> existingSpecimens = cdmAppController.getOccurrenceService().findByTitle(config);
589
        if(!existingSpecimens.getRecords().isEmpty()){
590
            if(existingSpecimens.getRecords().size()==1){
591
                return existingSpecimens.getRecords().iterator().next();
592
            }
593
        }
594
        return null;
595
    }
596

    
597
    /**
598
     * @param sourceMap
599
     * @param osbSet
600
     */
601
    private void addToSourceMap(Map<String, OriginalSourceBase<?>> sourceMap, Set<OriginalSourceBase> osbSet) {
602
        for( OriginalSourceBase<?> osb:osbSet) {
603
            if(osb.getCitation()!=null && osb.getCitationMicroReference() !=null  && !osb.getCitationMicroReference().isEmpty()) {
604
                try{
605
                    sourceMap.put(osb.getCitation().getTitleCache()+ "---"+osb.getCitationMicroReference(),osb);
606
                }catch(NullPointerException e){logger.warn("null pointer problem (no ref?) with "+osb);}
607
            } else if(osb.getCitation()!=null){
608
                try{
609
                    sourceMap.put(osb.getCitation().getTitleCache(),osb);
610
                }catch(NullPointerException e){logger.warn("null pointer problem (no ref?) with "+osb);}
611
            }
612
        }
613
    }
614

    
615
    /**
616
     * @param derivedUnitFacade
617
     * @param sour
618
     * @return
619
     */
620
    private boolean sourceNotLinkedToElement(DerivedUnitFacade derivedUnitFacade, OriginalSourceBase<?> source) {
621
        Set<IdentifiableSource> linkedSources = derivedUnitFacade.getSources();
622
        for (IdentifiableSource is:linkedSources){
623
            if (is.getCitation()!=null && source.getCitation()!=null &&
624
                    is.getCitation().getTitleCache().equalsIgnoreCase(source.getCitation().getTitleCache())){
625
                String isDetail =  is.getCitationMicroReference();
626
                if ((StringUtils.isBlank(isDetail) && StringUtils.isBlank(source.getCitationMicroReference()))
627
                        || (isDetail != null && isDetail.equalsIgnoreCase(source.getCitationMicroReference())) ) {
628
                    return false;
629
                }
630
            }
631
        }
632
        return true;
633
    }
634

    
635
    /**
636
     * @param reference
637
     * @param citationDetail
638
     * @return
639
     */
640
    //FIXME this method is highly critical, because
641
    //  * it will have serious performance and memory problems with large databases
642
    //        (databases may easily have >1 Mio source records)
643
    //  * it does not make sense to search for existing sources and then clone them
644
    //    we need to search for existing references instead and use them (if exist)
645
    //    for our new source.
646
    private IdentifiableSource getIdentifiableSource(Reference<?> reference, String citationDetail) {
647

    
648
        List<IdentifiableSource> issTmp = getCommonService().list(IdentifiableSource.class, null, null, null, null);
649

    
650

    
651
        if (reference != null){
652
            try {
653
                for (OriginalSourceBase<?> osb: issTmp){
654
                    if (osb.getCitation() != null && osb.getCitation().getTitleCache().equalsIgnoreCase(reference.getTitleCache())){
655
                        String osbDetail = osb.getCitationMicroReference();
656
                        if ((StringUtils.isBlank(osbDetail) && StringUtils.isBlank(citationDetail))
657
                                || (osbDetail != null && osbDetail.equalsIgnoreCase(citationDetail)) ) {
658
//                            System.out.println("REFERENCE FOUND RETURN EXISTING SOURCE");
659
                            return (IdentifiableSource) osb.clone();
660
                        }
661
                    }
662
                }
663
            } catch (CloneNotSupportedException e) {
664
                throw new RuntimeException(e);
665
            } catch (Exception e1){
666
                e1.printStackTrace();
667
            }
668
        }
669

    
670
        IdentifiableSource sour = IdentifiableSource.NewInstance(OriginalSourceType.Import,null,null, reference,citationDetail);
671
        return sour;
672
    }
673

    
674
    //    /**
675
    //     * @param reference
676
    //     * @param citationDetail
677
    //     * @return
678
    //     */
679
    //    private DescriptionElementSource getDescriptionSource(Reference<?> reference, String citationDetail) {
680
    //
681
    //        List<OriginalSourceBase> issTmp2 = getCommonService().list(DescriptionElementSource.class, null, null, null, null);
682
    //
683
    //        try {
684
    //            for (OriginalSourceBase<?> osb:issTmp2){
685
    //                if (osb.getCitation().equals(reference) && osb.getCitationMicroReference().equalsIgnoreCase(citationDetail)) {
686
    //                    return (DescriptionElementSource) osb.clone();
687
    //                }
688
    //            }
689
    //        } catch (CloneNotSupportedException e) {
690
    //            // TODO Auto-generated catch block
691
    //            e.printStackTrace();
692
    //        }
693
    //
694
    //        DescriptionElementSource sour = DescriptionElementSource.NewInstance(OriginalSourceType.Import,null,null, reference,citationDetail);
695
    //        return sour;
696
    //    }
697

    
698

    
699
    /**
700
     * Very fast and dirty implementation to allow handling of transient objects as described in
701
     * https://dev.e-taxonomy.eu/trac/ticket/3726
702
     *
703
     * Not yet complete.
704
     *
705
     * @param cdmBase
706
     * @param state
707
     */
708
    private void save(CdmBase cdmBase, Abcd206ImportState state) {
709
        ICdmApplicationConfiguration cdmRepository = state.getConfig().getCdmAppController();
710
        if (cdmRepository == null){
711
            cdmRepository = this;
712
        }
713

    
714
        if (cdmBase.isInstanceOf(LanguageString.class)){
715
            cdmRepository.getTermService().saveLanguageData(CdmBase.deproxy(cdmBase, LanguageString.class));
716
        }else if (cdmBase.isInstanceOf(SpecimenOrObservationBase.class)){
717
            cdmRepository.getOccurrenceService().saveOrUpdate(CdmBase.deproxy(cdmBase, SpecimenOrObservationBase.class));
718
        }else if (cdmBase.isInstanceOf(Reference.class)){
719
            cdmRepository.getReferenceService().saveOrUpdate(CdmBase.deproxy(cdmBase, Reference.class));
720
        }else if (cdmBase.isInstanceOf(Classification.class)){
721
            cdmRepository.getClassificationService().saveOrUpdate(CdmBase.deproxy(cdmBase, Classification.class));
722
        }else if (cdmBase.isInstanceOf(AgentBase.class)){
723
            cdmRepository.getAgentService().saveOrUpdate(CdmBase.deproxy(cdmBase, AgentBase.class));
724
        }else if (cdmBase.isInstanceOf(Collection.class)){
725
            cdmRepository.getCollectionService().saveOrUpdate(CdmBase.deproxy(cdmBase, Collection.class));
726
        }else if (cdmBase.isInstanceOf(DescriptionBase.class)){
727
            cdmRepository.getDescriptionService().saveOrUpdate(CdmBase.deproxy(cdmBase, DescriptionBase.class));
728
        }else if (cdmBase.isInstanceOf(TaxonBase.class)){
729
            cdmRepository.getTaxonService().saveOrUpdate(CdmBase.deproxy(cdmBase, TaxonBase.class));
730
        }else if (cdmBase.isInstanceOf(TaxonNameBase.class)){
731
            cdmRepository.getNameService().saveOrUpdate(CdmBase.deproxy(cdmBase, TaxonNameBase.class));
732
        }else{
733
            throw new IllegalArgumentException("Class not supported in save method: " + CdmBase.deproxy(cdmBase, CdmBase.class).getClass().getSimpleName());
734
        }
735

    
736
    }
737

    
738
    /**
739
     * setCollectionData : store the collection object into the
740
     * derivedUnitFacade
741
     *
742
     * @param state
743
     */
744
    private void setCollectionData(Abcd206ImportState state, DerivedUnitFacade derivedUnitFacade) {
745
        Abcd206ImportConfigurator config = state.getConfig();
746
        AbcdImportUtility.setUnitID(derivedUnitFacade.innerDerivedUnit(), state.getDataHolder().unitID, config);
747
        if(!config.isMapUnitIdToAccessionNumber()){
748
            derivedUnitFacade.setAccessionNumber(NB(state.getDataHolder().accessionNumber));
749
        }
750
        // derivedUnitFacade.setCollectorsNumber(NB(state.getDataHolder().collectorsNumber));
751

    
752
        /*
753
         * INSTITUTION & COLLECTION
754
         */
755
        // manage institution
756
        Institution institution = this.getInstitution(NB(state.getDataHolder().institutionCode), state);
757
        // manage collection
758
        Collection collection = this.getCollection(institution, NB(state.getDataHolder().collectionCode), state);
759
        // link specimen & collection
760
        derivedUnitFacade.setCollection(collection);
761
    }
762

    
763
    /**
764
     * getFacade : get the DerivedUnitFacade based on the recordBasis
765
     * @param state
766
     *
767
     * @return DerivedUnitFacade
768
     */
769
    private DerivedUnitFacade getFacade(Abcd206ImportState state) {
770
        if(DEBUG) {
771
            logger.info("getFacade()");
772
        }
773
        SpecimenOrObservationType type = null;
774

    
775
        // create specimen
776
        if (NB((state.getDataHolder().recordBasis)) != null) {
777
            if (state.getDataHolder().recordBasis.toLowerCase().startsWith("s") || state.getDataHolder().recordBasis.toLowerCase().indexOf("specimen")>-1) {// specimen
778
                type = SpecimenOrObservationType.PreservedSpecimen;
779
            }
780
            if (state.getDataHolder().recordBasis.toLowerCase().startsWith("o") ||state.getDataHolder().recordBasis.toLowerCase().indexOf("observation")>-1 ) {
781
                type = SpecimenOrObservationType.Observation;
782
            }
783
            if (state.getDataHolder().recordBasis.toLowerCase().indexOf("fossil")>-1){
784
                type = SpecimenOrObservationType.Fossil;
785
            }
786
            if (state.getDataHolder().recordBasis.toLowerCase().indexOf("living")>-1) {
787
                type = SpecimenOrObservationType.LivingSpecimen;
788
            }
789
            if (type == null) {
790
                logger.info("The basis of record does not seem to be known: " + state.getDataHolder().recordBasis);
791
                type = SpecimenOrObservationType.DerivedUnit;
792
            }
793
            // TODO fossils?
794
        } else {
795
            logger.info("The basis of record is null");
796
            type = SpecimenOrObservationType.DerivedUnit;
797
        }
798
        DerivedUnitFacade derivedUnitFacade = DerivedUnitFacade.NewInstance(type);
799
        return derivedUnitFacade;
800
    }
801

    
802
    private void getCollectorsFromXML(Element root, Abcd206XMLFieldGetter abcdFieldGetter, Abcd206ImportState state) {
803
        NodeList group;
804

    
805
        group = root.getChildNodes();
806
        for (int i = 0; i < group.getLength(); i++) {
807
            if (group.item(i).getNodeName().equals(prefix + "Identifications")) {
808
                group = group.item(i).getChildNodes();
809
                break;
810
            }
811
        }
812
        state.getDataHolder().gatheringAgentList = new ArrayList<String>();
813
        state.getDataHolder().gatheringTeamList = new ArrayList<String>();
814
        abcdFieldGetter.getType(root);
815
        abcdFieldGetter.getGatheringPeople(root);
816
    }
817

    
818
    /**
819
     * Store the unit's properties into variables Look which unit is the
820
     * preferred one Look what kind of name it is supposed to be, for the
821
     * parsing (Botanical, Zoological)
822
     * @param state
823
     *
824
     * @param racine: the root node for a single unit
825
     */
826
    private void setUnitPropertiesXML(Element root, Abcd206XMLFieldGetter abcdFieldGetter, Abcd206ImportState state) {
827
        try {
828
            NodeList group;
829

    
830
            group = root.getChildNodes();
831
            for (int i = 0; i < group.getLength(); i++) {
832
                if (group.item(i).getNodeName().equals(prefix + "Identifications")) {
833
                    group = group.item(i).getChildNodes();
834
                    break;
835
                }
836
            }
837
            state.getDataHolder().identificationList = new ArrayList<Identification>();
838
            state.getDataHolder().statusList = new ArrayList<SpecimenTypeDesignationStatus>();
839
            state.getDataHolder().atomisedIdentificationList = new ArrayList<HashMap<String, String>>();
840
            state.getDataHolder().referenceList = new ArrayList<String[]>();
841
            state.getDataHolder().multimediaObjects = new ArrayList<String>();
842

    
843
            abcdFieldGetter.getScientificNames(group);
844
            abcdFieldGetter.getType(root);
845

    
846
            if(DEBUG) {
847
                logger.info("this.identificationList "+state.getDataHolder().identificationList.toString());
848
            }
849
            abcdFieldGetter.getIDs(root);
850
            abcdFieldGetter.getRecordBasis(root);
851
            abcdFieldGetter.getKindOfUnit(root);
852
            abcdFieldGetter.getMultimedia(root);
853
            abcdFieldGetter.getNumbers(root);
854
            abcdFieldGetter.getGeolocation(root, state);
855
            abcdFieldGetter.getGatheringPeople(root);
856
            abcdFieldGetter.getGatheringDate(root);
857
            abcdFieldGetter.getGatheringElevation(root);
858
            abcdFieldGetter.getAssociatedUnitIds(root);
859
            boolean referencefound = abcdFieldGetter.getReferences(root);
860
            if (!referencefound) {
861
                String[]a = {state.getRef().getTitleCache(),"",""};
862
                state.getDataHolder().referenceList.add(a);
863
            }
864

    
865
        } catch (Exception e) {
866
            logger.info("Error occured while parsing XML file" + e);
867
        }
868
    }
869

    
870
    /**
871
     * Look if the Institution does already exist
872
     * @param institutionCode: a string with the institutioncode
873
     * @param config : the configurator
874
     * @return the Institution (existing or new)
875
     */
876
    private Institution getInstitution(String institutionCode, Abcd206ImportState state) {
877
        Institution institution=null;
878
        List<Institution> institutions;
879
        try {
880
            institutions = getAgentService().list(Institution.class, null, null, null, null);
881
        } catch (Exception e) {
882
            institutions = new ArrayList<Institution>();
883
            logger.warn(e);
884
        }
885
        if (institutions.size() > 0 && state.getConfig().isReUseExistingMetadata()) {
886
            for (Institution institut:institutions){
887
                try{
888
                    if (institut.getCode().equalsIgnoreCase(institutionCode)) {
889
                        institution=institut;
890
                    }
891
                }catch(Exception e){logger.warn("no institution code in the db");}
892
            }
893
        }
894
        if(DEBUG) {
895
            if(institution !=null) {
896
                logger.info("getinstitution " + institution.toString());
897
            }
898
        }
899
        if (institution == null){
900
            // create institution
901
            institution = Institution.NewInstance();
902
            institution.setCode(institutionCode);
903
            institution.setTitleCache(institutionCode, true);
904
        }
905
        save(institution, state);
906
        return institution;
907
    }
908

    
909
    /**
910
     * Look if the Collection does already exist
911
     * @param collectionCode
912
     * @param collectionCode: a string
913
     * @param config : the configurator
914
     * @return the Collection (existing or new)
915
     */
916
    private Collection getCollection(Institution institution, String collectionCode, Abcd206ImportState state) {
917
        Collection collection = null;
918
        List<Collection> collections;
919
        try {
920
            collections = getCollectionService().list(Collection.class, null, null, null, null);
921
        } catch (Exception e) {
922
            collections = new ArrayList<Collection>();
923
        }
924
        if (collections.size() > 0 && state.getConfig().isReUseExistingMetadata()) {
925
            for (Collection coll:collections){
926
                if (coll.getInstitute() != null) {
927
                    if (coll.getCode().equalsIgnoreCase(collectionCode) && coll.getInstitute().equals(institution)) {
928
                        collection=coll;
929
                    }
930
                }
931
            }
932
        }
933

    
934
        if(collection == null){
935
            collection =Collection.NewInstance();
936
            collection.setCode(collectionCode);
937
            collection.setInstitute(institution);
938
            collection.setTitleCache(collectionCode);
939
        }
940
        save(collection, state);
941
        return collection;
942
    }
943

    
944

    
945
    /**
946
     * join DeterminationEvent to the Taxon Object
947
     * @param state : the ABCD import state
948
     * @param taxon: the current Taxon
949
     * @param preferredFlag :if the current name is preferred
950
     * @param derivedFacade : the derived Unit Facade
951
     */
952
    @SuppressWarnings("rawtypes")
953
    private void linkDeterminationEvent(Abcd206ImportState state, Taxon taxon, boolean preferredFlag,  DerivedUnitFacade derivedFacade) {
954
        Abcd206ImportConfigurator config = state.getConfig();
955
        if(DEBUG){
956
            logger.info("start linkdetermination with taxon:" + taxon.getUuid()+", "+taxon);
957
        }
958

    
959
        DeterminationEvent determinationEvent = DeterminationEvent.NewInstance();
960
        determinationEvent.setTaxonName(taxon.getName());
961
        determinationEvent.setPreferredFlag(preferredFlag);
962

    
963
        determinationEvent.setIdentifiedUnit(state.getDerivedUnitBase());
964
        state.getDerivedUnitBase().addDetermination(determinationEvent);
965

    
966
        if(DEBUG){
967
            logger.info("NB TYPES INFO: "+ state.getDataHolder().statusList.size());
968
        }
969
        for (SpecimenTypeDesignationStatus specimenTypeDesignationstatus : state.getDataHolder().statusList) {
970
            if (specimenTypeDesignationstatus != null) {
971
                if(DEBUG){
972
                    logger.info("specimenTypeDesignationstatus :"+ specimenTypeDesignationstatus);
973
                }
974

    
975
                ICdmApplicationConfiguration cdmAppController = config.getCdmAppController();
976
                if(cdmAppController == null){
977
                    cdmAppController = this;
978
                }
979
                specimenTypeDesignationstatus = (SpecimenTypeDesignationStatus) cdmAppController.getTermService().find(specimenTypeDesignationstatus.getUuid());
980
                //Designation
981
                TaxonNameBase<?,?> name = taxon.getName();
982
                SpecimenTypeDesignation designation = SpecimenTypeDesignation.NewInstance();
983

    
984
                designation.setTypeStatus(specimenTypeDesignationstatus);
985
                designation.setTypeSpecimen(state.getDerivedUnitBase());
986
                name.addTypeDesignation(designation, true);
987
            }
988
        }
989

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

    
993
            String strReference=fullReference[0];
994
            String citationDetail = fullReference[1];
995
            String citationURL = fullReference[2];
996

    
997
            if (isNotBlank(strReference)){
998
                Reference<?> reference = null;
999
                for (Reference<?> refe: references) {
1000
                    if (refe.getTitleCache().equalsIgnoreCase(strReference)) {
1001
                        reference =refe;
1002
                        break;
1003
                    }
1004
                }
1005
                if (reference ==null){
1006
                    reference = ReferenceFactory.newGeneric();
1007
                    reference.setTitleCache(strReference, true);
1008
                    save(reference, state);
1009
                }
1010
                determinationEvent.addReference(reference);
1011
            }
1012
        }
1013
        save(state.getDerivedUnitBase(), state);
1014

    
1015
        if (config.isAddIndividualsAssociationsSuchAsSpecimenAndObservations() && preferredFlag) {
1016
            //do not add IndividualsAssociation to non-preferred taxa
1017
            if(DEBUG){
1018
                logger.info("isDoCreateIndividualsAssociations");
1019
            }
1020

    
1021
            makeIndividualsAssociation(state, taxon, determinationEvent);
1022

    
1023
            if(state.getConfig().isDeterminationOnFieldUnitLevel()){
1024
                DeterminationEvent fieldUnitDeterminationEvent = DeterminationEvent.NewInstance();
1025
                fieldUnitDeterminationEvent.setTaxonName(determinationEvent.getTaxonName());
1026
                fieldUnitDeterminationEvent.setPreferredFlag(determinationEvent.getPreferredFlag());
1027
                fieldUnitDeterminationEvent.setIdentifiedUnit(state.getFieldUnit());
1028
                Set<Reference> references = determinationEvent.getReferences();
1029
                for (Reference reference : references) {
1030
                    fieldUnitDeterminationEvent.addReference(reference);
1031
                }
1032
                state.getFieldUnit().addDetermination(fieldUnitDeterminationEvent);
1033
            }
1034

    
1035
            save(state.getDerivedUnitBase(), state);
1036
        }
1037
    }
1038

    
1039
    /**
1040
     * create and link each association (specimen, observation..) to the accepted taxon
1041
     * @param state : the ABCD import state
1042
     * @param taxon: the current Taxon
1043
     * @param determinationEvent:the determinationevent
1044
     */
1045
    private void makeIndividualsAssociation(Abcd206ImportState state, Taxon taxon, DeterminationEvent determinationEvent) {
1046
        SpecimenUserInteraction sui = state.getConfig().getSpecimenUserInteraction();
1047

    
1048
        if (DEBUG) {
1049
            logger.info("MAKE INDIVIDUALS ASSOCIATION");
1050
        }
1051

    
1052
        TaxonDescription taxonDescription = null;
1053
        Set<TaxonDescription> descriptions= taxon.getDescriptions();
1054
        if (state.getConfig().isInteractWithUser()){
1055
            if(!state.isDescriptionGroupSet()){
1056
                taxonDescription = sui.askForDescriptionGroup(descriptions);
1057
                state.setDescriptionGroup(taxonDescription);
1058
                state.setDescriptionGroupSet(true);
1059
            }else{
1060
                taxonDescription=state.getDescriptionGroup();
1061
            }
1062
        } else {
1063
            for (TaxonDescription description : descriptions){
1064
                Set<IdentifiableSource> sources =  description.getTaxon().getSources();
1065
                sources.addAll(description.getSources());
1066
                for (IdentifiableSource source:sources){
1067
                    if(state.getRef().equals(source.getCitation())) {
1068
                        taxonDescription = description;
1069
                    }
1070
                }
1071
            }
1072
        }
1073
        if (taxonDescription == null){
1074
            taxonDescription = TaxonDescription.NewInstance(taxon, false);
1075
            if(sourceNotLinkedToElement(taxonDescription,state.getRef(),null)) {
1076
                taxonDescription.addSource(OriginalSourceType.Import, null, null, state.getRef(), null);
1077
            }
1078
            state.setDescriptionGroup(taxonDescription);
1079
            taxon.addDescription(taxonDescription);
1080
        }
1081

    
1082
        //PREPARE REFERENCE QUESTIONS
1083

    
1084
        Map<String,OriginalSourceBase<?>> sourceMap = new HashMap<String, OriginalSourceBase<?>>();
1085

    
1086
        List<IdentifiableSource> issTmp = getCommonService().list(IdentifiableSource.class, null, null, null, null);
1087
        List<DescriptionElementSource> issTmp2 = getCommonService().list(DescriptionElementSource.class, null, null, null, null);
1088

    
1089
        Set<OriginalSourceBase> osbSet = new HashSet<OriginalSourceBase>();
1090
        if(issTmp2!=null) {
1091
            osbSet.addAll(issTmp2);
1092
        }
1093
        if(issTmp!=null) {
1094
            osbSet.addAll(issTmp);
1095
        }
1096

    
1097

    
1098
        addToSourceMap(sourceMap, osbSet);
1099

    
1100
        if (state.getConfig().isInteractWithUser()){
1101
            List<OriginalSourceBase<?>> res = null;
1102
            if(!state.isDescriptionSourcesSet()){
1103
                res = sui.askForSource(sourceMap, "the description group ("+taxon+")",
1104
                        "The current reference is "+state.getRef().getTitleCache(),getReferenceService(), state.getDataHolder().docSources);
1105
                state.setDescriptionRefs(res);
1106
                state.setDescriptionSourcesSet(true);
1107
            }
1108
            else{
1109
                res=state.getDescriptionRefs();
1110
            }
1111
            if(res !=null) {
1112
                for (OriginalSourceBase<?> sour:res){
1113
                    if(sour.isInstanceOf(IdentifiableSource.class)){
1114
                        try {
1115
                            if(sourceNotLinkedToElement(taxonDescription,sour)) {
1116
                                taxonDescription.addSource((IdentifiableSource)sour.clone());
1117
                            }
1118
                        } catch (CloneNotSupportedException e) {
1119
                            logger.warn("no cloning?");
1120
                        }
1121
                    }else{
1122
                        if(sourceNotLinkedToElement(taxonDescription,sour)) {
1123
                            taxonDescription.addSource(OriginalSourceType.Import,null, null, sour.getCitation(),sour.getCitationMicroReference());
1124
                        }
1125
                    }
1126
                }
1127
            }
1128
        }
1129
        else {
1130
            if(sourceNotLinkedToElement(taxonDescription,state.getRef(),null)) {
1131
                taxonDescription.addSource(OriginalSourceType.Import,null, null, state.getRef(), null);
1132
            }
1133
        }
1134
        state.setDescriptionGroup(taxonDescription);
1135

    
1136
        IndividualsAssociation indAssociation = IndividualsAssociation.NewInstance();
1137
        Feature feature = makeFeature(state.getDerivedUnitBase());
1138
        indAssociation.setAssociatedSpecimenOrObservation(state.getDerivedUnitBase());
1139
        indAssociation.setFeature(feature);
1140

    
1141
        if (state.getConfig().isInteractWithUser()){
1142
            sourceMap = new HashMap<String, OriginalSourceBase<?>>();
1143

    
1144
            issTmp = getCommonService().list(IdentifiableSource.class, null, null, null, null);
1145
            issTmp2 = getCommonService().list(DescriptionElementSource.class, null, null, null, null);
1146

    
1147
            osbSet = new HashSet<OriginalSourceBase>();
1148
            if(issTmp2!=null) {
1149
                osbSet.addAll(issTmp2);
1150
            }
1151
            if(issTmp!=null) {
1152
                osbSet.addAll(issTmp);
1153
            }
1154

    
1155

    
1156
            addToSourceMap(sourceMap, osbSet);
1157

    
1158
            List<OriginalSourceBase<?>> sources =null;
1159
            if(!state.isAssociationSourcesSet()) {
1160
                sources = sui.askForSource(sourceMap,  "descriptive element (association) ",taxon.toString(),
1161
                        getReferenceService(),state.getDataHolder().docSources);
1162
                state.setAssociationRefs(sources);
1163
                state.setAssociationSourcesSet(true);
1164
            }
1165
            else{
1166
                sources=state.getAssociationRefs();
1167
            }
1168
            if(sources !=null) {
1169
                for (OriginalSourceBase<?> source: sources) {
1170
                    if(source !=null) {
1171
                        if(source.isInstanceOf(DescriptionElementSource.class)){
1172
                            try {
1173
                                if(sourceNotLinkedToElement(indAssociation,source)) {
1174
                                    indAssociation.addSource((DescriptionElementSource)source.clone());
1175
                                }
1176
                            } catch (CloneNotSupportedException e) {
1177
                                logger.warn("clone forbidden?");
1178
                            }
1179
                        }else{
1180
                            if(sourceNotLinkedToElement(indAssociation,source)) {
1181
                                indAssociation.addSource(OriginalSourceType.Import,null, null, source.getCitation(),source.getCitationMicroReference());
1182
                            }
1183
                            try {
1184
                                if(sourceNotLinkedToElement(state.getDerivedUnitBase(), source)) {
1185
                                    state.getDerivedUnitBase().addSource((IdentifiableSource) source.clone());
1186
                                }
1187
                            } catch (CloneNotSupportedException e) {
1188
                                // TODO Auto-generated catch block
1189
                                e.printStackTrace();
1190
                            }
1191
                        }
1192

    
1193
                    }
1194
                }
1195
            }
1196
        }else {
1197
            if(sourceNotLinkedToElement(indAssociation,state.getRef(),null)) {
1198
                indAssociation.addSource(OriginalSourceType.Import,null, null, state.getRef(), null);
1199
            }
1200
            if(sourceNotLinkedToElement(state.getDerivedUnitBase(), state.getRef(),null)) {
1201
                state.getDerivedUnitBase().addSource(OriginalSourceType.Import,null, null, state.getRef(), null);
1202
            }
1203
            for (Reference<?> citation : determinationEvent.getReferences()) {
1204
                if(sourceNotLinkedToElement(indAssociation,citation,null))
1205
                {
1206
                    indAssociation.addSource(DescriptionElementSource.NewInstance(OriginalSourceType.Import, null, null, citation, null));
1207
                }
1208
                if(sourceNotLinkedToElement(state.getDerivedUnitBase(), state.getRef(),null)) {
1209
                    state.getDerivedUnitBase().addSource(OriginalSourceType.Import,null, null, state.getRef(), null);
1210
                }
1211
            }
1212
        }
1213

    
1214
        taxonDescription.addElement(indAssociation);
1215

    
1216
        save(taxonDescription, state);
1217
        save(taxon, state);
1218
        report.addDerivate(state.getDataHolder().unitID, state.getDerivedUnitBase());
1219
        report.addIndividualAssociation(taxon, state.getDataHolder().unitID, state.getDerivedUnitBase());
1220
    }
1221

    
1222
    /**
1223
     * @param derivedUnitBase2
1224
     * @param ref2
1225
     * @param object
1226
     * @return
1227
     */
1228
    private boolean sourceNotLinkedToElement(DerivedUnit derivedUnitBase2, Reference<?> b, String d) {
1229
        Set<IdentifiableSource> linkedSources = derivedUnitBase2.getSources();
1230
        for (IdentifiableSource is:linkedSources){
1231
            Reference<?> a = is.getCitation();
1232
            String c = is.getCitationMicroReference();
1233

    
1234
            boolean refMatch=false;
1235
            boolean microMatch=false;
1236

    
1237
            try{
1238
                if (a==null && b==null) {
1239
                    refMatch=true;
1240
                }
1241
                if (a!=null && b!=null) {
1242
                    if (a.getTitleCache().equalsIgnoreCase(b.getTitleCache())) {
1243
                        refMatch=true;
1244
                    }
1245
                }
1246
            }catch(Exception e){}
1247

    
1248

    
1249
            try{
1250
                if (c==null && d==null) {
1251
                    microMatch=true;
1252
                }
1253
                if(c!=null && d!=null) {
1254
                    if(c.equalsIgnoreCase(d)) {
1255
                        microMatch=true;
1256
                    }
1257
                }
1258
            }
1259
            catch(Exception e){}
1260

    
1261
            if (microMatch && refMatch) {
1262
                return false;
1263
            }
1264

    
1265

    
1266
        }
1267
        return true;
1268
    }
1269

    
1270
    /**
1271
     * @param specimen
1272
     * @param source
1273
     * @return
1274
     */
1275
    private boolean sourceNotLinkedToElement(SpecimenOrObservationBase<?> specimen, OriginalSourceBase<?> source) {
1276
        Set<IdentifiableSource> linkedSources = specimen.getSources();
1277
        for (IdentifiableSource is:linkedSources){
1278
            Reference<?> a = is.getCitation();
1279
            Reference<?> b = source.getCitation();
1280
            String c = is.getCitationMicroReference();
1281
            String d = source.getCitationMicroReference();
1282

    
1283
            boolean refMatch=false;
1284
            boolean microMatch=false;
1285

    
1286
            try{
1287
                if (a==null && b==null) {
1288
                    refMatch=true;
1289
                }
1290
                if (a!=null && b!=null) {
1291
                    if (a.getTitleCache().equalsIgnoreCase(b.getTitleCache())) {
1292
                        refMatch=true;
1293
                    }
1294
                }
1295
            }catch(Exception e){}
1296

    
1297

    
1298
            try{
1299
                if (c==null && d==null) {
1300
                    microMatch=true;
1301
                }
1302
                if(c!=null && d!=null) {
1303
                    if(c.equalsIgnoreCase(d)) {
1304
                        microMatch=true;
1305
                    }
1306
                }
1307
            }
1308
            catch(Exception e){}
1309

    
1310
            if (microMatch && refMatch) {
1311
                return false;
1312
            }
1313

    
1314

    
1315
        }
1316
        return true;
1317
    }
1318

    
1319
    /**
1320
     * @param indAssociation
1321
     * @param ref2
1322
     * @param object
1323
     * @return
1324
     */
1325
    private boolean sourceNotLinkedToElement(IndividualsAssociation indAssociation, Reference<?> a, String d) {
1326
        Set<DescriptionElementSource> linkedSources = indAssociation.getSources();
1327
        for (DescriptionElementSource is:linkedSources){
1328
            Reference<?> b = is.getCitation();
1329
            String c = is.getCitationMicroReference();
1330

    
1331
            boolean refMatch=false;
1332
            boolean microMatch=false;
1333

    
1334
            try{
1335
                if (a==null && b==null) {
1336
                    refMatch=true;
1337
                }
1338
                if (a!=null && b!=null) {
1339
                    if (a.getTitleCache().equalsIgnoreCase(b.getTitleCache())) {
1340
                        refMatch=true;
1341
                    }
1342
                }
1343
            }catch(Exception e){}
1344

    
1345

    
1346
            try{
1347
                if (c==null && d==null) {
1348
                    microMatch=true;
1349
                }
1350
                if(c!=null && d!=null) {
1351
                    if(c.equalsIgnoreCase(d)) {
1352
                        microMatch=true;
1353
                    }
1354
                }
1355
            }
1356
            catch(Exception e){}
1357

    
1358
            if (microMatch && refMatch) {
1359
                return false;
1360
            }
1361
        }
1362
        return true;
1363
    }
1364

    
1365
    /**
1366
     * @param taxonDescription
1367
     * @param ref2
1368
     * @param object
1369
     * @return
1370
     */
1371
    private boolean sourceNotLinkedToElement(TaxonDescription taxonDescription, Reference<?> a, String d) {
1372
        Set<IdentifiableSource> linkedSources = taxonDescription.getSources();
1373
        for (IdentifiableSource is:linkedSources){
1374
            Reference<?> b = is.getCitation();
1375
            String c = is.getCitationMicroReference();
1376

    
1377
            boolean refMatch=false;
1378
            boolean microMatch=false;
1379

    
1380
            try{
1381
                if (a==null && b==null) {
1382
                    refMatch=true;
1383
                }
1384
                if (a!=null && b!=null) {
1385
                    if (a.getTitleCache().equalsIgnoreCase(b.getTitleCache())) {
1386
                        refMatch=true;
1387
                    }
1388
                }
1389
            }catch(Exception e){}
1390

    
1391

    
1392
            try{
1393
                if (c==null && d==null) {
1394
                    microMatch=true;
1395
                }
1396
                if(c!=null && d!=null) {
1397
                    if(c.equalsIgnoreCase(d)) {
1398
                        microMatch=true;
1399
                    }
1400
                }
1401
            }
1402
            catch(Exception e){}
1403

    
1404
            if (microMatch && refMatch) {
1405
                return false;
1406
            }
1407
        }
1408
        return true;
1409
    }
1410

    
1411
    /**
1412
     * @param indAssociation
1413
     * @param source
1414
     * @return
1415
     */
1416
    private boolean sourceNotLinkedToElement(IndividualsAssociation indAssociation, OriginalSourceBase<?> source) {
1417
        Set<DescriptionElementSource> linkedSources = indAssociation.getSources();
1418
        for (DescriptionElementSource is:linkedSources){
1419
            Reference<?> a = is.getCitation();
1420
            Reference<?> b = source.getCitation();
1421
            String c = is.getCitationMicroReference();
1422
            String d = source.getCitationMicroReference();
1423

    
1424
            boolean refMatch=false;
1425
            boolean microMatch=false;
1426

    
1427
            try{
1428
                if (a==null && b==null) {
1429
                    refMatch=true;
1430
                }
1431
                if (a!=null && b!=null) {
1432
                    if (a.getTitleCache().equalsIgnoreCase(b.getTitleCache())) {
1433
                        refMatch=true;
1434
                    }
1435
                }
1436
            }catch(Exception e){}
1437

    
1438

    
1439
            try{
1440
                if (c==null && d==null) {
1441
                    microMatch=true;
1442
                }
1443
                if(c!=null && d!=null) {
1444
                    if(c.equalsIgnoreCase(d)) {
1445
                        microMatch=true;
1446
                    }
1447
                }
1448
            }
1449
            catch(Exception e){}
1450

    
1451
            if (microMatch && refMatch) {
1452
                return false;
1453
            }
1454
        }
1455
        return true;
1456
    }
1457

    
1458
    /**
1459
     * @param taxonDescription
1460
     * @param sour
1461
     * @return
1462
     */
1463
    private boolean sourceNotLinkedToElement(TaxonDescription taxonDescription, OriginalSourceBase<?> sour) {
1464
        Set<IdentifiableSource> linkedSources = taxonDescription.getSources();
1465
        for (IdentifiableSource is:linkedSources){
1466
            Reference<?> a = is.getCitation();
1467
            Reference<?> b = sour.getCitation();
1468
            String c = is.getCitationMicroReference();
1469
            String d = sour.getCitationMicroReference();
1470

    
1471
            boolean refMatch=false;
1472
            boolean microMatch=false;
1473

    
1474
            try{
1475
                if (a==null && b==null) {
1476
                    refMatch=true;
1477
                }
1478
                if (a!=null && b!=null) {
1479
                    if (a.getTitleCache().equalsIgnoreCase(b.getTitleCache())) {
1480
                        refMatch=true;
1481
                    }
1482
                }
1483
            }catch(Exception e){}
1484

    
1485

    
1486
            try{
1487
                if (c==null && d==null) {
1488
                    microMatch=true;
1489
                }
1490
                if(c!=null && d!=null) {
1491
                    if(c.equalsIgnoreCase(d)) {
1492
                        microMatch=true;
1493
                    }
1494
                }
1495
            }
1496
            catch(Exception e){}
1497

    
1498
            if (microMatch && refMatch) {
1499
                return false;
1500
            }
1501

    
1502

    
1503
        }
1504
        return true;
1505
    }
1506

    
1507
    /**
1508
     * look for the Feature object (FieldObs, Specimen,...)
1509
     * @param unit : a specimen or obersvation base
1510
     * @return the corresponding Feature
1511
     */
1512
    private Feature makeFeature(SpecimenOrObservationBase<?> unit) {
1513
        SpecimenOrObservationType type = unit.getRecordBasis();
1514

    
1515

    
1516

    
1517
        if (type.isFeatureObservation()){
1518
            return Feature.OBSERVATION();
1519
        }else if (type.isFeatureSpecimen()){
1520
            return Feature.SPECIMEN();
1521
        }else if (type == SpecimenOrObservationType.DerivedUnit){
1522
            return Feature.OBSERVATION();
1523
            //            return getFeature("Specimen or observation");
1524
        }else{
1525
            String message = "Unhandled record basis '%s' for defining individuals association feature type. Use default.";
1526
            logger.warn(String.format(message, type.getMessage()));
1527
            return Feature.OBSERVATION();
1528
            //            return getFeature("Specimen or observation");
1529

    
1530
        }
1531
    }
1532

    
1533
    /**
1534
     * HandleIdentifications : get the scientific names present in the ABCD
1535
     * document and store link them with the observation/specimen data
1536
     * @param state: the current ABCD import state
1537
     * @param derivedUnitFacade : the current derivedunitfacade
1538
     */
1539
    private void handleIdentifications(Abcd206ImportState state, DerivedUnitFacade derivedUnitFacade) {
1540
        Abcd206ImportConfigurator config = state.getConfig();
1541

    
1542

    
1543
        String scientificName = "";
1544
        boolean preferredFlag = false;
1545

    
1546
        if (state.getDataHolder().nomenclatureCode == ""){
1547
            state.getDataHolder().nomenclatureCode = config.getNomenclaturalCode().toString();
1548
        }
1549

    
1550
        for (int i = 0; i < state.getDataHolder().identificationList.size(); i++) {
1551
            Identification identification = state.getDataHolder().identificationList.get(i);
1552
            scientificName = identification.getScientificName().replaceAll(" et ", " & ");
1553

    
1554
            String preferred = identification.getPreferred();
1555
            if (preferred.equals("1") || preferred.toLowerCase().indexOf("true") != -1 || state.getDataHolder().identificationList.size()==1) {
1556
                preferredFlag = true;
1557
            }
1558
            else {
1559
                preferredFlag = false;
1560
            }
1561

    
1562
            if (identification.getCode().indexOf(':') != -1) {
1563
                state.getDataHolder().nomenclatureCode = identification.getCode().split(COLON)[1];
1564
            }
1565
            else{
1566
                state.getDataHolder().nomenclatureCode = identification.getCode();
1567
            }
1568
            TaxonNameBase<?,?> taxonName = getOrCreateTaxonName(scientificName, null, preferredFlag, state, i);
1569
            Taxon taxon = getOrCreateTaxonForName(taxonName, state);
1570
            addTaxonNode(taxon, state,preferredFlag);
1571
            linkDeterminationEvent(state, taxon, preferredFlag, derivedUnitFacade);
1572
        }
1573
    }
1574

    
1575

    
1576
    private TaxonNameBase<?, ?> getOrCreateTaxonName(String scientificName, Rank rank, boolean preferredFlag, Abcd206ImportState state, int unitIndexInAbcdFile){
1577
        TaxonNameBase<?, ?> taxonName = null;
1578
        Abcd206ImportConfigurator config = state.getConfig();
1579

    
1580
        //check atomised name data for rank
1581
        NonViralName<?> atomisedTaxonName = null;
1582
        if (rank==null && unitIndexInAbcdFile>=0 && (state.getDataHolder().atomisedIdentificationList != null || state.getDataHolder().atomisedIdentificationList.size() > 0)) {
1583
            atomisedTaxonName = setTaxonNameByType(state.getDataHolder().atomisedIdentificationList.get(unitIndexInAbcdFile), scientificName, state);
1584
            if(atomisedTaxonName!=null){
1585
                rank = atomisedTaxonName.getRank();
1586
            }
1587
        }
1588
        if(rank==null){
1589
            String message = "No rank specified for "+state.getDerivedUnitBase()+". Assuming species.";
1590
            report.addInfoMessage(message);
1591
            logger.warn(message);
1592
            rank = Rank.SPECIES();
1593
        }
1594

    
1595
        if(config.isReuseExistingTaxaWhenPossible()){
1596
            NonViralName<?> parsedName = parseScientificName(scientificName, state);
1597
            if(config.isIgnoreAuthorship() && parsedName!=null && preferredFlag){
1598
                // do not ignore authorship for non-preferred names because they need
1599
                // to be created for the determination history
1600
                String nameCache = parsedName.getNameCache();
1601
                List<NonViralName> names = getNameService().findNamesByNameCache(nameCache, MatchMode.EXACT, null);
1602
                taxonName = getBestMatchingName(scientificName, new ArrayList<TaxonNameBase>(names));
1603
            }
1604
            else {
1605
                //search for existing names
1606
                List<TaxonNameBase> names = getNameService().listByTitle(TaxonNameBase.class, scientificName, MatchMode.EXACT, null, null, null, null, null);
1607
                taxonName = getBestMatchingName(scientificName, names);
1608
            }
1609
        }
1610
        else if (config.isParseNameAutomatically()){
1611
            taxonName = parseScientificName(scientificName, state);
1612
            if(taxonName!=null){
1613
                report.addName(taxonName);
1614
                logger.info("Created new taxon name "+taxonName);
1615
            }
1616
        }
1617
        if(taxonName==null && atomisedTaxonName!=null){
1618
            taxonName = atomisedTaxonName;
1619
            report.addName(taxonName);
1620
            logger.info("Created new taxon name "+taxonName);
1621
        }
1622
        else if(taxonName==null){
1623
            //create new taxon name
1624
            taxonName = NonViralName.NewInstance(rank);
1625
            taxonName.setFullTitleCache(scientificName,true);
1626
            taxonName.setTitleCache(scientificName, true);
1627
            report.addName(taxonName);
1628
            logger.info("Created new taxon name "+taxonName);
1629
        }
1630
        save(taxonName, state);
1631
        return taxonName;
1632
    }
1633

    
1634
    private TaxonNameBase<?, ?> getBestMatchingName(String scientificName, java.util.Collection<TaxonNameBase> names){
1635
        List<TaxonNameBase> namesWithAcceptedTaxa = new ArrayList<TaxonNameBase>();
1636
        for (TaxonNameBase name : names) {
1637
            if(!name.getTaxa().isEmpty()){
1638
                namesWithAcceptedTaxa.add(name);
1639
            }
1640
        }
1641
        String message = "More than one taxon name was found for "+scientificName+"!";
1642
        //check for names with accepted taxa
1643
        if(namesWithAcceptedTaxa.size()>0){
1644
            if(namesWithAcceptedTaxa.size()>1){
1645
                report.addInfoMessage(message);
1646
                logger.warn(message);
1647
                return null;
1648
            }
1649
            return namesWithAcceptedTaxa.iterator().next();
1650
        }
1651
        //no names with accepted taxa found -> check accepted taxa of synonyms
1652
        List<Taxon> taxaFromSynonyms = new ArrayList<Taxon>();
1653
        for (TaxonNameBase name : names) {
1654
            Set<TaxonBase> taxonBases = name.getTaxonBases();
1655
            for (TaxonBase taxonBase : taxonBases) {
1656
                if(taxonBase.isInstanceOf(Synonym.class)){
1657
                    Synonym synonym = HibernateProxyHelper.deproxy(taxonBase, Synonym.class);
1658
                    taxaFromSynonyms.addAll(synonym.getAcceptedTaxa());
1659
                }
1660
            }
1661
        }
1662
        if(taxaFromSynonyms.size()>0){
1663
            if(taxaFromSynonyms.size()>1){
1664
                report.addInfoMessage(message);
1665
                logger.warn(message);
1666
                return null;
1667
            }
1668
            return taxaFromSynonyms.iterator().next().getName();
1669
        }
1670
        return null;
1671
    }
1672

    
1673
    private Taxon getOrCreateTaxonForName(TaxonNameBase<?, ?> taxonNameBase, Abcd206ImportState state){
1674
        Set<Taxon> acceptedTaxa = taxonNameBase.getTaxa();
1675
        if(acceptedTaxa.size()>0){
1676
            Taxon firstAcceptedTaxon = acceptedTaxa.iterator().next();
1677
            if(acceptedTaxa.size()>1){
1678
                String message = "More than one accepted taxon was found for taxon name: "
1679
                        + taxonNameBase.getTitleCache() + "!\n" + firstAcceptedTaxon + "was chosen for "+state.getDerivedUnitBase();
1680
                report.addInfoMessage(message);
1681
                logger.warn(message);
1682
            }
1683
            else{
1684
                return firstAcceptedTaxon;
1685
            }
1686
        }
1687
        else{
1688
            Set<TaxonBase> taxonAndSynonyms = taxonNameBase.getTaxonBases();
1689
            for (TaxonBase taxonBase : taxonAndSynonyms) {
1690
                if(taxonBase.isInstanceOf(Synonym.class)){
1691
                    Synonym synonym = HibernateProxyHelper.deproxy(taxonBase, Synonym.class);
1692
                    Set<Taxon> acceptedTaxaOfSynonym = synonym.getAcceptedTaxa();
1693
                    if(acceptedTaxaOfSynonym.size()!=1){
1694
                        String message = "No accepted taxa could be found for taxon name: "
1695
                                + taxonNameBase.getTitleCache()
1696
                                + "!\nEither it is a pro parte synonym or has no accepted taxa";
1697
                        report.addInfoMessage(message);
1698
                        logger.warn(message);
1699
                    }
1700
                    else{
1701
                        return acceptedTaxaOfSynonym.iterator().next();
1702
                    }
1703
                }
1704
            }
1705
        }
1706
        Taxon taxon = Taxon.NewInstance(taxonNameBase, state.getRef());
1707
        save(taxon, state);
1708
        report.addTaxon(taxon);
1709
        logger.info("Created new taxon "+ taxon);
1710
        return taxon;
1711
    }
1712

    
1713
    /**
1714
     * @param taxon : a taxon to add as a node
1715
     * @param state : the ABCD import state
1716
     */
1717
    private void addTaxonNode(Taxon taxon, Abcd206ImportState state, boolean preferredFlag) {
1718
        logger.info("link taxon to a taxonNode "+taxon.getTitleCache());
1719
        boolean exist = false;
1720
        Set<TaxonNode> allNodes = state.getClassification().getAllNodes();
1721
        for (TaxonNode p : allNodes){
1722
            try{
1723
                if(p.getTaxon().equals(taxon)) {
1724
                    exist =true;
1725
                }
1726
            }
1727
            catch(Exception e){
1728
                logger.warn("TaxonNode doesn't seem to have a taxon");
1729
            }
1730
        }
1731
        if (!exist){
1732
            if(state.getConfig().isMoveNewTaxaToDefaultClassification()){
1733
                addParentTaxon(taxon, state, preferredFlag, getDefaultClassification(state));
1734
            }
1735
            else{
1736
                addParentTaxon(taxon, state, preferredFlag, state.getClassification());
1737
            }
1738
        }
1739
    }
1740

    
1741
    private boolean hasTaxonNodeInClassification(Taxon taxon, Classification classification){
1742
        if(taxon.getTaxonNodes()!=null){
1743
            for (TaxonNode node : taxon.getTaxonNodes()){
1744
                if(node.getClassification().equals(classification)){
1745
                    return true;
1746
                }
1747
            }
1748
        }
1749
        return false;
1750
    }
1751

    
1752
    /**
1753
     * Add the hierarchy for a Taxon(add higher taxa)
1754
     * @param classification
1755
     * @param taxon: a taxon to add as a node
1756
     * @param state: the ABCD import state
1757
     */
1758
    private void addParentTaxon(Taxon taxon, Abcd206ImportState state, boolean preferredFlag, Classification classification){
1759
        NonViralName<?>  nvname = CdmBase.deproxy(taxon.getName(), NonViralName.class);
1760
        Rank rank = nvname.getRank();
1761
        Taxon genus =null;
1762
        Taxon subgenus =null;
1763
        Taxon species = null;
1764
        Taxon subspecies = null;
1765
        Taxon parent = null;
1766
        if (rank.isLower(Rank.GENUS() )){
1767
            String prefix = nvname.getGenusOrUninomial();
1768
            TaxonNameBase<?,?> taxonName = getOrCreateTaxonName(prefix, Rank.GENUS(), preferredFlag, state, -1);
1769
            genus = getOrCreateTaxonForName(taxonName, state);
1770
            if (preferredFlag) {
1771
                parent = saveOrUpdateClassification(null, genus, classification, state);
1772
            }
1773

    
1774
        }
1775
        if (rank.isLower(Rank.SUBGENUS())){
1776
            String prefix = nvname.getGenusOrUninomial();
1777
            String name = nvname.getInfraGenericEpithet();
1778
            if (name != null){
1779
                TaxonNameBase<?,?> taxonName = getOrCreateTaxonName(prefix+" "+name, Rank.SUBGENUS(), preferredFlag, state, -1);
1780
                subgenus = getOrCreateTaxonForName(taxonName, state);
1781
                if (preferredFlag) {
1782
                    parent = saveOrUpdateClassification(genus, subgenus, classification, state);
1783
                }            }
1784
        }
1785
        if (rank.isLower(Rank.SPECIES())){
1786
            if (subgenus!=null){
1787
                String prefix = nvname.getGenusOrUninomial();
1788
                String name = nvname.getInfraGenericEpithet();
1789
                String spe = nvname.getSpecificEpithet();
1790
                if (spe != null){
1791
                    TaxonNameBase<?,?> taxonName = getOrCreateTaxonName(prefix+" "+name+" "+spe, Rank.SPECIES(), preferredFlag, state, -1);
1792
                    species = getOrCreateTaxonForName(taxonName, state);
1793
                    if (preferredFlag) {
1794
                        parent = saveOrUpdateClassification(subgenus, species, classification, state);
1795
                    }
1796
                }
1797
            }
1798
            else{
1799
                String prefix = nvname.getGenusOrUninomial();
1800
                String name = nvname.getSpecificEpithet();
1801
                if (name != null){
1802
                    TaxonNameBase<?,?> taxonName = getOrCreateTaxonName(prefix+" "+name, Rank.SPECIES(), preferredFlag, state, -1);
1803
                    species = getOrCreateTaxonForName(taxonName, state);
1804
                    if (preferredFlag) {
1805
                        parent = saveOrUpdateClassification(genus, species, classification, state);
1806
                    }
1807
                }
1808
            }
1809
        }
1810
        if (rank.isLower(Rank.INFRASPECIES())){
1811
            TaxonNameBase<?,?> taxonName = getOrCreateTaxonName(nvname.getFullTitleCache(), Rank.SUBSPECIES(), preferredFlag, state, -1);
1812
            subspecies = getOrCreateTaxonForName(taxonName, state);
1813
            if (preferredFlag) {
1814
                parent = saveOrUpdateClassification(species, subspecies, classification, state);
1815
            }
1816
        }
1817
        if (preferredFlag && parent!=taxon) {
1818
            saveOrUpdateClassification(parent, taxon, classification, state);
1819
        }
1820
    }
1821

    
1822
    /**
1823
     * Link a parent to a child and save it in the current classification
1824
     * @param parent: the higher Taxon
1825
     * @param child : the lower (or current) Taxon
1826
     * return the Taxon from the new created Node
1827
     * @param classification
1828
     * @param state
1829
     */
1830
    private Taxon saveOrUpdateClassification(Taxon parent, Taxon child, Classification classification, Abcd206ImportState state) {
1831
        TaxonNode node =null;
1832
        if (parent != null) {
1833
            parent = (Taxon) getTaxonService().find(parent.getUuid());
1834
            child = (Taxon) getTaxonService().find(child.getUuid());
1835
            //here we do not have to check if the taxon nodes already exists
1836
            //this is done by classification.addParentChild()
1837
            //do not add child node if it already exists
1838
            if(hasTaxonNodeInClassification(child, classification)){
1839
                return child;
1840
            }
1841
            else{
1842
                node = classification.addParentChild(parent, child, state.getRef(), "");
1843
                save(classification, state);
1844
            }
1845
        }
1846
        else {
1847
            child = (Taxon) getTaxonService().find(child.getUuid());
1848
            //do not add child node if it already exists
1849
            if(hasTaxonNodeInClassification(child, classification)){
1850
                return child;
1851
            }
1852
            else{
1853
                node = classification.addChildTaxon(child, state.getRef(), null);
1854
                save(classification, state);
1855
            }
1856
        }
1857
        if(node!=null){
1858
            report.addTaxonNode(node);
1859
            return node.getTaxon();
1860
        }
1861
        String message = "Could not create taxon node for " +child;
1862
        report.addInfoMessage(message);
1863
        logger.warn(message);
1864
        return null;
1865
    }
1866

    
1867
    /**
1868
     * Parse automatically the scientific name
1869
     * @param state
1870
     * @param scientificName: the scientific name to parse
1871
     * @return a parsed name
1872
     */
1873
    private NonViralName<?> parseScientificName(String scientificName, Abcd206ImportState state) {
1874
        NonViralNameParserImpl nvnpi = NonViralNameParserImpl.NewInstance();
1875
        NonViralName<?> taxonName = null;
1876
        boolean problem = false;
1877

    
1878
        if(DEBUG){
1879
            logger.info("parseScientificName " + state.getDataHolder().nomenclatureCode.toString());
1880
        }
1881

    
1882
        if (state.getDataHolder().nomenclatureCode.toString().equals("Zoological") || state.getDataHolder().nomenclatureCode.toString().contains("ICZN")) {
1883
            taxonName = nvnpi.parseFullName(scientificName, NomenclaturalCode.ICZN, null);
1884
            if (taxonName.hasProblem()) {
1885
                problem = true;
1886
            }
1887
        }
1888
        if (state.getDataHolder().nomenclatureCode.toString().equals("Botanical") || state.getDataHolder().nomenclatureCode.toString().contains("ICBN")) {
1889
            taxonName = nvnpi.parseFullName(scientificName, NomenclaturalCode.ICNAFP, null);
1890
            if (taxonName.hasProblem()) {
1891
                problem = true;
1892
            }
1893
        }
1894
        if (state.getDataHolder().nomenclatureCode.toString().equals("Bacterial") || state.getDataHolder().nomenclatureCode.toString().contains("ICBN")) {
1895
            taxonName = nvnpi.parseFullName(scientificName, NomenclaturalCode.ICNB, null);
1896
            if (taxonName.hasProblem()) {
1897
                problem = true;
1898
            }
1899
        }
1900
        if (state.getDataHolder().nomenclatureCode.toString().equals("Cultivar") || state.getDataHolder().nomenclatureCode.toString().contains("ICNCP")) {
1901
            taxonName = nvnpi.parseFullName(scientificName, NomenclaturalCode.ICNCP, null);
1902
            if (taxonName.hasProblem()) {
1903
                problem = true;
1904
            }
1905
        }
1906
        if (problem) {
1907
            logger.info("Parsing with problem in parseScientificName " + scientificName);
1908
            return null;
1909
        }
1910
        return taxonName;
1911

    
1912
    }
1913

    
1914
    /**
1915
     * Create the name without automatic parsing, either because it failed, or because the user deactivated it.
1916
     * The name is built upon the ABCD fields
1917
     * @param atomisedMap : the ABCD atomised fields
1918
     * @param fullName : the full scientific name
1919
     * @param state
1920
     * @return the corresponding Botanical or Zoological or... name
1921
     */
1922
    private NonViralName<?> setTaxonNameByType(
1923
            HashMap<String, String> atomisedMap, String fullName, Abcd206ImportState state) {
1924
        boolean problem = false;
1925
        if(DEBUG) {
1926
            logger.info("settaxonnamebytype " + state.getDataHolder().nomenclatureCode.toString());
1927
        }
1928

    
1929
        if (state.getDataHolder().nomenclatureCode.equals("Zoological")) {
1930
            NonViralName<ZoologicalName> taxonName = ZoologicalName.NewInstance(null);
1931
            taxonName.setFullTitleCache(fullName, true);
1932
            taxonName.setGenusOrUninomial(NB(getFromMap(atomisedMap, "Genus")));
1933
            taxonName.setInfraGenericEpithet(NB(getFromMap(atomisedMap, "SubGenus")));
1934
            taxonName.setSpecificEpithet(NB(getFromMap(atomisedMap,"SpeciesEpithet")));
1935
            taxonName.setInfraSpecificEpithet(NB(getFromMap(atomisedMap,"SubspeciesEpithet")));
1936

    
1937
            if (taxonName.getGenusOrUninomial() != null){
1938
                taxonName.setRank(Rank.GENUS());
1939
            }
1940

    
1941
            if (taxonName.getInfraGenericEpithet() != null){
1942
                taxonName.setRank(Rank.SUBGENUS());
1943
            }
1944

    
1945
            if (taxonName.getSpecificEpithet() != null){
1946
                taxonName.setRank(Rank.SPECIES());
1947
            }
1948

    
1949
            if (taxonName.getInfraSpecificEpithet() != null){
1950
                taxonName.setRank(Rank.SUBSPECIES());
1951
            }
1952

    
1953
            Team team = null;
1954
            if (getFromMap(atomisedMap, "AuthorTeamParenthesis") != null) {
1955
                team = Team.NewInstance();
1956
                team.setTitleCache(getFromMap(atomisedMap, "AuthorTeamParenthesis"), true);
1957
            }
1958
            else {
1959
                if (getFromMap(atomisedMap, "AuthorTeamAndYear") != null) {
1960
                    team = Team.NewInstance();
1961
                    team.setTitleCache(getFromMap(atomisedMap, "AuthorTeamAndYear"), true);
1962
                }
1963
            }
1964
            if (team != null) {
1965
                taxonName.setBasionymAuthorship(team);
1966
            }
1967
            else {
1968
                if (getFromMap(atomisedMap, "AuthorTeamParenthesis") != null) {
1969
                    taxonName.setAuthorshipCache(getFromMap(atomisedMap, "AuthorTeamParenthesis"));
1970
                }
1971
                else if (getFromMap(atomisedMap, "AuthorTeamAndYear") != null) {
1972
                    taxonName.setAuthorshipCache(getFromMap(atomisedMap, "AuthorTeamAndYear"));
1973
                }
1974
            }
1975
            if (getFromMap(atomisedMap, "CombinationAuthorTeamAndYear") != null) {
1976
                team = Team.NewInstance();
1977
                team.setTitleCache(getFromMap(atomisedMap, "CombinationAuthorTeamAndYear"), true);
1978
                taxonName.setCombinationAuthorship(team);
1979
            }
1980
            if (taxonName.hasProblem()) {
1981
                logger.info("pb ICZN");
1982
                problem = true;
1983
            }
1984
            else {
1985
                return taxonName;
1986
            }
1987
        }
1988
        else if (state.getDataHolder().nomenclatureCode.equals("Botanical")) {
1989
            BotanicalName taxonName = (BotanicalName) parseScientificName(fullName, state);
1990
            if (taxonName != null){
1991
                return taxonName;
1992
            }
1993
            else{
1994
                taxonName = BotanicalName.NewInstance(null);
1995
            }
1996
            taxonName.setFullTitleCache(fullName, true);
1997
            taxonName.setGenusOrUninomial(NB(getFromMap(atomisedMap, "Genus")));
1998
            taxonName.setInfraGenericEpithet(NB(getFromMap(atomisedMap, "FirstEpithet")));
1999
            taxonName.setInfraSpecificEpithet(NB(getFromMap(atomisedMap, "InfraSpeEpithet")));
2000
            try {
2001
                taxonName.setRank(Rank.getRankByName(getFromMap(atomisedMap, "Rank")));
2002
            } catch (Exception e) {
2003
                if (taxonName.getGenusOrUninomial() != null){
2004
                    taxonName.setRank(Rank.GENUS());
2005
                }
2006
                else if (taxonName.getInfraGenericEpithet() != null){
2007
                    taxonName.setRank(Rank.SUBGENUS());
2008
                }
2009
                else if (taxonName.getSpecificEpithet() != null){
2010
                    taxonName.setRank(Rank.SPECIES());
2011
                }
2012
                else if (taxonName.getInfraSpecificEpithet() != null){
2013
                    taxonName.setRank(Rank.SUBSPECIES());
2014
                }
2015
            }
2016
            Team team = null;
2017
            if (getFromMap(atomisedMap, "AuthorTeamParenthesis") != null) {
2018
                team = Team.NewInstance();
2019
                team.setTitleCache(getFromMap(atomisedMap, "AuthorTeamParenthesis"), true);
2020
                taxonName.setBasionymAuthorship(team);
2021
            }
2022
            if (getFromMap(atomisedMap, "AuthorTeam") != null) {
2023
                team = Team.NewInstance();
2024
                team.setTitleCache(getFromMap(atomisedMap, "AuthorTeam"), true);
2025
                taxonName.setCombinationAuthorship(team);
2026
            }
2027
            if (team == null) {
2028
                if (getFromMap(atomisedMap, "AuthorTeamParenthesis") != null) {
2029
                    taxonName.setAuthorshipCache(getFromMap(atomisedMap, "AuthorTeamParenthesis"));
2030
                }
2031
                else if (getFromMap(atomisedMap, "AuthorTeam") != null) {
2032
                    taxonName.setAuthorshipCache(getFromMap(atomisedMap, "AuthorTeam"));
2033
                }
2034
            }
2035
            if (getFromMap(atomisedMap, "CombinationAuthorTeamAndYear") != null) {
2036
                team = Team.NewInstance();
2037
                team.setTitleCache(getFromMap(atomisedMap, "CombinationAuthorTeamAndYear"), true);
2038
                taxonName.setCombinationAuthorship(team);
2039
            }
2040
            if (taxonName.hasProblem()) {
2041
                logger.info("pb ICBN");
2042
                problem = true;
2043
            }
2044
            else {
2045
                return taxonName;
2046
            }
2047
        }
2048
        else if (state.getDataHolder().nomenclatureCode.equals("Bacterial")) {
2049
            NonViralName<BacterialName> taxonName = BacterialName.NewInstance(null);
2050
            taxonName.setFullTitleCache(fullName, true);
2051
            taxonName.setGenusOrUninomial(getFromMap(atomisedMap, "Genus"));
2052
            taxonName.setInfraGenericEpithet(NB(getFromMap(atomisedMap, "SubGenus")));
2053
            taxonName.setSpecificEpithet(NB(getFromMap(atomisedMap, "Species")));
2054
            taxonName.setInfraSpecificEpithet(NB(getFromMap(atomisedMap, "SubspeciesEpithet")));
2055

    
2056
            if (taxonName.getGenusOrUninomial() != null){
2057
                taxonName.setRank(Rank.GENUS());
2058
            }
2059
            else if (taxonName.getInfraGenericEpithet() != null){
2060
                taxonName.setRank(Rank.SUBGENUS());
2061
            }
2062
            else if (taxonName.getSpecificEpithet() != null){
2063
                taxonName.setRank(Rank.SPECIES());
2064
            }
2065
            else if (taxonName.getInfraSpecificEpithet() != null){
2066
                taxonName.setRank(Rank.SUBSPECIES());
2067
            }
2068

    
2069
            if (getFromMap(atomisedMap, "AuthorTeamAndYear") != null) {
2070
                Team team = Team.NewInstance();
2071
                team.setTitleCache(getFromMap(atomisedMap, "AuthorTeamAndYear"), true);
2072
                taxonName.setCombinationAuthorship(team);
2073
            }
2074
            if (getFromMap(atomisedMap, "ParentheticalAuthorTeamAndYear") != null) {
2075
                Team team = Team.NewInstance();
2076
                team.setTitleCache(getFromMap(atomisedMap, "ParentheticalAuthorTeamAndYear"), true);
2077
                taxonName.setBasionymAuthorship(team);
2078
            }
2079
            if (taxonName.hasProblem()) {
2080
                logger.info("pb ICNB");
2081
                problem = true;
2082
            }
2083
            else {
2084
                return taxonName;
2085
            }
2086
        }
2087
        else if (state.getDataHolder().nomenclatureCode.equals("Cultivar")) {
2088
            CultivarPlantName taxonName = CultivarPlantName.NewInstance(null);
2089

    
2090
            if (taxonName.hasProblem()) {
2091
                logger.info("pb ICNCP");
2092
                problem = true;
2093
            }
2094
            else {
2095
                return taxonName;
2096
            }
2097
            return taxonName;
2098
        }
2099

    
2100
        if (problem) {
2101
            logger.info("Problem im setTaxonNameByType ");
2102
            NonViralName<?> taxonName = NonViralName.NewInstance(null);
2103
            taxonName.setFullTitleCache(fullName, true);
2104
            return taxonName;
2105
        }
2106
        NonViralName<?> tn = NonViralName.NewInstance(null);
2107
        return tn;
2108
    }
2109

    
2110

    
2111
    /**
2112
     * Get a formated string from a hashmap
2113
     * @param atomisedMap
2114
     * @param key
2115
     * @return
2116
     */
2117
    private String getFromMap(HashMap<String, String> atomisedMap, String key) {
2118
        String value = null;
2119
        if (atomisedMap.containsKey(key)) {
2120
            value = atomisedMap.get(key);
2121
        }
2122

    
2123
        try {
2124
            if (value != null && key.matches(".*Year.*")) {
2125
                value = value.trim();
2126
                if (value.matches("[a-z A-Z ]*[0-9]{4}$")) {
2127
                    String tmp = value.split("[0-9]{4}$")[0];
2128
                    int year = Integer.parseInt(value.split(tmp)[1]);
2129
                    if (year >= 1752) {
2130
                        value = tmp;
2131
                    }
2132
                    else {
2133
                        value = null;
2134
                    }
2135
                }
2136
                else {
2137
                    value = null;
2138
                }
2139
            }
2140
        }
2141
        catch (Exception e) {
2142
            value = null;
2143
        }
2144
        return value;
2145
    }
2146

    
2147
    //    private void compareABCDtoCDM(URI urlFileName, List<String> knownElts, Abcd206XMLFieldGetter abcdFieldGetter) {
2148
    //        try {
2149
    //            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
2150
    //            DocumentBuilder constructeur = factory.newDocumentBuilder();
2151
    //            URL url = urlFileName.toURL();
2152
    //            Object o = url.getContent();
2153
    //            InputStream is = (InputStream) o;
2154
    //            Document document = constructeur.parse(is);
2155
    //            Element root = document.getDocumentElement();
2156
    //            abcdFieldGetter.traverse(root);
2157
    //        }
2158
    //        catch (ParserConfigurationException e){
2159
    //            e.printStackTrace();
2160
    //        }
2161
    //        catch (SAXException e) {
2162
    //            e.printStackTrace();
2163
    //        }
2164
    //        catch (IOException e) {
2165
    //            e.printStackTrace();
2166
    //        }
2167
    //        Set<String> elts = state.getDataHolder().allABCDelements.keySet();
2168
    //        Iterator<String> it = elts.iterator();
2169
    //        String elt;
2170
    //        while (it.hasNext()) {
2171
    //            elt = it.next();
2172
    //            if (knownElts.indexOf(elt) == -1) {
2173
    //                if(DEBUG) {
2174
    //                    logger.info("Unmerged ABCD element: " + elt + " - "+ state.getDataHolder().allABCDelements.get(elt));
2175
    //                }
2176
    //            }
2177
    //        }
2178
    //    }
2179

    
2180
    /**
2181
     * Load the list of names from the ABCD file and save them
2182
     * @param state : the current ABCD import state
2183
     * @param unitsList : the unit list from the ABCD file
2184
     * @param abcdFieldGetter : the ABCD parser
2185
     */
2186
    private void prepareCollectors(Abcd206ImportState state, NodeList unitsList, Abcd206XMLFieldGetter abcdFieldGetter) {
2187
        List<String> collectors = new ArrayList<String>();
2188
        List<String> teams = new ArrayList<String>();
2189
        List<List<String>> collectorinteams = new ArrayList<List<String>>();
2190

    
2191
        for (int i = 0; i < unitsList.getLength(); i++) {
2192
            this.getCollectorsFromXML((Element) unitsList.item(i), abcdFieldGetter, state);
2193
            for (String agent : state.getDataHolder().gatheringAgentList) {
2194
                collectors.add(agent);
2195
            }
2196
            List<String> tmpTeam = new ArrayList<String>(new HashSet<String>(state.getDataHolder().gatheringTeamList));
2197
            if(!tmpTeam.isEmpty()) {
2198
                teams.add(StringUtils.join(tmpTeam.toArray()," & "));
2199
            }
2200
            for (String agent:tmpTeam) {
2201
                collectors.add(agent);
2202
            }
2203
        }
2204

    
2205
        List<String> collectorsU = new ArrayList<String>(new HashSet<String>(collectors));
2206
        List<String> teamsU = new ArrayList<String>(new HashSet<String>(teams));
2207

    
2208

    
2209
        //existing teams in DB
2210
        Map<String,Team> titleCacheTeam = new HashMap<String, Team>();
2211
        List<UuidAndTitleCache<Team>> hiberTeam = getAgentService().getTeamUuidAndTitleCache();
2212

    
2213
        Set<UUID> uuids = new HashSet<UUID>();
2214
        for (UuidAndTitleCache<Team> hibernateT:hiberTeam){
2215
            uuids.add(hibernateT.getUuid());
2216
        }
2217
        if (!uuids.isEmpty()){
2218
            List<AgentBase> existingTeams = getAgentService().find(uuids);
2219
            for (AgentBase<?> existingP:existingTeams){
2220
                titleCacheTeam.put(existingP.getTitleCache(),CdmBase.deproxy(existingP,Team.class));
2221
            }
2222
        }
2223

    
2224

    
2225
        Map<String,UUID> teamMap = new HashMap<String, UUID>();
2226
        for (UuidAndTitleCache<Team> uuidt:hiberTeam){
2227
            teamMap.put(uuidt.getTitleCache(), uuidt.getUuid());
2228
        }
2229

    
2230
        //existing persons in DB
2231
        List<UuidAndTitleCache<Person>> hiberPersons = getAgentService().getPersonUuidAndTitleCache();
2232
        Map<String,Person> titleCachePerson = new HashMap<String, Person>();
2233
        uuids = new HashSet<UUID>();
2234
        for (UuidAndTitleCache<Person> hibernateP:hiberPersons){
2235
            uuids.add(hibernateP.getUuid());
2236
        }
2237

    
2238
        if (!uuids.isEmpty()){
2239
            List<AgentBase> existingPersons = getAgentService().find(uuids);
2240
            for (AgentBase<?> existingP:existingPersons){
2241
                titleCachePerson.put(existingP.getTitleCache(),CdmBase.deproxy(existingP,Person.class));
2242
            }
2243
        }
2244

    
2245
        Map<String,UUID> personMap = new HashMap<String, UUID>();
2246
        for (UuidAndTitleCache<Person> person:hiberPersons){
2247
            personMap.put(person.getTitleCache(), person.getUuid());
2248
        }
2249

    
2250
        java.util.Collection<Person> personToadd = new ArrayList<Person>();
2251
        java.util.Collection<Team> teamToAdd = new ArrayList<Team>();
2252

    
2253
        for (String collector:collectorsU){
2254
            Person p = Person.NewInstance();
2255
            p.setTitleCache(collector,true);
2256
            if (!personMap.containsKey(p.getTitleCache())){
2257
                personToadd.add(p);
2258
            }
2259
        }
2260
        for (String team:teamsU){
2261
            Team p = Team.NewInstance();
2262
            p.setTitleCache(team,true);
2263
            if (!teamMap.containsKey(p.getTitleCache())){
2264
                teamToAdd.add(p);
2265
            }
2266
        }
2267

    
2268
        if(!personToadd.isEmpty()){
2269
            for (Person agent: personToadd){
2270
                save(agent, state);
2271
                titleCachePerson.put(agent.getTitleCache(),CdmBase.deproxy(agent, Person.class) );
2272
            }
2273
        }
2274

    
2275
        Person ptmp ;
2276
        Map <String,Integer>teamdone = new HashMap<String, Integer>();
2277
        for (List<String> collteam: collectorinteams){
2278
            if (!teamdone.containsKey(StringUtils.join(collteam.toArray(),"-"))){
2279
                Team team = new Team();
2280
                boolean em =true;
2281
                for (String collector:collteam){
2282
                    ptmp = Person.NewInstance();
2283
                    ptmp.setTitleCache(collector,true);
2284
                    Person p2 = titleCachePerson.get(ptmp.getTitleCache());
2285
                    team.addTeamMember(p2);
2286
                    em=false;
2287
                }
2288
                if (!em) {
2289
                    teamToAdd.add(team);
2290
                }
2291
                teamdone.put(StringUtils.join(collteam.toArray(),"-"),0);
2292
            }
2293
        }
2294

    
2295
        if(!teamToAdd.isEmpty()){
2296
            for (Team agent: teamToAdd){
2297
                save(agent, state);
2298
                titleCacheTeam.put(agent.getTitleCache(), CdmBase.deproxy( agent,Team.class) );
2299
            }
2300
        }
2301

    
2302
        state.getConfig().setTeams(titleCacheTeam);
2303
        state.getConfig().setPersons(titleCachePerson);
2304
    }
2305

    
2306
    @Override
2307
    protected boolean isIgnore(Abcd206ImportState state) {
2308
        return false;
2309
    }
2310

    
2311
    /**
2312
     * Gets the default classification. If <code>null</code> creates it
2313
     * @param state the current import state
2314
     * @return the default classification
2315
     */
2316
    public Classification getDefaultClassification(Abcd206ImportState state) {
2317
        if(state.getDefaultClassification()==null){
2318
            List<Classification> classificationList = getClassificationService().list(Classification.class, null, null, null, null);
2319
            for (Classification classif : classificationList){
2320
                if (classif.getTitleCache().equalsIgnoreCase(DEFAULT_CLASSIFICATION_ABCD) && classif.getCitation().equals(state.getRef())) {
2321
                    state.setDefaultClassification(classif);
2322
                    break;
2323
                }
2324
            }
2325
            state.setDefaultClassification(Classification.NewInstance(DEFAULT_CLASSIFICATION_ABCD, state.getRef(), Language.DEFAULT()));
2326
            save(state.getDefaultClassification(), state);
2327
        }
2328
        return state.getDefaultClassification();
2329
    }
2330

    
2331
}
(2-2/11)