Project

General

Profile

Download (12.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.io;
11

    
12
import java.io.File;
13
import java.io.IOException;
14
import java.net.MalformedURLException;
15
import java.net.URL;
16
import java.util.ArrayList;
17
import java.util.HashMap;
18
import java.util.List;
19
import java.util.Map;
20

    
21
import org.apache.commons.imaging.ImageInfo;
22
import org.apache.commons.imaging.ImageReadException;
23
import org.apache.commons.imaging.Imaging;
24
import org.apache.commons.imaging.common.GenericImageMetadata.GenericImageMetadataItem;
25
import org.apache.commons.imaging.common.ImageMetadata;
26
import org.apache.commons.imaging.common.ImageMetadata.ImageMetadataItem;
27
import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata;
28
import org.apache.log4j.Logger;
29
import org.springframework.stereotype.Component;
30

    
31
import eu.etaxonomy.cdm.app.images.AbstractImageImporter;
32
import eu.etaxonomy.cdm.app.images.ImageImportState;
33
import eu.etaxonomy.cdm.common.URI;
34
import eu.etaxonomy.cdm.model.agent.AgentBase;
35
import eu.etaxonomy.cdm.model.agent.Person;
36
import eu.etaxonomy.cdm.model.common.CdmBase;
37
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
38
import eu.etaxonomy.cdm.model.description.Feature;
39
import eu.etaxonomy.cdm.model.description.TaxonDescription;
40
import eu.etaxonomy.cdm.model.description.TextData;
41
import eu.etaxonomy.cdm.model.media.ImageFile;
42
import eu.etaxonomy.cdm.model.media.Media;
43
import eu.etaxonomy.cdm.model.media.MediaRepresentation;
44
import eu.etaxonomy.cdm.model.media.Rights;
45
import eu.etaxonomy.cdm.model.media.RightsType;
46
import eu.etaxonomy.cdm.model.reference.Reference;
47
import eu.etaxonomy.cdm.model.taxon.Taxon;
48
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
49
import eu.etaxonomy.cdm.strategy.match.DefaultMatchStrategy;
50
import eu.etaxonomy.cdm.strategy.match.IMatchStrategyEqual;
51

    
52
/**
53
 * TODO not working at the moment
54
 *
55
 * @author n.hoffmann
56
 * @since 18.11.2008
57
 */
58
@Component
59
public class PalmaeImageImport extends AbstractImageImporter {
60

    
61
    private static final long serialVersionUID = 1226643507245147417L;
62

    
63
    private static final Logger logger = Logger.getLogger(PalmaeImageImport.class);
64

    
65
	enum MetaData{
66
		NAME,
67
		ARTIST,
68
		COPYRIGHT,
69
		COPYRIGHTNOTICE,
70
		OBJECTNAME
71
	}
72

    
73
	private static int modCount = 300;
74

    
75
	private static String pluralString = "images";
76

    
77
	/**
78
	 * Rudimetary implementation using apache sanselan. This implementation depends
79
	 * on the metadata standards used in the palmae images. The IPTC field ObjectName
80
	 * contains a string like this: "Arecaceae; Eugeissona utilis". The string
81
	 * in front of the semicolon is the family name and the one behind, the taxon name.
82
	 * So we basically assume, that if the string gets split by ";" the element at
83
	 * index 1 should be the taxon name.
84
	 * If this format changes this method breaks!
85
	 *
86
	 * TODO The ImageMetaData class of the commons package should provide
87
	 * convenient access to the metadata of an image as well as all the error handling
88
	 *
89
	 * @param imageFile
90
	 * @return the name of the taxon as stored in ObjectName IPTC tag
91
	 */
92
	public String retrieveTaxonNameFromImageMetadata(File imageFile){
93
		String name = null;
94

    
95
		ImageMetadata metadata = null;
96

    
97
		try {
98
			metadata = Imaging.getMetadata(imageFile);
99
		} catch (ImageReadException e) {
100
			logger.error("Error reading image" + " in " + imageFile.getName(), e);
101
		} catch (IOException e) {
102
			logger.error("Error reading file"  + " in " + imageFile.getName(), e);
103
		}
104

    
105
		if(metadata instanceof JpegImageMetadata){
106
			JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata;
107

    
108
			for (ImageMetadataItem metadataItem : jpegMetadata.getItems()){
109
                if (metadataItem instanceof GenericImageMetadataItem){
110
                    GenericImageMetadataItem item = (GenericImageMetadataItem) metadataItem;
111
    				if(item.getKeyword().equals("ObjectName")){
112
    					logger.debug("File: " + imageFile.getName() + ". ObjectName string is: " + item.getText());
113
    					String[] objectNameSplit = item.getText().split(";");
114

    
115
    					try {
116
    						name = objectNameSplit[1].trim();
117
    					} catch (ArrayIndexOutOfBoundsException e) {
118
    						logger.warn("ObjectNameSplit has no second part: " + item.getText() + " in " + imageFile.getName());
119
    						//throw e;
120
    					}
121
    				}
122
                }else{
123
                    throw new IllegalStateException("Unsupported ImageMetadataItem type: " +  metadataItem.getClass().getName());
124
                }
125
			}
126
		}
127

    
128

    
129
		return name;
130
	}
131

    
132
	private Map<MetaData, String> getMetaData(File imageFile, List<MetaData> metaData){
133
		HashMap<MetaData, String> result = new HashMap<>();
134

    
135
		ImageMetadata metadata = null;
136
		List<String> metaDataStrings = new ArrayList<>();
137

    
138
		for (MetaData data: metaData){
139
			metaDataStrings.add(data.name().toLowerCase());
140
		}
141

    
142
		try {
143
			metadata = Imaging.getMetadata(imageFile);
144
		} catch (ImageReadException e) {
145
			logger.error("Error reading image" + " in " + imageFile.getName(), e);
146
		} catch (IOException e) {
147
			logger.error("Error reading file"  + " in " + imageFile.getName(), e);
148
		}
149

    
150
		if(metadata instanceof JpegImageMetadata){
151
			JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata;
152

    
153
			for (ImageMetadataItem metadataItem : jpegMetadata.getItems()){
154
               if (metadataItem instanceof GenericImageMetadataItem){
155
                    GenericImageMetadataItem item = (GenericImageMetadataItem) metadataItem;
156
    				if(metaDataStrings.contains(item.getKeyword().toLowerCase())){
157
    					logger.debug("File: " + imageFile.getName() + ". "+ item.getKeyword() +"string is: " + item.getText());
158
    					result.put(MetaData.valueOf(item.getKeyword().toUpperCase()), item.getText());
159
    				}
160
               }else{
161
                   throw new IllegalStateException("Unsupported ImageMetadataItem type: " + metadataItem.getClass().getName());
162
               }
163
			}
164
		}
165

    
166
		return result;
167
	}
168

    
169
	@Override
170
    protected void invokeImageImport (ImageImportState state){
171

    
172
		logger.info("Importing images from directory: " + state.getConfig().getSourceNameString());
173

    
174
		File sourceFolder = new File(state.getConfig().getSource().getJavaUri());
175
		String taxonName;
176
		if(sourceFolder.isDirectory()){
177
			int count = 0;
178
			for( File file : sourceFolder.listFiles()){
179
				if(file.isFile()){
180
					doCount(count++, modCount, pluralString);
181

    
182
					taxonName= retrieveTaxonNameFromImageMetadata(file);
183
					logger.debug("Looking up taxa with taxon name: " + taxonName);
184

    
185
					//TODO:
186
					ArrayList<MetaData> metaDataList = new ArrayList<>();
187
					metaDataList.add (MetaData.ARTIST);
188
					metaDataList.add (MetaData.COPYRIGHT);
189
					metaDataList.add (MetaData.COPYRIGHTNOTICE);
190
					metaDataList.add (MetaData.OBJECTNAME);
191
					//metaDataList.add (MetaData.NAME);
192

    
193
					Map<MetaData, String> metaData = getMetaData(file, metaDataList);
194

    
195

    
196

    
197
					Reference sec = referenceService.find(state.getConfig().getSecUuid());
198

    
199
					List<TaxonBase> taxa = new ArrayList<>();
200
					if (taxonName != null){
201
						taxa = taxonService.searchByName(taxonName, true, sec);
202
					}else{
203
						logger.error("TaxonName is null "  + " in " + file.getName());
204
					}
205
					if(taxa.size() == 0){
206
						logger.warn("no taxon with this name found: " + taxonName + " in " + file.getName());
207
					}else if(taxa.size() > 1){
208
						logger.error(taxa);
209
						logger.error("multiple taxa with this name found: " + taxonName + " in " + file.getName());
210
					}else{
211
						Taxon taxon = (Taxon) taxa.get(0);
212

    
213
						taxonService.saveOrUpdate(taxon);
214

    
215
						//MetaDataFactory metaDataFactory = MetaDataFactory.getInstance();
216
						//ImageMetaData imageMetaData = (ImageMetaData) metaDataFactory.readMediaData(file.toURI(), MimeType.IMAGE);
217
						try{
218
						ImageInfo imageinfo = Imaging.getImageInfo(file);
219

    
220
						String mimeType = imageinfo.getMimeType();
221
						String suffix = "jpg";
222

    
223
						// URL for this image
224
						URL url = null;
225
						try {
226
							url = new URL(state.getConfig().getMediaUrlString() + file.getName());
227
						} catch (MalformedURLException e) {
228
							logger.warn("URL is malformed: "+ url);
229
						}
230

    
231
						ImageFile imageFile = ImageFile.NewInstance(URI.fromUrl(url),null, imageinfo.getHeight(), imageinfo.getWidth());
232

    
233
						MediaRepresentation representation = MediaRepresentation.NewInstance(mimeType, suffix);
234
						representation.addRepresentationPart(imageFile);
235

    
236
						Media media = Media.NewInstance();
237
						media.addRepresentation(representation);
238
						if (metaData.containsKey(MetaData.OBJECTNAME)){
239
							media.setTitleCache(metaData.get(MetaData.OBJECTNAME).replace("'", ""), true);
240
						}
241
						//TODO: add the rights and the author:
242
						Person artist = null;
243
						if (metaData.containsKey(MetaData.ARTIST)){
244
							//TODO search for the person first and then create the object...
245
							artist = Person.NewTitledInstance(metaData.get(MetaData.ARTIST).replace("'", ""));
246
							artist.setGivenName(getGivenName(metaData.get(MetaData.ARTIST)).replace("'", ""));
247
							artist.setFamilyName(getFamilyName(metaData.get(MetaData.ARTIST)).replace("'", ""));
248

    
249
							IMatchStrategyEqual matchStrategy = DefaultMatchStrategy.NewInstance(AgentBase.class);
250
							try{
251
								List<Person> agents = commonService.findMatching(artist, matchStrategy);
252

    
253
								if (agents.size()!= 0){
254
									artist = agents.get(0);
255
								}
256
							}catch(eu.etaxonomy.cdm.strategy.match.MatchException e){
257
								logger.warn("MatchException occurred");
258
							}
259

    
260
							media.setArtist(artist);
261
						}
262

    
263
						if (metaData.containsKey(MetaData.COPYRIGHT)){
264
							//TODO: maybe search for the identic right...
265
							Rights copyright = Rights.NewInstance();
266
							copyright.setType(RightsType.COPYRIGHT());
267
							Person copyrightOwner;
268
							if (artist != null && !artist.getFamilyName().equalsIgnoreCase(getFamilyName(metaData.get(MetaData.COPYRIGHT)))){
269
								copyrightOwner = Person.NewInstance();
270

    
271
								copyrightOwner.setGivenName(getGivenName(metaData.get(MetaData.COPYRIGHT)));
272
								copyrightOwner.setFamilyName(getFamilyName(metaData.get(MetaData.COPYRIGHT)));
273
							}else
274
							{
275
								copyrightOwner = artist;
276
							}
277
							copyright.setAgent(copyrightOwner);
278
							//IMatchStrategy matchStrategy = DefaultMatchStrategy.NewInstance(Rights.class);
279
							media.addRights(copyright);
280
						}
281

    
282
						Reference sourceRef = state.getConfig().getSourceReference();
283
						TaxonDescription description = taxon.getOrCreateImageGallery(sourceRef == null ? null :sourceRef.getTitleCache());
284

    
285

    
286
						TextData textData = null;
287
						for (DescriptionElementBase element : description.getElements()){
288
							if (element.isInstanceOf(TextData.class)){
289
								textData = CdmBase.deproxy(element, TextData.class);
290
							}
291
						}
292
						if (textData == null){
293
							textData = TextData.NewInstance();
294
						}
295

    
296

    
297
						textData.addMedia(media);
298

    
299
						textData.setFeature(Feature.IMAGE());
300

    
301
						description.addElement(textData);
302

    
303
						taxonService.saveOrUpdate(taxon);
304
						}catch(Exception e) {
305
							e.printStackTrace();
306
						}
307
					}
308
				}
309
			}
310
		}else{
311
			logger.error("given source folder is not a directory");
312
		}
313
		return;
314
	}
315

    
316
	private String getGivenName(String artist){
317
		if (artist == null){
318
			return "";
319
		}
320
		if (!artist.contains(" ")) {
321
			return "";
322
		}
323
		if (artist.contains(",")){
324
			String [] artistSplits = artist.split(",");
325
			artist = artistSplits[0];
326
		}
327

    
328
		try{
329
		return artist.substring(0, artist.lastIndexOf(' ')).replace("'", "");
330
		}catch (Exception e){
331
			return "";
332
		}
333
	}
334

    
335
	private String getFamilyName(String artist){
336

    
337
		if (artist.contains(",")){
338
			String [] artistSplits = artist.split(",");
339
			artist = artistSplits[0];
340

    
341
		}
342
		if (!artist.contains(" ")) {
343

    
344
			return artist;
345
		}
346
		try{
347
		return artist.substring(artist.lastIndexOf(' ')).replace(" ", "");
348
		}
349
		catch(Exception e){
350
			return "";
351
		}
352
	}
353

    
354
	protected void doCount(int count, int modCount, String pluralString){
355
		if ((count % modCount ) == 0 && count!= 0 ){ logger.info(pluralString + " handled: " + (count));}
356
	}
357
}
(1-1/3)