Project

General

Profile

Download (12.7 KB) Statistics
| Branch: | Revision:
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.greece;
10

    
11
import java.io.File;
12
import java.io.IOException;
13
import java.net.URI;
14
import java.util.List;
15

    
16
import org.apache.commons.imaging.ImageReadException;
17
import org.apache.commons.imaging.Imaging;
18
import org.apache.commons.imaging.common.GenericImageMetadata.GenericImageMetadataItem;
19
import org.apache.commons.imaging.common.ImageMetadata;
20
import org.apache.commons.imaging.common.ImageMetadata.ImageMetadataItem;
21
import org.apache.log4j.Logger;
22
import org.joda.time.DateTime;
23
import org.joda.time.DateTimeZone;
24
import org.joda.time.format.DateTimeFormat;
25
import org.joda.time.format.DateTimeFormatter;
26
import org.springframework.stereotype.Component;
27
import org.springframework.transaction.TransactionStatus;
28

    
29
import eu.etaxonomy.cdm.api.service.config.MatchingTaxonConfigurator;
30
import eu.etaxonomy.cdm.io.common.CdmImportBase;
31
import eu.etaxonomy.cdm.io.common.utils.ImportDeduplicationHelper;
32
import eu.etaxonomy.cdm.io.mexico.SimpleExcelTaxonImportState;
33
import eu.etaxonomy.cdm.model.agent.Person;
34
import eu.etaxonomy.cdm.model.common.CdmBase;
35
import eu.etaxonomy.cdm.model.common.Language;
36
import eu.etaxonomy.cdm.model.common.TimePeriod;
37
import eu.etaxonomy.cdm.model.description.Feature;
38
import eu.etaxonomy.cdm.model.description.TaxonDescription;
39
import eu.etaxonomy.cdm.model.description.TextData;
40
import eu.etaxonomy.cdm.model.media.Media;
41
import eu.etaxonomy.cdm.model.media.Rights;
42
import eu.etaxonomy.cdm.model.media.RightsType;
43
import eu.etaxonomy.cdm.model.reference.Reference;
44
import eu.etaxonomy.cdm.model.taxon.Synonym;
45
import eu.etaxonomy.cdm.model.taxon.Taxon;
46
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
47
/**
48
 * Import for the Flora Hellenica images.
49
 *
50
 * @author a.mueller
51
 * @since 03.04.2017
52
 */
