Project

General

Profile

Download (29.3 KB) Statistics
| Branch: | 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.app.cyprus;
11

    
12
import java.io.File;
13
import java.io.IOException;
14
import java.net.MalformedURLException;
15
import java.net.URI;
16
import java.net.URISyntaxException;
17
import java.util.ArrayList;
18
import java.util.HashMap;
19
import java.util.HashSet;
20
import java.util.Iterator;
21
import java.util.List;
22
import java.util.Map;
23
import java.util.Set;
24
import java.util.regex.Matcher;
25
import java.util.regex.Pattern;
26

    
27
import org.apache.commons.imaging.ImageReadException;
28
import org.apache.commons.imaging.Imaging;
29
import org.apache.commons.imaging.common.GenericImageMetadata.GenericImageMetadataItem;
30
import org.apache.commons.imaging.common.ImageMetadata;
31
import org.apache.commons.imaging.common.ImageMetadata.ImageMetadataItem;
32
import org.apache.log4j.Logger;
33
import org.joda.time.DateTime;
34
import org.joda.time.format.DateTimeFormat;
35
import org.joda.time.format.DateTimeFormatter;
36
import org.springframework.transaction.TransactionStatus;
37

    
38
import eu.etaxonomy.cdm.api.application.CdmApplicationController;
39
import eu.etaxonomy.cdm.api.service.config.MatchingTaxonConfigurator;
40
import eu.etaxonomy.cdm.app.common.CdmDestinations;
41
import eu.etaxonomy.cdm.common.UTF8;
42
import eu.etaxonomy.cdm.common.media.CdmImageInfo;
43
import eu.etaxonomy.cdm.database.DbSchemaValidation;
44
import eu.etaxonomy.cdm.database.ICdmDataSource;
45
import eu.etaxonomy.cdm.io.api.application.CdmIoApplicationController;
46
import eu.etaxonomy.cdm.io.common.utils.ImportDeduplicationHelper;
47
import eu.etaxonomy.cdm.io.mexico.SimpleExcelTaxonImportState;
48
import eu.etaxonomy.cdm.model.agent.AgentBase;
49
import eu.etaxonomy.cdm.model.agent.Institution;
50
import eu.etaxonomy.cdm.model.agent.Person;
51
import eu.etaxonomy.cdm.model.common.CdmBase;
52
import eu.etaxonomy.cdm.model.common.Language;
53
import eu.etaxonomy.cdm.model.common.TimePeriod;
54
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
55
import eu.etaxonomy.cdm.model.description.Feature;
56
import eu.etaxonomy.cdm.model.description.TaxonDescription;
57
import eu.etaxonomy.cdm.model.description.TextData;
58
import eu.etaxonomy.cdm.model.media.ImageFile;
59
import eu.etaxonomy.cdm.model.media.Media;
60
import eu.etaxonomy.cdm.model.media.MediaRepresentation;
61
import eu.etaxonomy.cdm.model.media.MediaRepresentationPart;
62
import eu.etaxonomy.cdm.model.media.Rights;
63
import eu.etaxonomy.cdm.model.media.RightsType;
64
import eu.etaxonomy.cdm.model.taxon.Synonym;
65
import eu.etaxonomy.cdm.model.taxon.Taxon;
66
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
67

    
68
/**
69
 * Creates CDM Media from images stored in the given path.
70
 *
71
 * Note: Currently adapted to also change from Scaler IIF API to default Scaler API.
72
 * Note2: updateMetadata() still needs to be adapted to support 3 MediaRepresentations
73
 *
74
 * @author a.mueller
75
 * @since 05.2017
76
 */
