Project

General

Profile

« Previous | Next » 

Revision 120a845b

Added by Andreas Müller over 6 years ago

ref #6903 first implementation of Bogota specimen import, not yet with taxon import for missing taxa

View differences:

app-import/src/main/java/eu/etaxonomy/cdm/app/bogota/BogotaSpecimenActivator.java
1
/**
2
* Copyright (C) 2016 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
package eu.etaxonomy.cdm.app.bogota;
10

  
11
import java.net.URI;
12
import java.util.UUID;
13

  
14
import org.apache.log4j.Logger;
15

  
16
import eu.etaxonomy.cdm.app.common.CdmDestinations;
17
import eu.etaxonomy.cdm.database.DbSchemaValidation;
18
import eu.etaxonomy.cdm.database.ICdmDataSource;
19
import eu.etaxonomy.cdm.io.bogota.BogotaSpecimenImportConfigurator;
20
import eu.etaxonomy.cdm.io.common.CdmDefaultImport;
21
import eu.etaxonomy.cdm.io.common.IImportConfigurator.CHECK;
22
import eu.etaxonomy.cdm.io.common.ImportResult;
23
import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
24
import eu.etaxonomy.cdm.model.reference.Reference;
25
import eu.etaxonomy.cdm.model.reference.ReferenceFactory;
26

  
27
/**
28
 * Activator for import of Bogota Checklist
29
 *
30
 * @author a.mueller
31
 * @date 21.04.2017
32
 *
33
 */
34
public class BogotaSpecimenActivator {
35
    private static final Logger logger = Logger.getLogger(BogotaSpecimenActivator.class);
36

  
37
//    static final ICdmDataSource cdmDestination = CdmDestinations.localH2();
38
//  static final ICdmDataSource cdmDestination = CdmDestinations.cdm_test_local_bogota();
39
    static final ICdmDataSource cdmDestination = CdmDestinations.cdm_bogota_production();
40

  
41
//    int minRow = 6;
42
//    int maxRow = 15; //minRow + 11999;
43

  
44
    int minRow = 180;
45
    int maxRow = 191; //minRow + 11999;
46

  
47
    boolean dedupRefs = false;
48
    boolean dedupAuthors = false;
49

  
50
    //check - import
51
    static final CHECK check = CHECK.IMPORT_WITHOUT_CHECK;
52

  
53
    protected void doImport(ICdmDataSource cdmDestination){
54

  
55
        URI source = bogotaSpecimens();
56

  
57
        //make Source
58
        BogotaSpecimenImportConfigurator config= BogotaSpecimenImportConfigurator.NewInstance(source, cdmDestination);
59
        config.setNomenclaturalCode(NomenclaturalCode.ICNAFP);
60
        config.setCheck(check);
61
        config.setDbSchemaValidation(DbSchemaValidation.VALIDATE);
62

  
63
        config.setMinLineNumber(minRow);
64
        config.setMaxLineNumber(maxRow);
65
        config.setDeduplicateReferences(dedupRefs);
66
        config.setDeduplicateAuthors(dedupAuthors);
67

  
68
        config.setSource(source);
69
        String fileName = source.toString();
70
        fileName = fileName.substring(fileName.lastIndexOf("/") + 1 );
71

  
72
        String message = "Start import from ("+ fileName + ") ...";
73
        System.out.println(message);
74
        logger.warn(message);
75

  
76
        config.setSourceReference(getSourceReference());
77

  
78
        CdmDefaultImport<BogotaSpecimenImportConfigurator> myImport = new CdmDefaultImport<>();
79

  
80
        ImportResult result = myImport.invoke(config);
81
        System.out.println(result.createReport());
82

  
83
        System.out.println("End import from (" + source.toString() + ")...");
84

  
85
    }
86

  
87

  
88
    //bogotaChecklist
89
    public static URI bogotaSpecimens() {
90
        return URI.create("file:////BGBM-PESIHPC/Bogota/Flora_de_Bogota_Dataset_20170901_GB20171011_14607-entries-to-import_GB_20171016.xlsx");
91
    }
92

  
93

  
94
    private Reference getSourceReference() {
95
        Reference result = ReferenceFactory.newGeneric();
96
        result.setTitle("Flora_de_Bogota_Dataset_20170901_GB20171011_14607-entries-to-import_GB_20171016.xlsx");
97
        result.setUuid(UUID.fromString("05e8c346-4809-4323-a484-822c92ad033d"));
98
        return result;
99
    }
100

  
101

  
102
    /**
103
     * @param args
104
     */
105
    public static void main(String[] args) {
106
        BogotaSpecimenActivator me = new BogotaSpecimenActivator();
107
        me.doImport(cdmDestination);
108
        System.exit(0);
109
    }
110
}
app-import/src/main/java/eu/etaxonomy/cdm/app/common/CdmDestinations.java
129 129
		return makeDestination(dbType, cdmServer, cdmDB, -1, cdmUserName, null);
130 130
	}
131 131

  
132
    public static ICdmDataSource cdm_test_local_bogota(){
133
        DatabaseTypeEnum dbType = DatabaseTypeEnum.MySQL;
134
        String cdmServer = "127.0.0.1";
135
        String cdmDB = "cdm_local_flora_bogota";
136
        String cdmUserName = "edit";     //root on pesiimport2
137
        return makeDestination(dbType, cdmServer, cdmDB, -1, cdmUserName, null);
138
    }