53

    
54
@Component
55
public class FloraHellenicaImageImport<CONFIG extends FloraHellenicaImportConfigurator>
56
        extends CdmImportBase<CONFIG,SimpleExcelTaxonImportState<CONFIG>>{
57

    
58
    private static final long serialVersionUID = 7118028793298922703L;
59
    private static final Logger logger = Logger.getLogger(FloraHellenicaImageImport.class);
60

    
61
    private static final String BASE_URL = "https://media.e-taxonomy.eu/flora-greece/";
62
    private static final String IMAGE_FOLDER = "////BGBM-PESIHPC/Greece/thumbs/";
63

    
64
    @SuppressWarnings("unchecked")
65
    private ImportDeduplicationHelper<SimpleExcelTaxonImportState<?>> deduplicationHelper = (ImportDeduplicationHelper<SimpleExcelTaxonImportState<?>>)ImportDeduplicationHelper.NewInstance(this);
66

    
67
    @Override
68
    protected void doInvoke(SimpleExcelTaxonImportState<CONFIG> state) {
69
        TransactionStatus tx = this.startTransaction();
70
        for (int plate = 1; plate < 22 ; plate++){
71
            try {
72
                handleSinglePlate(state, plate);
73
            } catch (Exception e) {
74
                logger.error("Error when handling plate " + plate);
75
                e.printStackTrace();
76
            }
77
        }
78
        this.commitTransaction(tx);
79
    }
80

    
81
    private void handleSinglePlate(SimpleExcelTaxonImportState<CONFIG> state, int plate) {
82
        String fill = plate < 10 ? "0" : "";
83
        String plateStr = "Plate_" + fill + plate + "/";
84
        String fullFolderUrl = BASE_URL + plateStr;
85
        String fullThumbUrl = BASE_URL + "thumbs/" + plateStr;
86
        String folderStr = IMAGE_FOLDER + plateStr;
87
        File file = new File(folderStr);
88
        String[] list = file.list();
89
        for (String fileStr : list){
90
            try {
91
                handleSingleFile(state, fullFolderUrl, fullThumbUrl, fileStr, plate);
92
            } catch (Exception e) {
93
                logger.error("Error when handling file: " + fileStr + " in plate " + plate);
94
                e.printStackTrace();
95
            }
96
        }
97
    }
98

    
99
    private void handleSingleFile(SimpleExcelTaxonImportState<CONFIG> state,
100
            String fullFolderUrl, String fullThumbUrl, String fileStr, int plate) {
101
        String[] taxonNameAndArtist = getTaxonName(fileStr);
102
        String taxonNameStr = taxonNameAndArtist[0];
103
        String taxonNameStr2 = null;
104
        String artistStr = taxonNameAndArtist[1];
105
        if (fileStr.equals("RamondaSerbica(L)+Nathaliae(R)1.jpg")){
106
            taxonNameStr = "Ramonda serbica";
107
            taxonNameStr2 = "Ramonda nathaliae";
108
        }else if (fileStr.contains("HypericumCerastioides")){
109
            taxonNameStr = taxonNameStr.replace("HypericumCerastoides", "HypericumCerastioides");
110
        }else if (fileStr.contains("StachysScardica")){
111
            taxonNameStr = taxonNameStr.replace("StachysScardica", "BetonicaScardica");
112
        }else if (fileStr.contains("OleaEuropaeaOleaster ")){
113
            taxonNameStr = taxonNameStr.replace("OleaEuropaeaOleaster", "OleaEuropaeaEuropaea");
114
        }
115

    
116
        try {
117

    
118
            Media media = getImageMedia(fullFolderUrl + fileStr, fullThumbUrl + fileStr, true);
119

    
120
            //image metadata
121
            URI uri = URI.create(fullThumbUrl + fileStr);
122
            try{
123
                ImageMetadata metadata = Imaging.getMetadata(uri.toURL().openStream(), null);
124
                List<? extends ImageMetadataItem> items = metadata.getItems();
125
                for (ImageMetadataItem metadataItem : items){
126
                    if (metadataItem instanceof GenericImageMetadataItem){
127
                        GenericImageMetadataItem item = (GenericImageMetadataItem) metadataItem;
128

    
129
    //                    System.out.println(item.getKeyword() +  ":    " + item.getText());
130
                        String keyword = item.getKeyword().toLowerCase();
131
                        String value = removeQuots(item.getText());
132
                        if("image description".equals(keyword)){
133
                            media.putDescription(Language.DEFAULT(), value);
134
                        }else if ("artist".equals(keyword)){
135
                            if (isNotBlank(artistStr) && ! value.contains(artistStr)){
136
                                logger.warn("Artist and artistStr are different: " +  artistStr  + "; " + value);
137
                            }
138
                            artistStr = value;
139
                        }else if ("date time original".equalsIgnoreCase(item.getKeyword())){
140
                            DateTimeFormatter f = DateTimeFormat.forPattern("yyyy:MM:dd HH:mm:ss");
141
                            DateTime created = f.withZone(DateTimeZone.forID("Europe/Athens")).parseDateTime(value);
142
                            media.setMediaCreated(TimePeriod.NewInstance(created));
143
                        }
144
                    }else{
145
                        throw new IllegalStateException("Unsupported ImageMetadataItem type: " + metadataItem.getClass().getName());
146
                    }
147
                }
148
            } catch (ImageReadException | IOException e1) {
149
                e1.printStackTrace();
150
            }
151
            if (isNotBlank(artistStr)){
152
                Person person = Person.NewInstance();
153
                String[] split = artistStr.split("\\+");
154
                if (split.length == 1){
155
                    person.setFamilyName(artistStr);
156
                }else if (split.length == 2){
157
                    person.setGivenName(split[0]);
158
                    person.setFamilyName(split[1]);
159
                }else{
160
                    person.setTitleCache("artistStr", true);
161
                }
162
                person = deduplicationHelper.getExistingAuthor(state, person);
163

    
164
                media.setArtist(person);
165
                //copyright
166
                Rights right = Rights.NewInstance();
167
                right.setType(RightsType.COPYRIGHT());
168
                right.setAgent(person);
169
                right = deduplicationHelper.getExistingCopyright(state, right);
170
                media.addRights(right);
171
            }
172

    
173
            String detail = "p. " + FloraHellenicaImageCaptionImport.startPage + 1 + plate *2;
174
            media.addPrimaryMediaSource(getSecReference(state), detail);
175

    
176

    
177
            Taxon taxon = getAcceptedTaxon(taxonNameStr);
178
            makeTextData(fileStr, media, taxon);
179
            if (taxonNameStr2 != null){
180
                Taxon taxon2 = getAcceptedTaxon(taxonNameStr);
181
                makeTextData(fileStr, media, taxon2);
182
            }
183

    
184

    
185
            if (taxonNameStr2 == null){
186
                media.putTitle(Language.LATIN(), taxon == null ? taxonNameStr :
187
                    taxon.getName().getTitleCache());
188
            }else{
189
                media.putTitle(Language.LATIN(), "Ramonda serbica(L) + R. nathaliae(R)");
190
            }
191

    
192

    
193
        } catch (Exception e) {
194
            e.printStackTrace();
195
            return;
196
        }
197
    }
198

    
199
    private String removeQuots(String text) {
200
        if (text.startsWith("'") && text.endsWith("'")){
201
            return text.substring(1, text.length() -1);
202
        }else{
203
            return text;
204
        }
205
    }
206

    
207
    private Reference secReference;
208
    private Reference getSecReference(SimpleExcelTaxonImportState<CONFIG> state) {
209
        if (secReference != null){
210
            secReference = getReferenceService().find(state.getConfig().getSecReference().getUuid());
211
        }
212
        return secReference;
213
    }
214

    
215

    
216
    /**
217
     * Gets the image gallery, creates
218
     */
219
    private void makeTextData(String fileStr, Media media, Taxon taxon) {
220
        if (taxon == null){
221
            logger.warn("Taxon not found for image " + fileStr + "."
222
                    + "Media could not be attached to taxon.");
223
            getMediaService().saveOrUpdate(media);
224
            return;
225
        }
226
        TaxonDescription imageGallery = taxon.getImageGallery(true);
227
        TextData textData;
228
        if (imageGallery.getElements().isEmpty()){
229
            textData = TextData.NewInstance();
230
            textData.setFeature(Feature.IMAGE());
231
        }else{
232
            textData = CdmBase.deproxy(imageGallery.getElements().iterator().next(), TextData.class);
233
        }
234
        imageGallery.addElement(textData);
235
        textData.addMedia(media);
236
    }
237

    
238
    /**
239
     * @param taxonNameStr
240
     * @return
241
     */
242
    private Taxon getAcceptedTaxon(String taxonNameStr) {
243

    
244
        MatchingTaxonConfigurator config = new MatchingTaxonConfigurator();
245
        taxonNameStr = adaptName(taxonNameStr);
246
        config.setTaxonNameTitle(taxonNameStr);
247
        config.setIncludeSynonyms(true);
248
        List<TaxonBase> list = getTaxonService().findTaxaByName(config);
249
        if (list.isEmpty()){
250
            logger.warn("Taxon not found for media: " + taxonNameStr);
251
            return null;
252
        }else{
253
            if (list.size()>1){
254
                logger.warn("More than 1 taxon found for media: " + taxonNameStr);
255
            }
256
            TaxonBase<?> taxonBase = list.get(0);
257
            Taxon result;
258
            if (taxonBase.isInstanceOf(Synonym.class)){
259
                result = CdmBase.deproxy(taxonBase, Synonym.class).getAcceptedTaxon();
260
            }else{
261
                result = CdmBase.deproxy(taxonBase, Taxon.class);
262
            }
263
            return result;
264
        }
265
    }
266

    
267
    /**
268
     * @param taxonNameStr
269
     * @return
270
     */
271
    private String adaptName(String taxonNameStr) {
272
        if (taxonNameStr.equals("Hypericum cerastoides")){
273
            taxonNameStr = "Hypericum cerastioides";
274
        }
275
        return taxonNameStr;
276
    }
277

    
278
    /**
279
     * @param fileStr
280
     * @return
281
     */
282
    private String[] getTaxonName(String fileStr) {
283
        String[] result = new String[2];
284
        fileStr = fileStr.split("\\.")[0];
285
        fileStr = fileStr.replaceAll("[0-9]", "");
286
        String[] x = fileStr.split("_");
287
        if (x.length == 2){
288
            result[1] = x[1];
289
        }
290

    
291
        fileStr = splitCamelCase(x[0]);
292
        String[] split = fileStr.split(" ");
293
        String name = split[0] + " " + split[1].toLowerCase() +
294
                (split.length > 2 ? " subsp. " + split[2].toLowerCase() : "");
295
        result[0] = name;
296
        System.out.println(result[0] + (result[1] != null ?  "   Artist: " + result[1]: ""));
297
        return result;
298
    }
299

    
300
    //from http://stackoverflow.com/questions/2559759/how-do-i-convert-camelcase-into-human-readable-names-in-java
301
    static String splitCamelCase(String s) {
302
        return s.replaceAll(
303
           String.format("%s",
304
//              "(?<=[A-Z])(?=[A-Z][a-z])",
305
              "(?<=[^A-Z])(?=[A-Z])"
306
//              "(?<=[A-Za-z])(?=[^A-Za-z])"
307
           ),
308
           " "
309
        );
310
     }
311

    
312
    /**
313
     * {@inheritDoc}
314
     */
315
    @Override
316
    protected boolean doCheck(SimpleExcelTaxonImportState<CONFIG> state) {
317
        return false;
318
    }
319

    
320
    /**
321
     * {@inheritDoc}
322
     */
323
    @Override
324
    protected boolean isIgnore(SimpleExcelTaxonImportState<CONFIG> state) {
325
        return ! state.getConfig().isDoImages();
326
    }
327

    
328

    
329

    
330
}
(5-5/18)