Project

General

Profile

Download (9.47 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2017 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.identifier;
10

    
11
import java.io.File;
12
import java.io.IOException;
13
import java.io.InputStreamReader;
14
import java.util.HashSet;
15
import java.util.List;
16
import java.util.Set;
17
import java.util.UUID;
18

    
19
import org.apache.log4j.Logger;
20
import org.springframework.stereotype.Component;
21
import org.springframework.transaction.TransactionStatus;
22

    
23
import au.com.bytecode.opencsv.CSVReader;
24
import eu.etaxonomy.cdm.common.CdmUtils;
25
import eu.etaxonomy.cdm.io.common.SimpleImport;
26
import eu.etaxonomy.cdm.model.common.CdmBase;
27
import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
28
import eu.etaxonomy.cdm.model.common.Identifier;
29
import eu.etaxonomy.cdm.model.term.DefinedTerm;
30
import eu.etaxonomy.cdm.model.term.DefinedTermBase;
31
import eu.etaxonomy.cdm.model.term.TermType;
32

    
33
/**
34
 * Imports identifiers for a certain {@link IdentifiableEntity} class from a csv
35
 * file. The class and the identifier type are defined in the configurator.
36
 *
37
 * The csv file has to follow the following format:
38
 * <BR><BR>
39
 * 1. field: uuid of the {@link IdentifiableEntity} of class defined in configurator<BR>
40
 * 2. The value of the identifier (of type defined in configurator)<BR><BR>
41
 *
42
 * NOTE: This import was first written for #6542
43
 * NOTE 2: TODO It was observed that the last line was not imported.
44
 *
45
 * @author a.mueller
46
 * @since 25.03.2017
47
 */
48
@Component
49
public class IdentifierImport
50
        extends SimpleImport<IdentifierImportConfigurator, File>{
51

    
52
    private static final long serialVersionUID = 5797541146159665997L;
53
    private static Logger logger = Logger.getLogger(IdentifierImport.class);
54

    
55
    @Override
56
    protected void doInvoke(IdentifierImportConfigurator config) {
57
        try {
58
            InputStreamReader inputReader = config.getSource();
59
            CSVReader csvReader = new CSVReader(inputReader, ';');
60
            List<String[]> lines = csvReader.readAll();
61
            if (lines.isEmpty()){
62
                logger.info("Import file is empty");
63
                csvReader.close();
64
                return;
65
            }
66

    
67
            Set<UUID> entityUuidsHandled = new HashSet<>();
68

    
69
            UUID identifierTypeUuid = config.getIdentifierTypeUuid();
70

    
71
            DefinedTermBase<?> identifierType = getTermService().find(identifierTypeUuid);
72
            if (identifierType == null || identifierType.getTermType() != TermType.IdentifierType){
73
                logger.warn("IdentifierType not recognized. Skip import");
74
                csvReader.close();
75
                return;
76
            }
77
            DefinedTerm idType = CdmBase.deproxy(identifierType, DefinedTerm.class);
78

    
79
            int i = 0;
80
            for (String[] strs : lines){
81
                IdentifiableEntity<?> entity = handleSingleLine(config, strs, idType, i, entityUuidsHandled);
82
                if (entity != null){
83
//                    entitiesToSave.add(entity);
84
                }
85
                i++;
86
            }
87
            csvReader.close();
88

    
89
            //not needed as the objects update automatically during transactions in handleSingleLine()
90
//            getCommonService().saveOrUpdate(entitiesToSave);
91

    
92
        } catch (IOException e) {
93
            throw new RuntimeException(e);
94
        }
95
    }
96

    
97
    /**
98
     * @param config configurator
99
     * @param strs text array for given line
100
     * @param i line counter
101
     * @param entityUuidsHandled
102
     * @return
103
     */
104
    private IdentifiableEntity<?> handleSingleLine(IdentifierImportConfigurator config,
105
            String[] strs, DefinedTerm idType, int i, Set<UUID> entityUuidsHandled) {
106

    
107
        //no data
108
        if (strs.length < 1){
109
            String message = String.format(
110
                    "No data available in line %d. Skipped", i);
111
            logger.warn(message);
112
            return null;
113
        }
114

    
115
        //entity uuid
116
        String uuidStr = strs[0];
117
        UUID uuid;
118
        try {
119
            uuid = UUID.fromString(uuidStr);
120
        } catch (Exception e) {
121
            String message = String.format(
122
                    "Entity identifier not recognized as UUID in line %d. Skipped. Value was: %s", i, uuidStr);
123
            logger.warn(message);
124
            return null;
125
        }
126

    
127
        TransactionStatus tx = this.startTransaction();
128
        IdentifiableEntity<?> entity = getEntityFromRepository(config, uuid);
129
        if (entity == null){
130
            String message = String.format(
131
                    "Entity for uuid %s could not be found in line %d. Skipped", uuid.toString(), i);
132
            logger.warn(message);
133
            return null;
134
        }
135

    
136
        //identifier value
137
        if (strs.length < 2){
138
            String message = String.format(
139
                    "Record in line %d has no identifier value information. Skipped.", i);
140
            logger.warn(message);
141
            this.commitTransaction(tx);
142
            return null;
143
        }
144

    
145
        //titleCache
146
        if (strs.length>2){
147
            String entityCache = entity.getTitleCache();
148
            String titleCache = strs[2];
149
            if (!CdmUtils.nullSafeEqual(entityCache, titleCache)){
150
                String message = String.format(
151
                        "Record in line %d has different titleCache: " + entityCache +" <-> "+ titleCache, i);
152
                logger.warn(message);
153
            }
154
        }
155

    
156
        String value = null;
157
        if (isNotBlank(strs[1])){
158
            value = strs[1];
159
        }else if (config.isIgnoreEmptyIdentifier()){
160
            String message = String.format(
161
                    "Record in line %d has empty identifier value information. Skipped.", i);
162
            logger.debug(message);
163
            this.commitTransaction(tx);
164
            return null;
165
        }
166

    
167
        Identifier identifier = null;
168
        //TODO clean redundant code
169
        if (config.isWarnAndDoNotOverrideIfExists()){
170
            boolean wasAlreadyImported = entityUuidsHandled.contains(uuid);
171
            if (wasAlreadyImported){
172
                String message = String.format(
173
                        "More than 1 instance for uuid '%s' ("+entity.getTitleCache()+") found in line %d. Updating not possible without deleting previous value as 'update existing' was selected. Record in line was neglected.", uuidStr, i);
174
                logger.warn(message);
175
                this.commitTransaction(tx);
176
                return null;
177
            }
178
            Set<Identifier> existingIdentifiers = entity.getIdentifiers_(idType.getUuid());
179
            if (!existingIdentifiers.isEmpty()){
180
                identifier = existingIdentifiers.iterator().next();
181
                if (!CdmUtils.nullSafeEqual(identifier.getIdentifier(), value)){
182
                    String message = String.format(
183
                            "Existing identifier in line %d differs: " + value + ". Line not imported", i);
184
                    logger.warn(message);
185
                    this.commitTransaction(tx);
186
                    return null;
187
                }
188
            }else{
189
                addNewIdentifier(idType, entity, value, identifier);
190
            }
191

    
192
        }else if (config.isUpdateExisting()){
193
            boolean wasAlreadyImported = entityUuidsHandled.contains(uuid);
194
            if (wasAlreadyImported){
195
                String message = String.format(
196
                        "More than 1 instance for uuid '%s' ("+entity.getTitleCache()+") found in line %d. Updating not possible without deleting previous value as 'update existing' was selected. Record in line was neglected.", uuidStr, i);
197
                logger.warn(message);
198
                this.commitTransaction(tx);
199
                return null;
200
            }else{
201
                Set<Identifier> existingIdentifiers = entity.getIdentifiers_(idType.getUuid());
202
                if (existingIdentifiers.size() == 1){
203
                    identifier = existingIdentifiers.iterator().next();
204
                    if (!CdmUtils.nullSafeEqual(identifier.getIdentifier(), value)){
205
                        String message = String.format(
206
                                "Existing identifier in line %d differs: " + value, i);
207
                        logger.warn(message);
208
                        identifier.setIdentifier(value);
209
                    }
210
                }else if (existingIdentifiers.size() > 1){
211
                    String message = String.format(
212
                            "Taxon name in line %d has more than a single entry for the given identifier type. I can't update the value but added a new record", i);
213
                    logger.warn(message);
214
                    addNewIdentifier(idType, entity, value, identifier);
215
                }else{
216
                    addNewIdentifier(idType, entity, value, identifier);
217
                }
218
            }
219
        } else {
220
            addNewIdentifier(idType, entity, value, identifier);
221
        }
222
        entityUuidsHandled.add(uuid);
223

    
224
        this.commitTransaction(tx);
225
        return entity;
226
    }
227

    
228
    private void addNewIdentifier(DefinedTerm idType, IdentifiableEntity<?> entity, String value,
229
            Identifier identifier) {
230
        if (identifier == null){
231
            identifier = Identifier.NewInstance(value, idType);
232
            entity.addIdentifier(identifier);
233
        }
234
    }
235

    
236
    private IdentifiableEntity<?> getEntityFromRepository(IdentifierImportConfigurator config, UUID uuid) {
237
        IdentifiableEntity<?> result = getCommonService().find(config.getCdmClass(), uuid);
238
        return result;
239
    }
240
}
(1-1/2)