139

  
132 140
	public static ICdmDataSource cdm_test_local_euromed(){
133 141
		DatabaseTypeEnum dbType = DatabaseTypeEnum.MySQL;
134 142
		String cdmServer = "127.0.0.1";
app-import/src/main/java/eu/etaxonomy/cdm/io/bogota/BogotaSpecimenImport.java
1
// $Id$
2
/**
3
* Copyright (C) 2017 EDIT
4
* European Distributed Institute of Taxonomy
5
* http://www.e-taxonomy.eu
6
*
7
* The contents of this file are subject to the Mozilla Public License Version 1.1
8
* See LICENSE.TXT at the top of this package for the full license terms.
9
*/
10
package eu.etaxonomy.cdm.io.bogota;
11

  
12
import java.util.HashMap;
13
import java.util.Map;
14
import java.util.UUID;
15

  
16
import org.apache.log4j.Logger;
17
import org.joda.time.Partial;
18
import org.springframework.stereotype.Component;
19

  
20
import eu.etaxonomy.cdm.api.facade.DerivedUnitFacade;
21
import eu.etaxonomy.cdm.common.CdmUtils;
22
import eu.etaxonomy.cdm.io.common.utils.ImportDeduplicationHelper;
23
import eu.etaxonomy.cdm.model.agent.AgentBase;
24
import eu.etaxonomy.cdm.model.agent.Institution;
25
import eu.etaxonomy.cdm.model.agent.Person;
26
import eu.etaxonomy.cdm.model.agent.Team;
27
import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
28
import eu.etaxonomy.cdm.model.common.CdmBase;
29
import eu.etaxonomy.cdm.model.common.DefinedTerm;
30
import eu.etaxonomy.cdm.model.common.ExtensionType;
31
import eu.etaxonomy.cdm.model.common.IdentifiableSource;
32
import eu.etaxonomy.cdm.model.common.Language;
33
import eu.etaxonomy.cdm.model.common.TimePeriod;
34
import eu.etaxonomy.cdm.model.description.IndividualsAssociation;
35
import eu.etaxonomy.cdm.model.description.TaxonDescription;
36
import eu.etaxonomy.cdm.model.location.Country;
37
import eu.etaxonomy.cdm.model.location.NamedArea;
38
import eu.etaxonomy.cdm.model.location.NamedAreaLevel;
39
import eu.etaxonomy.cdm.model.location.NamedAreaType;
40
import eu.etaxonomy.cdm.model.location.Point;
41
import eu.etaxonomy.cdm.model.location.ReferenceSystem;
42
import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;
43
import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignationStatus;
44
import eu.etaxonomy.cdm.model.name.TaxonName;
45
import eu.etaxonomy.cdm.model.occurrence.Collection;
46
import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
47
import eu.etaxonomy.cdm.model.occurrence.DeterminationEvent;
48
import eu.etaxonomy.cdm.model.reference.Reference;
49
import eu.etaxonomy.cdm.model.taxon.Synonym;
50
import eu.etaxonomy.cdm.model.taxon.Taxon;
51
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
52
import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
53
import eu.etaxonomy.cdm.strategy.parser.DeterminationModifierParser;
54
import eu.etaxonomy.cdm.strategy.parser.SpecimenTypeParser;
55
import eu.etaxonomy.cdm.strategy.parser.TimePeriodParser;
56

  
57
/**
58
 * @author a.mueller
59
 * @date 21.04.2017
60
 *
61
 */
62
@Component
63
public class BogotaSpecimenImport<CONFIG extends BogotaSpecimenImportConfigurator>
64
        extends SimpleExcelSpecimenImport<CONFIG> {
65

  
66
    private static final long serialVersionUID = -884838817884874228L;
67
    private static final Logger logger = Logger.getLogger(BogotaSpecimenImport.class);
68

  
69
    private static final String COL_TAXON_UUID = "Platform Name ID = cdmID";
70
    private static final String COL_VOUCHER_ID = "Voucher ID";
71

  
72
    private static final String COL_FAMILY = "Family";
73
    private static final String COL_GENUS = "Genus";
74
    private static final String COL_SPECIFIC_EPI = "Specific Epithet";
75
    private static final String COL_BASIONYM_AUTHOR = "Author in parenthesis";
76
    private static final String COL_AUTHOR = "Author";
77
    private static final String COL_IDENTIFIER = "Identifier";
78
    private static final String COL_IDENTIFICATION_DATE = "Identification date";
79
    private static final String COL_IDENTIFICATION_QUALIFIER = "Qualifier";
80
    private static final String COL_TYPUS = "Type";
81
    private static final String COL_IDENTIFICATION_HISTORY = "Identification history";
82
    private static final String COL_COLLECTOR_VERBATIM = "Verbatim Collectors  (Originalfeld JBB)";
83
    private static final String COL_COLLECTOR_LASTNAME = "Primary Collector Last Name  (Originalfeld JBB)";
84
    private static final String COL_COLLECTOR_FIRSTNAME = "Primary Collector First Name Initial (Originalfeld JBB)";
85
    private static final String COL_COLLECTOR_MIDDLENAME = "Primary Collector Middle Name Initial (Originalfeld JBB)";
86
    private static final String COL_COLLECTOR_TYPE = "Primary collector type (Originalfeld JBB)";
87
    private static final String COL_COLLECTOR_NUMBER = "Collector's No";
88
    private static final String COL_COLLECTORS = "Collectors";
89
    private static final String COL_COLLECTION_DATE_FROM = "Collection Date from";
90
    private static final String COL_COLLECTION_DATE_TO = "Collection Date to";
91
    private static final String COL_ALTITUDE_FROM = "Altitude Value from";
92
    private static final String COL_ALTITUDE_TO = "Altitude Value to";
93
    private static final String COL_ALTITUDE_UNIT = "Altitude Unit";
94
    private static final String COL_LOCALITY = "Locality";
95
    private static final String COL_LOCALITY_ID = "LocalityID";
96
    private static final String COL_LATITUDE = "Latitude";
97
    private static final String COL_LONGITUDE = "Longitude";
98
    private static final String COL_ERROR_DISTANCE = "Error distance in m";
99
    private static final String COL_COUNTRY = "Country";
100
    private static final String COL_STATE_AREA = "State/Province/Greater Area";
101
    private static final String COL_GEO_METHOD = "Geocode Method";
102
    private static final String COL_HABITUS = "Habitus";
103
    private static final String COL_COLLECTION = "[Series] Voucher location";
104

  
105
    private static final UUID uuidAnonymous = UUID.fromString("2303f043-6e92-4afa-9082-7719e78a1c8a");
106
    private static final UUID uuidBogota = UUID.fromString("95b6cb03-8452-4439-98bd-8c1aa3c1da4e");
107
    private static final UUID uuidDefaultGeocodMethod = UUID.fromString("0983e680-b0ca-4e46-8df7-0f1d757a2e01");
108
    private static final UUID uuidExtTypeIdentificationHistory = UUID.fromString("7cee5c29-e16b-4e6f-ad57-bf7044259375");
109
    private static final UUID uuidDetQualVelAff = UUID.fromString("511a0c23-2646-4035-b570-36bdc2eb5557");
110

  
111
//    @SuppressWarnings("unchecked")
112
    private ImportDeduplicationHelper<SimpleExcelSpecimenImportState<?>> deduplicationHelper;
113
//           = (ImportDeduplicationHelper<SimpleExcelSpecimenImportState<?>>)ImportDeduplicationHelper.NewStandaloneInstance();
114

  
115

  
116
    @Override
117
    protected String getWorksheetName() {
118
        return "To be imported";
119
    }
120

  
121
//    private boolean isFirst = true;
122
//    private TransactionStatus tx = null;
123

  
124
    /**
125
     * {@inheritDoc}
126
     */
127
    @Override
128
    protected void firstPass(SimpleExcelSpecimenImportState<CONFIG> state) {
129
//        if (isFirst){
130
//            tx = this.startTransaction();
131
//            isFirst = false;
132
//        }
133

  
134
        HashMap<String, String> record = state.getOriginalRecord();
135

  
136
        String voucherId = getValue(record, COL_VOUCHER_ID);
137
        if (!isInInterval(state)){
138
            return;
139
        }
140
        String line = state.getCurrentLine() + " (id:"+ voucherId+"): ";
141
        if (state.getCurrentLine() % 100 == 0){System.out.println(line);}
142
        try {
143

  
144
            //species
145
            TaxonBase<?> taxonBase = getOrCreateTaxon(state, line, record, voucherId);
146

  
147
            if (taxonBase != null){
148
                Taxon taxon = getTaxon(taxonBase);
149

  
150
                TaxonDescription taxonDescription = getTaxonDescription(state, line, taxon);
151

  
152
                DerivedUnit specimen = makeSpecimen(state, line, record, voucherId, taxonBase);
153

  
154
                IndividualsAssociation indAssoc = IndividualsAssociation.NewInstance(specimen);
155
                indAssoc.addImportSource(voucherId, COL_VOUCHER_ID, getSourceCitation(state), null);
156
                taxonDescription.addElement(indAssoc);
157

  
158
            }
159
        } catch (Exception e) {
160
            state.getResult().addError("An unexpected exception appeared in record", e, null, line);
161
            e.printStackTrace();
162
        }
163

  
164
    }
165

  
166

  
167
    /**
168
     * @param state
169
     * @return
170
     */
171
    private boolean isInInterval(SimpleExcelSpecimenImportState<CONFIG> state) {
172
        Integer min = state.getConfig().getMinLineNumber();
173
        Integer max = state.getConfig().getMaxLineNumber();
174
        Integer current = state.getCurrentLine();
175
        if (current < min || current > max){
176
            return false;
177
        }else{
178
            return true;
179
        }
180
    }
181

  
182

  
183
    /**
184
     * @param state
185
     * @param line
186
     * @param taxon
187
     * @return
188
     */
189
    private TaxonDescription getTaxonDescription(SimpleExcelSpecimenImportState<CONFIG> state, String line,
190
            Taxon taxon) {
191
        Reference ref = getSourceCitation(state);
192
        TaxonDescription desc = this.getTaxonDescription(taxon, ref, ! IMAGE_GALLERY, CREATE);
193
        return desc;
194
    }
195

  
196

  
197
    /**
198
     * @param state
199
     * @param line
200
     * @param record
201
     * @param voucherId
202
     * @return
203
     */
204
    private DerivedUnit makeSpecimen(SimpleExcelSpecimenImportState<CONFIG> state, String line,
205
            HashMap<String, String> record, String voucherId, TaxonBase<?> taxonBase) {
206

  
207
        DerivedUnitFacade facade = DerivedUnitFacade.NewPreservedSpecimenInstance();
208
        facade.setAccessionNumber(voucherId);
209
        makeDetermination(facade.innerDerivedUnit(), state, line, record, taxonBase.getName());
210
        makeTypus(facade.innerDerivedUnit(), state, line, record, taxonBase.getName());
211
        makeCollectorFields(facade, state, line, record);
212
        makeLocationFields(facade, state, line, record);
213
        makeHabitus(facade, state, line, record);
214
        makeCollection(facade, state, line, record);
215
        DerivedUnit specimen = facade.innerDerivedUnit();
216
        specimen.addSource(makeOriginalSource(state));
217
        return specimen;
218
    }
219

  
220

  
221
    /**
222
     * @param innerDerivedUnit
223
     * @param state
224
     * @param line
225
     * @param record
226
     * @param name
227
     */
228
    private void makeTypus(DerivedUnit specimen, SimpleExcelSpecimenImportState<CONFIG> state, String line,
229
            HashMap<String, String> record, TaxonName name) {
230
        String typus = record.get(COL_TYPUS);
231
        if (typus != null){
232
            SpecimenTypeDesignationStatus status;
233
            try {
234
                status = SpecimenTypeParser.parseSpecimenTypeStatus(typus);
235
                SpecimenTypeDesignation designation = SpecimenTypeDesignation.NewInstance();
236
                designation.setTypeStatus(status);
237
                name.addSpecimenTypeDesignation(specimen, status, null, null, null, false, false);
238
            } catch (UnknownCdmTypeException e) {
239
                state.getResult().addWarning("Type designation could not be parsed", null, line);
240
            }
241
        }
242
    }
243

  
244

  
245
    /**
246
     * @param facade
247
     * @param state
248
     * @param line
249
     * @param record
250
     */
251
    private void makeCollection(DerivedUnitFacade facade, SimpleExcelSpecimenImportState<CONFIG> state,
252
            String line, HashMap<String, String> record) {
253
        String strCollection = record.get(COL_COLLECTION);
254
        String collectionFormat = ".*\\([A-Z]{2,4}\\)";
255
        if (!strCollection.matches(collectionFormat)){
256
            String message = "Voucher location format does not match the expected format. Voucher '(" + strCollection + ")' location not added.";
257
            state.getResult().addError(message, null, line);
258
            return;
259
        }
260
        String[] splits = strCollection.split("\\(");
261
        String collectionName = splits[0];
262
        String collectionCode = splits[1].replace(")", "");
263
        Collection collection = Collection.NewInstance();
264
        collection.setName(collectionName);
265
        collection.setCode(collectionCode);
266
        collection = getDeduplicationHelper(state).getExistingCollection(state, collection);
267
        facade.setCollection(collection);
268
    }
269

  
270

  
271
    /**
272
     * @param state
273
     * @return
274
     */
275
    private ImportDeduplicationHelper<SimpleExcelSpecimenImportState<?>> getDeduplicationHelper(SimpleExcelSpecimenImportState<CONFIG> state) {
276
        if (deduplicationHelper == null){
277
            deduplicationHelper = ImportDeduplicationHelper.NewInstance(this, state);
278
        }
279
        return deduplicationHelper;
280
    }
281

  
282

  
283
    /**
284
     * @param facade
285
     * @param state
286
     * @param line
287
     * @param record
288
     */
289
    private void makeHabitus(DerivedUnitFacade facade, SimpleExcelSpecimenImportState<CONFIG> state, String line,
290
            HashMap<String, String> record) {
291
        String habitus = record.get(COL_HABITUS);
292
        if (habitus != null){
293
            facade.setPlantDescription(habitus);
294
        }
295
    }
296

  
297

  
298
    /**
299
     * @param facade
300
     * @param state
301
     * @param line
302
     * @param record
303
     * @param voucherId
304
     */
305
    private void makeLocationFields(DerivedUnitFacade facade, SimpleExcelSpecimenImportState<CONFIG> state, String line,
306
            HashMap<String, String> record) {
307
        //Altitude
308
        String strAltitudeFrom = record.get(COL_ALTITUDE_FROM);
309
        String strAltitudeTo = record.get(COL_ALTITUDE_TO);
310
        Integer intAltitudeFrom = intFromString(state, strAltitudeFrom, line, COL_ALTITUDE_FROM);
311
        Integer intAltitudeTo = intFromString(state, strAltitudeTo, line, COL_ALTITUDE_TO);
312
        if (intAltitudeFrom != null){
313
            facade.setAbsoluteElevation(intAltitudeFrom);
314
            if (!intAltitudeFrom.equals(intAltitudeTo)){
315
                facade.setAbsoluteElevationMax(intAltitudeTo);
316
            }
317
            if (!record.get(COL_ALTITUDE_UNIT).equals("m")){
318
                state.getResult().addWarning("Altitude unit is not m but " + record.get(COL_ALTITUDE_UNIT), "makeLocationFields", line);
319
            }
320
        }
321
        checkNoToIfNoFrom(strAltitudeFrom, strAltitudeTo, state, line, COL_ALTITUDE_TO);
322

  
323
        //locality
324
        String locality = record.get(COL_LOCALITY);
325
        if (locality != null){  //should always exist
326
            facade.setLocality(locality, Language.SPANISH_CASTILIAN());
327
        }
328

  
329
        //Lat + Long
330
        String strLatitude = record.get(COL_LATITUDE);
331
        String strLongitude = record.get(COL_LONGITUDE);
332
        String strError = record.get(COL_ERROR_DISTANCE);
333
        Double dblLatitude = doubleFromString(state, strLatitude, line, COL_LATITUDE);
334
        Double dblLongitude = doubleFromString(state, strLongitude, line, COL_LONGITUDE);
335
        Integer intError = intFromString(state, strError, line, COL_ERROR_DISTANCE);
336
        ReferenceSystem referenceSystem = makeReferenceSystem(state, record, line);
337

  
338
        if (dblLatitude != null || dblLongitude != null || intError != null){ //should always exist
339
            Point exactLocation = Point.NewInstance(dblLongitude, dblLatitude, referenceSystem, intError);
340
            facade.setExactLocation(exactLocation);
341
        }
342

  
343
        //Country
344
        String strCountry = record.get(COL_COUNTRY);
345
        if (strCountry != null){
346
            if (strCountry.equals("Colombia")){
347
                Country colombia = Country.COLOMBIAREPUBLICOF();
348
                colombia.setLabel("Colombia");
349
                getTermService().saveOrUpdate(colombia);
350
                facade.setCountry(colombia);
351
            }else{
352
                state.getResult().addWarning("Country was not Colombia as expected but " +  strCountry,
353
                        "makeLocationFields", line);
354
            }
355
        }
356

  
357
        //State
358
        String strStateArea = record.get(COL_STATE_AREA);
359
        if (strStateArea != null){
360
            if (strStateArea.replaceAll("\\s", "").equalsIgnoreCase("Bogotá,D.C.")){
361
                NamedArea bogota = makeBogota(state, line);
362
                facade.addCollectingArea(bogota);
363
            }else{
364
                state.getResult().addWarning(COL_STATE_AREA + " was not 'Bogotá,  D.C.' as expected but " +  strCountry,
365
                        "makeLocationFields", line);
366
            }
367
        }
368
    }
369

  
370

  
371
    /**
372
     * @param strAltitudeFrom
373
     * @param strAltitudeTo
374
     * @param state
375
     * @param line
376
     * @param colAltitudeTo
377
     */
378
    private void checkNoToIfNoFrom(String strFrom, String strTo,
379
            SimpleExcelSpecimenImportState<CONFIG> state,
380
            String line, String toAttributeName) {
381
        if (isNotBlank(strTo) && isBlank(strFrom)){
382
            String message = "A min-max attribute has a max value (%s) but no min value. This is invalid."
383
                    + " The max value attribute name is %s.";
384
            message = String.format(message, strTo, toAttributeName);
385
            state.getResult().addWarning(message, null, line);
386
        }
387
    }
388

  
389
    private ReferenceSystem defaultGeocodeMethod;
390

  
391
    /**
392
     * @param state
393
     * @param record
394
     * @param line
395
     * @return
396
     */
397
    private ReferenceSystem makeReferenceSystem(SimpleExcelSpecimenImportState<CONFIG> state,
398
            Map<String, String> record, String line) {
399
        String defaultStrRefSys = "Wieczorek, J., Guo, Q., & Hijmans, R. (2004). The point-radius method for georeferencing locality descriptions and calculating associated uncertainty. International journal of geographical information science, 18(8), 745-767.; Escobar D, Díaz SR, Jojoa LM, Rudas E, Albarracín RD, Ramírez C, Gómez JY, López CR, Saavedra J (2015). Georreferenciación de localidades: Una guía de referencia para colecciones biológicas. Instituto de Investigación de Recursos Biológicos Alexander von Humboldt – Instituto de Ciencias Naturales, Universidad Nacional de Colombia. Bogotá D.C., Colombia. 95 p.";
400
        String strRefSys = record.get(COL_GEO_METHOD);
401
        if (strRefSys == null){
402
            return null;
403
        }else if (!strRefSys.equals(defaultStrRefSys)){
404
            state.getResult().addError("The expected Geocode Method is not the expected default method. Geocode Method was not added.", null, line);
405
            return null;
406
        }else if (defaultGeocodeMethod != null){
407
            return defaultGeocodeMethod;
408
        }else{
409
            String label = "Point radius method";
410
            String description = defaultStrRefSys;
411
            String labelAbbrev = "PRM";
412
            defaultGeocodeMethod = getReferenceSystem(state, uuidDefaultGeocodMethod,
413
                    label, description, labelAbbrev, null);
414
            return defaultGeocodeMethod;
415
        }
416
    }
417

  
418
    private NamedArea bogota;
419
    /**
420
     * @param state
421
     * @param line
422
     * @return
423
     */
424
    private NamedArea makeBogota(SimpleExcelSpecimenImportState<CONFIG> state, String line) {
425
        if (bogota != null){
426
            return bogota;
427
        }else{
428
            String label = "Bogotá, D.C.";
429
            NamedAreaType areaType = NamedAreaType.ADMINISTRATION_AREA();
430
            NamedAreaLevel level = NamedAreaLevel.STATE();
431
            bogota = getNamedArea(state, uuidBogota, label, label, null, areaType,
432
                    level, null, null, null);
433
            return bogota;
434
        }
435
    }
436

  
437

  
438
    /**
439
     * @param facade
440
     * @param state
441
     * @param line
442
     * @param record
443
     */
444
    private void makeCollectorFields(DerivedUnitFacade facade, SimpleExcelSpecimenImportState<CONFIG> state, String line,
445
            HashMap<String, String> record) {
446

  
447
        //collector number
448
        facade.setFieldNumber(record.get(COL_COLLECTOR_NUMBER));
449

  
450
        //gathering date
451
        String dateFrom = unknownToNull((record.get(COL_COLLECTION_DATE_FROM)));
452
        String dateTo = unknownToNull(record.get(COL_COLLECTION_DATE_TO));
453
        checkNoToIfNoFrom(dateFrom, dateTo, state, line, COL_COLLECTION_DATE_TO);
454
        try {
455
            if (dateFrom != null && dateFrom.equals(dateTo)){
456
                dateTo = null;
457
            }
458
            TimePeriod gatheringPeriod = TimePeriodParser.parseEnglishDate(dateFrom, dateTo);
459
            facade.setGatheringPeriod(gatheringPeriod);
460
        } catch (Exception e) {
461
            state.getResult().addError("Error creating gathering date", e, null, line);
462
        }
463

  
464
        //collector
465
        String collectorType = record.get(COL_COLLECTOR_TYPE);
466
        String collectors = record.get(COL_COLLECTORS);
467
        AgentBase<?> collector;
468
        if (collectorType.startsWith("Anonymous")){
469
            collector = getAnonymous();
470
        }else if (collectorType.equals("Brother") || collectorType.equals("Person")){
471
            Person person = Person.NewInstance();
472
            if (collectorType.equals("Person")){
473
                person.setLastname(record.get(COL_COLLECTOR_LASTNAME));
474
                String initials = CdmUtils.concat("", record.get(COL_COLLECTOR_FIRSTNAME), record.get(COL_COLLECTOR_MIDDLENAME));
475
                initials = (initials == null)? null : initials.replaceAll("\\s", "");
476
                person.setInitials(initials);
477
                String full = person.getTitleCache();
478
                if (!full.equals(collectors)){
479
                    person.setTitleCache(collectors, true);
480
                    //TODO longterm, collector cache
481
                }
482
            }else{
483
                person.setTitleCache(collectors, true);
484
                person.setPrefix("Hno.");
485
                person.setFirstname(collectors.replace("Hno.", "").trim());
486
            }
487
            collector = person;
488
        }else if (collectorType.equals("Group")){
489
            collector = Team.NewTitledInstance(collectors, collectors);
490
        }else if (collectorType.equals("Institution")){
491
            collector = Institution.NewNamedInstance(collectors);
492
        }else{
493
            String message = "Collector type " + collectorType + " not yet supported by import. Collector not added.";
494
            state.getResult().addError(message, null, line);
495
            collector = null;
496
        }
497
        collector = getDeduplicationHelper(state).getExistingAgent(state, collector);
498
        facade.setCollector(collector);
499
    }
500

  
501

  
502
    /**
503
     * @param string
504
     * @return
505
     */
506
    private String unknownToNull(String string) {
507
        if (string == null || string.equalsIgnoreCase("unknown")){
508
            return null;
509
        }else{
510
            return string;
511
        }
512
    }
513

  
514
    private Person anonymous;
515
    private Person getAnonymous() {
516
        if (anonymous != null){
517
            return anonymous;
518
        }
519
        anonymous = CdmBase.deproxy(getAgentService().find(uuidAnonymous), Person.class);
520
        if (anonymous == null){
521
            anonymous = Person.NewTitledInstance("Anon.");
522
            anonymous.setUuid(uuidAnonymous);
523
            getAgentService().save(anonymous);
524
        }
525
        return anonymous;
526
    }
527

  
528

  
529
    /**
530
     * @param facade
531
     * @param state
532
     * @param line
533
     * @param record
534
     * @param taxonBase
535
     */
536
    private void makeDetermination(DerivedUnit specimen, SimpleExcelSpecimenImportState<CONFIG> state, String line,
537
            HashMap<String, String> record, TaxonName taxonName) {
538

  
539
        DeterminationEvent determination;
540
        determination = DeterminationEvent.NewInstance(taxonName, specimen);
541
        determination.setPreferredFlag(true);
542

  
543
        //determiner/identifier
544
        TeamOrPersonBase<?> determiner = makeDeterminer(state, record, line);
545
        determination.setDeterminer(determiner);
546

  
547
        //date
548
        TimePeriod date = makeIdentificationDate(state, record, line);
549
        determination.setTimeperiod(date);
550

  
551
        //qualifier
552
        DefinedTerm qualifier = makeDeterminationQualifier(state, record, line);
553
        determination.setModifier(qualifier);
554

  
555
        //history
556
        String history = record.get(COL_IDENTIFICATION_HISTORY);
557
        if (history != null){
558
            String label = "Identification History";
559
            String text = label;
560
            ExtensionType detHistoryType = getExtensionType(state, uuidExtTypeIdentificationHistory, label, text, null);
561
            specimen.addExtension(history, detHistoryType);
562
        }
563
    }
564

  
565

  
566
    /**
567
     * @param state
568
     * @param record
569
     * @param line
570
     * @return
571
     */
572
    private TeamOrPersonBase<?> makeDeterminer(SimpleExcelSpecimenImportState<CONFIG> state,
573
            HashMap<String, String> record, String line) {
574
        String identifier = record.get(COL_IDENTIFIER);
575
        if (identifier == null){
576
            return null;
577
        }else if (identifier.equals("Anon.")){
578
            return getAnonymous();
579
        }else{
580
            Person person = Person.NewInstance();
581
            person.setTitleCache(identifier, true);
582
//            String format = "([A-Z]\\.){1,3}" +
583
//                    NonViralNameParserImplRegExBase.capitalWord +
584
//                    "(-" + NonViralNameParserImplRegExBase.capitalWord;
585

  
586
            String[] splits = identifier.split("\\.");
587
            int length = splits.length;
588
            if (splits[length - 1].equals("")){
589
                splits[length - 2]= splits[length - 2]+".";
590
                length--;
591
            }
592
            if (splits[length - 1].startsWith("-")){
593
                splits[length - 2]= splits[length - 2]+"." + splits[length - 1];
594
                length--;
595
            }
596
            String lastName = splits[length - 1];
597
            String initials = null;
598
            for (int i= 0; i < length-1;i++){
599
                initials = CdmUtils.concat("", initials, splits[i]+".");
600
            }
601
            person.setLastname(lastName);
602
            person.setInitials(initials);
603
            TeamOrPersonBase<?> result = getDeduplicationHelper(state).getExistingAuthor(state, person);
604
            return result;
605
        }
606
    }
607

  
608

  
609
    /**
610
     * @param state
611
     * @param record
612
     * @param line
613
     * @return
614
     */
615
    private TimePeriod makeIdentificationDate(SimpleExcelSpecimenImportState<CONFIG> state,
616
            HashMap<String, String> record, String line) {
617
        String strDate = record.get(COL_IDENTIFICATION_DATE);
618
        if (strDate == null || strDate.equals("s.n.")){
619
            return null;
620
        }
621
        String[] splits = strDate.split("/");
622
        String strYear = splits[splits.length-1];
623
        String strMonth = splits.length < 2? null:splits[splits.length-2];
624
        String strDay = splits.length < 3? null:splits[splits.length-3];
625

  
626
        Integer year = intFromString(state, strYear, line, COL_IDENTIFICATION_DATE);
627
        Integer month = intFromString(state, strMonth, line, COL_IDENTIFICATION_DATE);
628
        Integer day = intFromString(state, strDay, line, COL_IDENTIFICATION_DATE);
629
        Partial start = TimePeriodParser.makePartialFromDateParts(year, month, day);
630
        return TimePeriod.NewInstance(start);
631
    }
632

  
633

  
634
    /**
635
     * @param state
636
     * @param record
637
     * @param line
638
     * @return
639
     */
640
    private DefinedTerm makeDeterminationQualifier(SimpleExcelSpecimenImportState<CONFIG> state,
641
            HashMap<String, String> record, String line) {
642
        String qualifier = record.get(COL_IDENTIFICATION_QUALIFIER);
643
        if (qualifier != null){
644
            try {
645
                return DeterminationModifierParser.parseDeterminationQualifier(qualifier);
646
            } catch (UnknownCdmTypeException e) {
647
                //TODO add to terms
648
                if (qualifier.equals("vel. aff.")){
649

  
650
                    DefinedTerm velAff = (DefinedTerm)getTermService().find(uuidDetQualVelAff);
651
                    if (velAff == null){
652
                        velAff = DefinedTerm.NewModifierInstance(qualifier, qualifier, qualifier);
653
                        velAff.setUuid(uuidDetQualVelAff);
654
                        getTermService().save(velAff);
655
                    }
656
                    return velAff;
657
                }
658
                state.getResult().addError("Determination qualifier could not be recognized: " + qualifier, null, line);
659
                return null;
660
            }
661
        }else{
662
            return null;
663
        }
664
    }
665

  
666

  
667
    /**
668
     * @param taxonBase
669
     * @return
670
     */
671
    private Taxon getTaxon(TaxonBase<?> taxonBase) {
672
        if (taxonBase.isInstanceOf(Synonym.class)){
673
            return CdmBase.deproxy(taxonBase, Synonym.class).getAcceptedTaxon();
674
        }else{
675
            return CdmBase.deproxy(taxonBase, Taxon.class);
676
        }
677
    }
678

  
679

  
680
    /**
681
     * @param state
682
     * @param line
683
     * @param record
684
     * @param noStr
685
     * @return
686
     */
687
    private TaxonBase<?> getOrCreateTaxon(SimpleExcelSpecimenImportState<CONFIG> state, String line,
688
            HashMap<String, String> record, String noStr) {
689

  
690
        String strUuidTaxon = record.get(COL_TAXON_UUID);
691
        if (strUuidTaxon != null){
692
            UUID uuidTaxon;
693
            try {
694
                uuidTaxon = UUID.fromString(strUuidTaxon);
695
            } catch (Exception e) {
696
                state.getResult().addError("Taxon uuid has incorrect format. Taxon could not be loaded. Data not imported.", null, line);
697
                return null;
698
            }
699
            TaxonBase<?> result = getTaxonService().find(uuidTaxon);
700
            if (result == null){
701
                state.getResult().addError("Taxon for uuid  "+strUuidTaxon+" could not be found in database. "
702
                        + "Taxon could not be loaded. Data not imported.", null, line);
703

  
704
            }
705
            return result;
706
        }else{
707
            TaxonName taxonName = null;
708
            Reference sec = null;
709
            Taxon result = Taxon.NewInstance(taxonName, sec);
710
            result.addSource(makeOriginalSource(state));
711
            //TODO export uuid
712

  
713
//            state.getResult().addInfo("Taxon");
714
            //TODO
715
            return null;
716
        }
717
    }
718

  
719

  
720
    @Override
721
    protected void secondPass(SimpleExcelSpecimenImportState<CONFIG> state) {
722
//        if (tx != null){
723
//            this.commitTransaction(tx);
724
//            tx = null;
725
//        }
726
    }
727

  
728
    @Override
729
    protected IdentifiableSource makeOriginalSource(SimpleExcelSpecimenImportState<CONFIG> state) {
730
        return IdentifiableSource.NewDataImportInstance(getValue(state.getOriginalRecord(), COL_VOUCHER_ID), COL_VOUCHER_ID, getSourceCitation(state));
731
    }
732

  
733
    /**
734
     * @param state
735
     * @return
736
     */
737
    protected Reference getSourceCitation(SimpleExcelSpecimenImportState<CONFIG> state) {
738
        Reference source = state.getConfig().getSourceReference();
739
        if (source.getId() == 0){
740
            Reference persisted = getReferenceService().find(source.getUuid());
741
            if (persisted == null){
742
                getReferenceService().saveOrUpdate(source);
743
            }else{
744
                state.getConfig().setSourceReference(persisted);
745
                source = persisted;
746
            }
747
        }
748
        return source;
749
    }
750
}
app-import/src/main/java/eu/etaxonomy/cdm/io/bogota/BogotaSpecimenImportConfigurator.java
1
// $Id$
2
/**
3
* Copyright (C) 2017 EDIT
4
* European Distributed Institute of Taxonomy
5
* http://www.e-taxonomy.eu
6
*
7
* The contents of this file are subject to the Mozilla Public License Version 1.1
8
* See LICENSE.TXT at the top of this package for the full license terms.
9
*/
10
package eu.etaxonomy.cdm.io.bogota;
11

  
12
import java.net.URI;
13

  
14
import eu.etaxonomy.cdm.database.ICdmDataSource;
15
import eu.etaxonomy.cdm.io.common.ImportStateBase;
16
import eu.etaxonomy.cdm.io.excel.common.ExcelImportConfiguratorBase;
17

  
18
/**
19
 * @author a.mueller
20
 * @date 21.04.2017
21
 *
22
 */
23
public class BogotaSpecimenImportConfigurator extends ExcelImportConfiguratorBase{
24

  
25
    private static final long serialVersionUID = 6688815926646112726L;
26

  
27
    private int minLineNumber = 0;
28
    private int maxLineNumber = 1000000;
29

  
30
    /**
31
     * @param source
32
     * @param cdmDestination
33
     * @return
34
     */
35
    public static BogotaSpecimenImportConfigurator NewInstance(URI source, ICdmDataSource destination) {
36
        return new BogotaSpecimenImportConfigurator(source, destination);
37
    }
38

  
39
    /**
40
     * @param uri
41
     * @param destination
42
     */
43
    private BogotaSpecimenImportConfigurator(URI uri, ICdmDataSource destination) {
44
        super(uri, destination);
45
    }
46

  
47
    /**
48
     * {@inheritDoc}
49
     */
50
    @Override
51
    public ImportStateBase getNewState() {
52
        return new SimpleExcelSpecimenImportState<>(this);
53
    }
54

  
55
    /**
56
     * {@inheritDoc}
57
     */
58
    @Override
59
    protected void makeIoClassList() {
60
        ioClassList = new Class[]{
61
                BogotaSpecimenImport.class,
62
        };
63
    }
64

  
65
    public int getMinLineNumber() {
66
        return minLineNumber;
67
    }
68
    public void setMinLineNumber(int minLineNumber) {
69
        this.minLineNumber = minLineNumber;
70
    }
71

  
72
    public int getMaxLineNumber() {
73
        return maxLineNumber;
74
    }
75

  
76
    public void setMaxLineNumber(int maxLineNumber) {
77
        this.maxLineNumber = maxLineNumber;
78
    }
79

  
80

  
81
}
app-import/src/main/java/eu/etaxonomy/cdm/io/bogota/SimpleExcelSpecimenImport.java
1
/**
2
* Copyright (C) 2016 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
package eu.etaxonomy.cdm.io.bogota;
10

  
11
import java.util.HashMap;
12
import java.util.List;
13
import java.util.Set;
14

  
15
import org.apache.log4j.Logger;
16

  
17
import eu.etaxonomy.cdm.io.excel.common.ExcelImportBase;
18
import eu.etaxonomy.cdm.io.excel.common.ExcelImportConfiguratorBase;
19
import eu.etaxonomy.cdm.io.excel.common.ExcelRowBase;
20
import eu.etaxonomy.cdm.model.common.IdentifiableSource;
21
import eu.etaxonomy.cdm.strategy.parser.INonViralNameParser;
22
import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImpl;
23

  
24
/**
25
 * Simple Excel import class that works without default state class
26
 * {@link SimpleExcelSpecimenImportState}
27
 * @author a.mueller
28
 * @date 16.06.2016
29
 */
30
public abstract class SimpleExcelSpecimenImport<CONFIG extends ExcelImportConfiguratorBase>
31
        extends ExcelImportBase<SimpleExcelSpecimenImportState<CONFIG>, CONFIG, ExcelRowBase>{
32

  
33
    private static final long serialVersionUID = -4345647703312616421L;
34

  
35
    private static final Logger logger = Logger.getLogger(SimpleExcelSpecimenImport.class);
36

  
37
    protected static INonViralNameParser<?> nameParser = NonViralNameParserImpl.NewInstance();
38

  
39

  
40
    @Override
41
    protected void analyzeRecord(HashMap<String, String> record, SimpleExcelSpecimenImportState<CONFIG> state) {
42
        //override only if needed
43
    }
44

  
45
    @Override
46
    protected void secondPass(SimpleExcelSpecimenImportState<CONFIG> state) {
47
        //override only if needed
48
    }
49

  
50
    @Override
51
    protected boolean isIgnore(SimpleExcelSpecimenImportState<CONFIG> state) {
52
        return false;
53
    }
54

  
55
//***************************** METHODS *********************************/
56

  
57

  
58
    /**
59
     * @param state
60
     * @return
61
     */
62
    protected IdentifiableSource makeOriginalSource(SimpleExcelSpecimenImportState<CONFIG> state) {
63
        return IdentifiableSource.NewDataImportInstance("line: " + state.getCurrentLine(), null, state.getConfig().getSourceReference());
64
    }
65

  
66

  
67
    /**
68
     * @param line
69
     * @param keys
70
     * @param expectedKeys
71
     */
72
    protected void checkAllKeysExist(String line, Set<String> keys, List<String> expectedKeys) {
73
        for (String key: keys) {
74
            if (! expectedKeys.contains(key)){
75
                logger.warn(line + "Unexpected Key: " + key);
76
            }
77
        }
78
    }
79

  
80

  
81
}
app-import/src/main/java/eu/etaxonomy/cdm/io/bogota/SimpleExcelSpecimenImportState.java
1
/**
2
* Copyright (C) 2016 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
package eu.etaxonomy.cdm.io.bogota;
10

  
11
import org.apache.log4j.Logger;
12

  
13
import eu.etaxonomy.cdm.io.excel.common.ExcelImportConfiguratorBase;
14
import eu.etaxonomy.cdm.io.excel.common.ExcelImportState;
15
import eu.etaxonomy.cdm.io.excel.common.ExcelRowBase;
16

  
17
/**
18
 * @author a.mueller
19
 * @date 16.06.2016
20
 *
21
 */
22
public class SimpleExcelSpecimenImportState<CONFIG extends ExcelImportConfiguratorBase>
23
        extends ExcelImportState<CONFIG, ExcelRowBase>{
24

  
25
    @SuppressWarnings("unused")
26
    private static final Logger logger = Logger.getLogger(SimpleExcelSpecimenImportState.class);
27

  
28

  
29
// ************************* CONSTRUCTUR *******************************/
30
    /**
31
     * @param config
32
     */
33
    public SimpleExcelSpecimenImportState(CONFIG config) {
34
        super(config);
35
    }
36

  
37
 //************************ PUTTER / GETTER *****************************/
38

  
39

  
40
}

Also available in: Unified diff