77
public class CyprusImagesActivator {
78
	private static final Logger logger = Logger.getLogger(CyprusImagesActivator.class);
79

    
80
	static final ICdmDataSource cdmDestination = CdmDestinations.local_cyprus();
81
//	static final ICdmDataSource cdmDestination = CdmDestinations.cdm_test_cyprus();
82
//	static final ICdmDataSource cdmDestination = CdmDestinations.cdm_production_cyprus();
83

    
84
	static boolean testOnly = false;
85
	static boolean update_notCreate = false;
86
	//if true, data will always be updated, if false, only missing data will be updated
87
	static boolean forceUpdate = false;
88

    
89
    private static final String path = "//media/digitalimages/EditWP6/Zypern/photos/";
90
    private static final String oldUrlPath = "https://pictures.bgbm.org/digilib/Scaler/IIIF/Cyprus!";
91
    private static final String newUrlPath = "https://pictures.bgbm.org/digilib/Scaler?fn=Cyprus/";
92
    private static final String oldPostfix = "/full/full/0/default.jpg";
93
    private static final String newPostfix = "&mo=file";
94
    private static final String mediumPostfix ="&mo=fit&dw=400&dh=400";
95
    private static final String smallPostfix ="&mo=fit&dw=200&dh=200";
96

    
97
    private ImportDeduplicationHelper<SimpleExcelTaxonImportState<?>> deduplicationHelper;
98

    
99
    private void doImport(ICdmDataSource cdmDestination){
100

    
101
		CdmApplicationController app = CdmIoApplicationController.NewInstance(cdmDestination, DbSchemaValidation.VALIDATE);
102
		TransactionStatus tx = app.startTransaction();
103

    
104
		deduplicationHelper = (ImportDeduplicationHelper)ImportDeduplicationHelper.NewInstance(app);
105

    
106
        File file = new File(path);
107
        String[] fileList = file.list();
108
        Set<String> notFound = new HashSet<>();
109

    
110
        String regEx = "([A-Z][a-z]+_[a-z\\-]{3,}(?:_s_[a-z\\-]{3,})?)_[A-F]\\d{1,2}\\.(?:jpg|JPG)";
111
        Pattern pattern = Pattern.compile(regEx);
112

    
113
        String start = "O";  //O
114
        String end = "Q";      //Q
115
        String startLetter = "";
116

    
117
        for (String fileName : fileList){
118
            if(fileName.compareToIgnoreCase(start) < 0 || fileName.compareToIgnoreCase(end) >= 0){
119
                continue;
120
            }
121
            Matcher matcher = pattern.matcher(fileName);
122
            if (matcher.matches() ){
123
//                System.out.println(fileName);
124
                if (!fileName.substring(0,3).equals(startLetter)){
125
                    startLetter = fileName.substring(0,3);
126
                    System.out.println(startLetter);
127
                }
128
                String taxonName = matcher.group(1);
129
                taxonName = taxonName.replace("_s_", " subsp. ").replace("_", " ");
130
                Taxon taxon = getAcceptedTaxon(app, taxonName);
131
                if (taxon == null){
132
                    if (!notFound.contains(taxonName)){
133
                        notFound.add(taxonName);
134
                        logger.warn("Taxon not found: " + taxonName);
135
                    }
136
                }else{
137
                    try {
138
                        handleTaxon(app, taxon, fileName);
139
                    } catch (Exception e) {
140
                        logger.error("Unhandled exception ("+e.getMessage()+") when reading file " + fileName +". File not imported: ");
141
                        e.printStackTrace();
142
                    }
143
                }
144
            }else{
145
                if (!fileName.matches("(?:\\.erez|Thumbs\\.db.*|zypern_.*|__Keywords_template\\.txt)")){
146
                    logger.warn("Incorrect filename:" + fileName);
147
                }else{
148
                    System.out.println("Not clear yet: " + fileName);
149
                }
150
            }
151
        }
152

    
153
//		app.getTaxonService().saveOrUpdate(taxaToSave);
154

    
155
		if (testOnly){
156
		    tx.setRollbackOnly();
157
		}
158
		app.commitTransaction(tx);
159
	}
160

    
161
    private void handleTaxon(CdmApplicationController app, Taxon taxon, String fileName) {
162
        Map<String, Media> existingUrls = getAllExistingUrls(taxon);
163
        String pathToOldImage = oldUrlPath + fileName + oldPostfix;
164

    
165
        String pathToFullImage = newUrlPath + fileName + newPostfix;
166
        String pathToMediumImage = newUrlPath + fileName + mediumPostfix;
167
        String pathToSmallImage = newUrlPath + fileName + smallPostfix;
168

    
169
        if (containsAll(existingUrls, pathToFullImage, pathToMediumImage, pathToSmallImage)){
170
            return;
171
        }else{
172
            Media media;
173
            if (containsAny(existingUrls, pathToOldImage, pathToMediumImage, pathToSmallImage)){
174
                media = getExistingMedia(existingUrls, pathToOldImage, pathToMediumImage, pathToSmallImage);
175
                if (media == null){
176
                    return;
177
                }else if (media.getAllTitles().isEmpty()){
178
                    media.setTitleCache(null, false);
179
                    media.putTitle(Language.LATIN(), fileName);
180
                }
181
            }else{
182
                media = Media.NewInstance();
183
                makeMetaData(media, fileName, false);
184
                makeTitle(media, fileName, false);
185
                if (!testOnly){
186
                    makeTextData(fileName, media, taxon);
187
                }
188
            }
189
            fillMediaWithAllRepresentations(media, pathToFullImage, pathToMediumImage, pathToSmallImage, pathToOldImage);
190
        }
191
    }
192

    
193
    private Media getExistingMedia(Map<String, Media> existingUrls, String pathToFullImage, String pathToMediumImage,
194
            String pathToSmallImage) {
195
        Set<Media> result = new HashSet<>();
196
        for(String existingUrl : existingUrls.keySet()){
197
            if (existingUrl.equals(pathToFullImage) || existingUrl.equals(pathToMediumImage) ||
198
                    existingUrl.equals(pathToSmallImage)){
199
                result.add(existingUrls.get(existingUrl));
200
            }
201
        }
202
        if (result.isEmpty()){
203
            logger.warn("Media for existing URL not found. This should not happen.");
204
            return null;
205
        }else if (result.size() > 1){
206
            logger.warn("Existing URLs have more than 1 Media. This should not happen.");
207
            return null;
208
        }else{
209
            return result.iterator().next();
210
        }
211
    }
212

    
213
    /**
214
     * <code>true</code> if all 3 paths exist in the URL set
215
     */
216
    private boolean containsAll(Map<String, Media> existingUrlMap, String pathToFullImage, String pathToMediumImage,
217
            String pathToSmallImage) {
218
        Set<String> existingUrls = existingUrlMap.keySet();
219
        return existingUrls.contains(pathToFullImage) && existingUrls.contains(pathToMediumImage)
220
                && existingUrls.contains(pathToSmallImage);
221
    }
222

    
223
    /**
224
     * <code>true</code> if any of the 3 paths exists in the URL set
225
     */
226
    private boolean containsAny(Map<String, Media> existingUrlMap, String pathToFullImage, String pathToMediumImage,
227
            String pathToSmallImage) {
228
        Set<String> existingUrls = existingUrlMap.keySet();
229
        return existingUrls.contains(pathToFullImage) || existingUrls.contains(pathToMediumImage)
230
                || existingUrls.contains(pathToSmallImage);
231
    }
232

    
233
    private void makeTitle(Media media, String fileName, boolean updateOnly) {
234
        String title = fileName.replace("_s_"," subsp. ")
235
                .replace("_"," ").replace(".jpg","").replace(".JPG","");
236
        if ( (!updateOnly) || media.getAllTitles().isEmpty()){
237
            media.putTitle(Language.LATIN(), title);
238
        }
239
    }
240

    
241
    private void makeMetaData(Media media, String fileName, boolean updateOnly) {
242

    
243
        File file = new File(path + fileName);
244
        if (!file.exists()){
245
            logger.warn("File for filename " +  fileName + " does not exist.");
246
            return;
247
        }
248

    
249
        Map<String, String> keywords = new HashMap<>();
250
        String copyright = null;
251
        String artistStr = null;
252
        String created = null;
253
        try{
254
//            IImageMetadata metadata = Sanselan.getMetadata(file);
255
            ImageMetadata metadata = Imaging.getMetadata(file);
256
            List<? extends ImageMetadataItem> items = metadata.getItems();
257
            for (Object object : items){
258
                ImageMetadataItem metadataItem = (ImageMetadataItem) object;
259
//                System.out.println(item.getKeyword() +  ":    " + item.getText());
260
                if (metadataItem instanceof GenericImageMetadataItem){
261
                    GenericImageMetadataItem item = (GenericImageMetadataItem) metadataItem;
262

    
263
                    String keyword = item.getKeyword().toLowerCase();
264
                    String value =removeQuots(item.getText());
265

    
266
                    if("keywords".equals(keyword)){
267
                        String[] splits = value.split(":");
268
                        if (splits.length == 2){
269
                            keywords.put(splits[0].trim().toLowerCase(), splits[1].trim());
270
                        }else{
271
                            logger.warn("Keyword has not correct format and can not be parsed: " + value +  "  for file " + fileName);
272
                        }
273
                    }else if ("Copyright Notice".equalsIgnoreCase(keyword)){
274
                        copyright = value;
275
                    }else if ("artist".equals(keyword)){
276
                        artistStr = value;
277
                    }else if ("date time original".equalsIgnoreCase(item.getKeyword())){
278
                        created = value;
279
                    }
280
                }
281
            }
282
        } catch (ImageReadException | IOException e1) {
283
            logger.warn("       Problem (" + e1.getMessage() + ") when reading metadata from file: " + fileName);
284
            e1.printStackTrace();
285
        }
286

    
287
        AgentBase<?> artistAgent = null;
288
        Rights right = null;
289
        DateTime createdDate = null;
290
        String locality = null;
291

    
292
        //artist
293
        if (keywords.get("photographer") != null){
294
            String artist = keywords.get("photographer");
295
            artistAgent = makePerson(artist, fileName);
296
        }
297
        if (artistStr != null){
298
            if (keywords.get("photographer") == null){
299
                artistAgent = makePerson(artistStr, fileName);
300
            }else if (!keywords.get("photographer").toLowerCase().replace(" ", "")
301
                    .contains(artistStr.toLowerCase().replace(" ", ""))){
302
                logger.warn("Artist '" + artistStr + "' could not be handled for " + fileName);
303
            }
304
        }
305

    
306
        //locality
307
        if (keywords.get("locality") != null){
308
            locality = keywords.get("locality");
309
        }
310

    
311
        //copyright
312
        if (copyright != null){
313
            AgentBase<?> agent;
314
            if (copyright.equals("Botanic Garden and Botanical Museum Berlin-Dahlem (BGBM)")){
315
                agent = Institution.NewNamedInstance(copyright);
316
            }else{
317
                agent = makePerson(copyright, fileName);
318
            }
319
            right = Rights.NewInstance(null, null, RightsType.COPYRIGHT());
320
            right.setAgent(agent);
321
            right = deduplicationHelper.getExistingCopyright(null, right);
322
        }
323

    
324
        //created
325
        if (created != null){
326
            DateTimeFormatter f = DateTimeFormat.forPattern("yyyy:MM:dd HH:mm:ss");
327
            try {
328
                createdDate = f/*.withZone(DateTimeZone.forID("Europe/Athens"))*/.parseDateTime(created);
329
            } catch (Exception e) {
330
                logger.warn("Exception (" + e.getMessage() + ") when parsing create date " + created + " for file " + fileName);
331
            }
332
        }
333

    
334
        boolean force = !updateOnly || forceUpdate;
335
        //add to media
336
        if (artistAgent != null && (force || media.getArtist() == null)){
337
            media.setArtist(artistAgent);
338
        }
339
        if (right != null && (force || media.getRights().isEmpty())){
340
            media.removeRights(right);
341
            media.addRights(right);
342
        }
343
        if (createdDate != null && (force || media.getMediaCreated() == null)){
344
            media.setMediaCreated(TimePeriod.NewInstance(createdDate));
345
        }
346
        if (locality != null && (force || media.getDescription(Language.ENGLISH()) == null)){
347
            media.putDescription(Language.ENGLISH(), locality);
348
        }
349
    }
350

    
351
    private Person makePerson(String artist, String fileName) {
352
        artist = artist.trim();
353
        String regEx = "((?:[A-Z]\\. ?)+)([A-Z][a-z\\-\u00E4\u00F6\u00FC]+)";
354
        Matcher matcher = Pattern.compile(regEx).matcher(artist);
355
        Person person = Person.NewInstance();
356
        if (matcher.matches()){
357
            person.setGivenName(matcher.group(1).trim());
358
            person.setFamilyName(matcher.group(2).trim());
359
        }else{
360
            person.setTitleCache(artist, true);
361
            logger.warn("Person could not be parsed: " + artist + " for file " + fileName);
362
        }
363

    
364
        person = deduplicationHelper.getExistingAuthor(null, person);
365
        return person;
366
    }
367

    
368
    private String removeQuots(String text) {
369
        if (text.startsWith("'") && text.endsWith("'")){
370
            return text.substring(1, text.length() -1);
371
        }else{
372
            return text;
373
        }
374
    }
375

    
376
    private void makeTextData(String fileStr, Media media, Taxon taxon) {
377
        TaxonDescription imageGallery = taxon.getImageGallery(true);
378
        TextData textData = null;
379
        if (!imageGallery.getElements().isEmpty()){
380
            DescriptionElementBase el = imageGallery.getElements().iterator().next();
381
            if (el.isInstanceOf(TextData.class)){
382
                textData = CdmBase.deproxy(el, TextData.class);
383
            }else{
384
                logger.warn("Image gallery had non-textdata description element: " +  fileStr);
385
            }
386
        }
387
        if (textData == null){
388
            textData = TextData.NewInstance();
389
            textData.setFeature(Feature.IMAGE());
390
        }
391
        imageGallery.addElement(textData);
392
        textData.addMedia(media);
393
    }
394

    
395
    private void fillMediaWithAllRepresentations(Media media, String fullPath, String mediumPath, String smallPath, String oldFullPath){
396
        Set<MediaRepresentation> existingRepresentations = new HashSet<>(media.getRepresentations());
397
        makeMediaRepresentation(oldFullPath, media, existingRepresentations, fullPath);
398
        makeMediaRepresentation(mediumPath, media, existingRepresentations, null);
399
        makeMediaRepresentation(smallPath, media, existingRepresentations, null);
400
        if(!existingRepresentations.isEmpty()){
401
            logger.warn("Media contains existing representations which are not contained in the 3 paths: " + media.getTitleCache());
402
        }
403
    }
404

    
405
    private void makeMediaRepresentation(String uriString, Media media,
406
            Set<MediaRepresentation> existingRepresentations, String replaceUri) {
407
        MediaRepresentation existingMediaRep = getExistingMediaRepresentation(uriString, existingRepresentations);
408
        boolean readMediaData = true;
409
        MediaRepresentation newMediaRep = makeMediaRepresentation(replaceUri != null? replaceUri : uriString, readMediaData);
410
        if (existingMediaRep == null){
411
            media.addRepresentation(newMediaRep);
412
        }else{
413
            existingRepresentations.remove(existingMediaRep);
414
            mergeToExistingRepresentation(existingMediaRep, newMediaRep);
415
        }
416
    }
417

    
418
    private void mergeToExistingRepresentation(MediaRepresentation existingMediaRep, MediaRepresentation newMediaRep) {
419
        existingMediaRep.setMimeType(newMediaRep.getMimeType());
420
        existingMediaRep.setSuffix(newMediaRep.getSuffix());
421
        if(!existingMediaRep.getParts().isEmpty() && !newMediaRep.getParts().isEmpty()){
422
            MediaRepresentationPart existingPart = existingMediaRep.getParts().iterator().next();
423
            ImageFile newPart = (ImageFile)newMediaRep.getParts().iterator().next();
424
            if(existingPart.isInstanceOf(ImageFile.class)){
425
                ImageFile existingImage = CdmBase.deproxy(existingPart, ImageFile.class);
426
                existingImage.setHeight(newPart.getHeight());
427
                existingImage.setWidth(newPart.getWidth());
428
            }else{
429
                logger.warn("MediaRepresentationPart was not of type ImageFile. Height and width not merged: " + existingPart.getUri());
430
            }
431
            existingPart.setSize(newPart.getSize());
432
            existingPart.setUri(newPart.getUri());
433
        }
434
    }
435

    
436
    private MediaRepresentation getExistingMediaRepresentation(String uriString,
437
            Set<MediaRepresentation> existingRepresentations) {
438
        for (MediaRepresentation rep : existingRepresentations){
439
            for (MediaRepresentationPart part : rep.getParts()){
440
                if (part.getUri() != null && part.getUri().toString().equals(uriString)){
441
                    return rep;
442
                }
443
            }
444
        }
445
        return null;
446
    }
447

    
448
    /**
449
     * Creates
450
     * @see #READ_MEDIA_DATA
451
     * @return
452
     * @throws MalformedURLException
453
     */
454
    protected Media getImageMedia(String uriString, String uriStrThumb, boolean readMediaData) throws MalformedURLException {
455
        if( uriString == null){
456
            return null;
457
        } else {
458
            uriString = uriString.replace(" ", "%20");  //replace whitespace
459
            try {
460
                MediaRepresentation representation = makeMediaRepresentation(uriString, readMediaData);
461
                Media media = Media.NewInstance();
462
                media.addRepresentation(representation);
463

    
464
                if (uriStrThumb != null){
465
                    CdmImageInfo imageInfoThumb = null;
466
                    uriStrThumb = uriStrThumb.replace(" ", "%20");  //replace whitespace
467
                    URI uriThumb = new URI(uriStrThumb);
468
                    try {
469
                        if (readMediaData){
470
                            logger.info("Read media data from: " + uriThumb);
471
                            imageInfoThumb = CdmImageInfo.NewInstance(uriThumb, 0);
472
                        }
473
                    } catch (Exception e) {
474
                        String message = "An error occurred when trying to read image meta data for " + uriThumb.toString() + ": " +  e.getMessage();
475
                        logger.warn(message);
476
                    }
477

    
478
                    ImageFile imageFileFhumb = ImageFile.NewInstance(uriThumb, null, imageInfoThumb);
479
                    MediaRepresentation reprThumb = MediaRepresentation.NewInstance();
480
                    if(imageInfoThumb != null){
481
                        reprThumb.setMimeType(imageInfoThumb.getMimeType());
482
                        reprThumb.setSuffix(imageInfoThumb.getSuffix());
483
                    }
484
                    reprThumb.addRepresentationPart(imageFileFhumb);
485
                    media.addRepresentation(reprThumb);
486
                }
487

    
488
                return media;
489
            } catch (URISyntaxException e1) {
490
                String message = "An URISyntaxException occurred when trying to create uri from multimedia objcet string: " +  uriString;
491
                logger.warn(message);
492
                return null;
493
            }
494
        }
495
    }
496

    
497
    private MediaRepresentation makeMediaRepresentation(String uriString, boolean readMediaData) {
498

    
499
        uriString = uriString.replace(" ", "%20");  //replace whitespace
500
        CdmImageInfo imageInfo = null;
501
        URI uri;
502
        try {
503
            uri = new URI(uriString);
504
        } catch (URISyntaxException e1) {
505
            logger.error("Malformed URI. Could not create media representation: " + uriString);
506
            return null;
507
        }
508
        try {
509
            if (readMediaData){
510
                logger.info("Read media data from: " + uri);
511
                imageInfo = CdmImageInfo.NewInstance(uri, 0);
512
            }
513
        } catch (Exception e) {
514
            try {
515
                //try again
516
                imageInfo = CdmImageInfo.NewInstance(uri, 0);
517
            } catch (Exception e1) {
518
                String message = "An error occurred when trying to read image meta data for " + uri.toString() + ": " +  e1.getMessage();
519
                e1.printStackTrace();
520
                logger.warn(message);
521
            }
522
        }
523
        ImageFile imageFile = ImageFile.NewInstance(uri, null, imageInfo);
524

    
525
        MediaRepresentation representation = MediaRepresentation.NewInstance();
526

    
527
        if(imageInfo != null){
528
            representation.setMimeType(imageInfo.getMimeType());
529
            representation.setSuffix(imageInfo.getSuffix());
530
        }
531
        representation.addRepresentationPart(imageFile);
532
        return representation;
533
    }
534

    
535
    private Map<String, Media> getAllExistingUrls(Taxon taxon) {
536
        Map<String, Media> result = new HashMap<>();
537
        Set<TaxonDescription> descriptions = taxon.getDescriptions();
538
        for (TaxonDescription td : descriptions){
539
            if (td.isImageGallery()){
540
                for (DescriptionElementBase deb : td.getElements()){
541
                    if (deb.isInstanceOf(TextData.class)){
542
                        TextData textData = CdmBase.deproxy(deb, TextData.class);
543
                        for (Media media :textData.getMedia()){
544
                            for (MediaRepresentation rep : media.getRepresentations()){
545
                                for (MediaRepresentationPart part : rep.getParts()){
546
                                    URI uri = part.getUri();
547
                                    if (uri != null){
548
                                        String uriStr = uri.toString();
549
                                        result.put(uriStr, media);
550
                                    }
551
                                }
552
                            }
553
                        }
554
                    }
555
                }
556
            }
557
        }
558
        return result;
559
    }
560

    
561
    private Taxon getAcceptedTaxon(CdmApplicationController app, String taxonNameStr) {
562

    
563
        MatchingTaxonConfigurator config = new MatchingTaxonConfigurator();
564
        taxonNameStr = adaptName(taxonNameStr);
565
        config.setTaxonNameTitle(taxonNameStr);
566
        config.setIncludeSynonyms(false);
567
        List<TaxonBase> list = app.getTaxonService().findTaxaByName(config);
568
        if (list.isEmpty()){
569
//            logger.warn("Taxon not found for media: " + taxonNameStr);
570
            taxonNameStr = taxonNameStr.replaceFirst(" ", " " + UTF8.HYBRID.toString());
571
            config.setTaxonNameTitle(taxonNameStr);
572
            list = app.getTaxonService().findTaxaByName(config);
573
            if (list.isEmpty()){
574
                return null;
575
            }else if (list.size() > 1){
576
                logger.warn("After searching for hybrids more than 1 taxon was foung: " + taxonNameStr);
577
            }
578
        }
579
        if (list.size()>1){
580
            Iterator<TaxonBase> it = list.iterator();
581
            while (it.hasNext()){
582
                Taxon next = (Taxon)it.next();
583
                if (next.getTaxonNodes().isEmpty() && !next.getTaxaForMisappliedName(true).isEmpty()){
584
                    it.remove();
585
                }
586
            }
587
            if (list.size()>1){
588
                logger.warn("More than 1 taxon found for media: " + taxonNameStr + " . Will now try to use only taxon with taxon node.");
589
                it = list.iterator();
590
                while (it.hasNext()){
591
                    Taxon next = (Taxon)it.next();
592
                    if (next.getTaxonNodes().isEmpty()){
593
                        it.remove();
594
                    }
595
                }
596
                if (list.size()>1){
597
                    logger.warn("Still more than 1 taxon found for media: " + taxonNameStr);
598
                }else if (list.size() < 1){
599
                    logger.warn("After removing nodeless taxa no taxon was left: " +  taxonNameStr);
600
                    return null;
601
                }
602
            }else if (list.size() < 1){
603
                logger.warn("After removing misapplications no taxon was left: " +  taxonNameStr);
604
                return null;
605
            }
606
        }
607
        TaxonBase<?> taxonBase = list.get(0);
608
        Taxon result;
609
        if (taxonBase.isInstanceOf(Synonym.class)){
610
            result = CdmBase.deproxy(taxonBase, Synonym.class).getAcceptedTaxon();
611
        }else{
612
            result = CdmBase.deproxy(taxonBase, Taxon.class);
613
        }
614
        return result;
615
    }
616

    
617
    private String adaptName(String taxonNameStr) {
618
//        if (taxonNameStr.equals("Hypericum cerastoides")){
619
//            taxonNameStr = "Hypericum cerastioides";
620
//        }
621
        return taxonNameStr;
622
    }
623

    
624
	private void test(){
625
	    File f = new File(path);
626
	    String[] list = f.list();
627
	    List<String> fullFileNames = new ArrayList<>();
628
	    for (String fileName : list){
629
	        fullFileNames.add(path + fileName);
630
	        if (! fileName.matches("([A-Z][a-z]+_[a-z\\-]{3,}(?:_s_[a-z\\-]{3,})?)_[A-F]\\d{1,2}\\.(jpg|JPG)")){
631
	            System.out.println(fileName);
632
	        }
633
	    }
634
	}
635

    
636
	private void updateMetadata(ICdmDataSource cdmDestination){
637
        CdmApplicationController app = CdmIoApplicationController.NewInstance(cdmDestination, DbSchemaValidation.VALIDATE);
638
        TransactionStatus tx = app.startTransaction();
639

    
640
        deduplicationHelper = (ImportDeduplicationHelper<SimpleExcelTaxonImportState<?>>)ImportDeduplicationHelper.NewInstance(app);
641

    
642
        List<Media> list = app.getMediaService().list(Media.class, null, null, null, null);
643
        for (Media media : list){
644
            String fileName = getUrlStringForMedia(media);
645
            if (fileName.startsWith(newUrlPath)){
646
                //TODO not yet adapted to new image server URLs
647
                fileName = fileName.replace(newUrlPath, "");
648
                if (fileName.equals("Acinos_exiguus_C1.jpg")){  //for debugging only
649
//                  System.out.println(fileName);
650
                    makeMetaData(media, fileName, true);
651
                    makeTitle(media, fileName, true);
652
                }
653
            }else{
654
                logger.warn("Filename does not start with standard url path: " + fileName);
655
            }
656
        }
657

    
658
        if (testOnly){
659
            tx.setRollbackOnly();
660
        }
661
        app.commitTransaction(tx);
662
	}
663

    
664
    private String getUrlStringForMedia(Media media) {
665
        String result = null;
666
        for (MediaRepresentation rep : media.getRepresentations()){
667
            for (MediaRepresentationPart part : rep.getParts()){
668
                URI uri = part.getUri();
669
                if (uri != null){
670
                    if (result != null){
671
                        //TODO this still needs to be adapted to the 3 representations of media
672
                        logger.warn("More than 1 uri exists for media "+ media.getId());
673
                    }else{
674
                        result = uri.toString();
675
                    }
676
                }
677
            }
678
        }
679
        return result;
680
    }
681

    
682
	public static void main(String[] args) {
683
		CyprusImagesActivator me = new CyprusImagesActivator();
684
		if (update_notCreate){
685
		    me.updateMetadata(cdmDestination);
686
		}else{
687
		    me.doImport(cdmDestination);
688
		}
689
//		me.test();
690
		System.exit(0);
691
	}
692
}
(3-3/4)