Project

General

Profile

Download (11.7 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.URI;
16
import java.net.URL;
17
import java.util.ArrayList;
18
import java.util.HashMap;
19
import java.util.List;
20
import java.util.Map;
21
import java.util.Set;
22
import java.util.Map.Entry;
23

    
24
import org.apache.log4j.Logger;
25
import org.apache.sanselan.ImageInfo;
26
import org.apache.sanselan.ImageReadException;
27
import org.apache.sanselan.Sanselan;
28
import org.apache.sanselan.common.IImageMetadata;
29
import org.apache.sanselan.common.ImageMetadata.Item;
30
import org.apache.sanselan.formats.jpeg.JpegImageMetadata;
31
import org.springframework.stereotype.Component;
32

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

    
53
/**
54
 * TODO not working at the moment
55
 * 
56
 * @author n.hoffmann
57
 * @created 18.11.2008
58
 * @version 1.0
59
 */
60
@Component
61
public class PalmaeImageImport extends AbstractImageImporter {
62
	private static final Logger logger = Logger.getLogger(PalmaeImageImport.class);
63
	
64
	enum MetaData{
65
		NAME,
66
		ARTIST,
67
		COPYRIGHT,
68
		COPYRIGHTNOTICE,
69
		OBJECTNAME
70
	}
71
	
72
	private static int modCount = 300;
73

    
74
	private static String pluralString = "images";
75
	
76
	/**
77
	 * Rudimetary implementation using apache sanselan. This implementation depends
78
	 * on the metadata standards used in the palmae images. The IPTC field ObjectName
79
	 * contains a string like this: "Arecaceae; Eugeissona utilis". The string 
80
	 * in front of the semicolon is the family name and the one behind, the taxon name.
81
	 * So we basically assume, that if the string gets split by ";" the element at 
82
	 * index 1 should be the taxon name.
83
	 * If this format changes this method breaks!
84
	 * 
85
	 * TODO The ImageMetaData class of the commons package should provide 
86
	 * convenient access to the metadata of an image as well as all the error handling
87
	 * 
88
	 * @param imageFile
89
	 * @return the name of the taxon as stored in ObjectName IPTC tag
90
	 */
91
	public String retrieveTaxonNameFromImageMetadata(File imageFile){
92
		String name = null;
93
		
94
		IImageMetadata metadata = null;
95
		
96
		try {
97
			metadata = Sanselan.getMetadata(imageFile);
98
		} catch (ImageReadException e) {
99
			logger.error("Error reading image" + " in " + imageFile.getName(), e);
100
		} catch (IOException e) {
101
			logger.error("Error reading file"  + " in " + imageFile.getName(), e);
102
		}
103
		
104
		if(metadata instanceof JpegImageMetadata){
105
			JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata;
106

    
107
			for (Object object : jpegMetadata.getItems()){
108
				
109
				Item item = (Item) object;
110
				
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
			}
123
		}
124
		
125
		
126
		return name;
127
	}
128
	
129
	public Map<MetaData, String> getMetaData(File imageFile, List<MetaData> metaData){
130
		HashMap<MetaData, String> result = new HashMap<MetaData, String>();
131
		
132
		IImageMetadata metadata = null;
133
		List<String> metaDataStrings = new ArrayList<String>();
134
		
135
		for (MetaData data: metaData){
136
			metaDataStrings.add(data.name().toLowerCase());
137
		}
138
			
139
		
140
		try {
141
			metadata = Sanselan.getMetadata(imageFile);
142
		} catch (ImageReadException e) {
143
			logger.error("Error reading image" + " in " + imageFile.getName(), e);
144
		} catch (IOException e) {
145
			logger.error("Error reading file"  + " in " + imageFile.getName(), e);
146
		}
147
		
148
		
149
		
150
		if(metadata instanceof JpegImageMetadata){
151
			JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata;
152
			
153
			for (Object object : jpegMetadata.getItems()){
154
				Item item = (Item) object;
155
				
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
					Set<Entry<MetaData, String>> resultSet = result.entrySet();
160
				}
161
			}
162
		}
163
		
164
		return result;
165
	}
166
		
167
	
168

    
169
	protected boolean invokeImageImport (ImageImportConfigurator config){
170
		
171
		logger.info("Importing images from directory: " + config.getSourceNameString());
172
		
173
		File sourceFolder = new File(config.getSource());
174
		String taxonName;
175
		if(sourceFolder.isDirectory()){
176
			int count = 0;
177
			for( File file : sourceFolder.listFiles()){
178
				if(file.isFile()){
179
					doCount(count++, modCount, pluralString);
180
					
181
					taxonName= retrieveTaxonNameFromImageMetadata(file);
182
					logger.debug("Looking up taxa with taxon name: " + taxonName);
183
					
184
					//TODO:
185
					ArrayList<MetaData> metaDataList = new ArrayList<MetaData>();
186
					metaDataList.add (MetaData.ARTIST);
187
					metaDataList.add (MetaData.COPYRIGHT);
188
					metaDataList.add (MetaData.COPYRIGHTNOTICE);
189
					metaDataList.add (MetaData.OBJECTNAME);
190
					//metaDataList.add (MetaData.NAME);
191
					
192
					Map<MetaData, String> metaData = getMetaData(file, metaDataList);
193
					
194
					
195
					
196
					Reference sec = referenceService.find(config.getSecUuid());
197

    
198
					List<TaxonBase> taxa = new ArrayList<TaxonBase>();
199
					if (taxonName != null){
200
						taxa = taxonService.searchTaxaByName(taxonName, sec);			
201
					}else{
202
						logger.error("TaxonName is null "  + " in " + file.getName());
203
					}
204
					if(taxa.size() == 0){
205
						logger.warn("no taxon with this name found: " + taxonName + " in " + file.getName());
206
					}else if(taxa.size() > 1){
207
						logger.error(taxa);
208
						logger.error("multiple taxa with this name found: " + taxonName + " in " + file.getName());
209
					}else{
210
						Taxon taxon = (Taxon) taxa.get(0);
211
						
212
						taxonService.saveOrUpdate(taxon);
213
						
214
						//MetaDataFactory metaDataFactory = MetaDataFactory.getInstance();
215
						//ImageMetaData imageMetaData = (ImageMetaData) metaDataFactory.readMediaData(file.toURI(), MimeType.IMAGE);
216
						try{
217
						ImageInfo imageinfo = Sanselan.getImageInfo(file);
218
						
219
						String mimeType = imageinfo.getMimeType();
220
						String suffix = "jpg";
221
						
222
						
223
						// URL for this image
224
						URL url = null;
225
						try {
226
							url = new URL(config.getMediaUrlString() + file.getName());
227
						} catch (MalformedURLException e) {
228
							logger.warn("URL is malformed: "+ url);
229
						}
230
						
231
						
232
						ImageFile imageFile = ImageFile.NewInstance(url.toURI(),null, imageinfo.getHeight(), imageinfo.getWidth());
233
						
234
						
235
						MediaRepresentation representation = MediaRepresentation.NewInstance(mimeType, suffix);
236
						representation.addRepresentationPart(imageFile);
237
						
238
						Media media = Media.NewInstance();
239
						media.addRepresentation(representation);
240
						if (metaData.containsKey(MetaData.OBJECTNAME)){
241
							media.setTitleCache(metaData.get(MetaData.OBJECTNAME).replace("'", ""), true);
242
						}
243
						//TODO: add the rights and the author:
244
						Person artist = null;
245
						if (metaData.containsKey(MetaData.ARTIST)){
246
							//TODO search for the person first and then create the object...
247
							artist = Person.NewTitledInstance(metaData.get(MetaData.ARTIST).replace("'", ""));
248
							artist.setFirstname(getFirstName(metaData.get(MetaData.ARTIST)).replace("'", ""));
249
							artist.setLastname(getLastName(metaData.get(MetaData.ARTIST)).replace("'", ""));
250
							
251
							IMatchStrategy matchStrategy = DefaultMatchStrategy.NewInstance(AgentBase.class);
252
							try{
253
								List<Person> agents = commonService.findMatching(artist, matchStrategy);
254
								
255
								if (agents.size()!= 0){
256
									artist = agents.get(0);
257
								}
258
							}catch(eu.etaxonomy.cdm.strategy.match.MatchException e){
259
								logger.warn("MatchException occurred");
260
							}
261
							
262
							media.setArtist(artist);
263
						}
264
						
265
						if (metaData.containsKey(MetaData.COPYRIGHT)){
266
							//TODO: maybe search for the identic right... 
267
							Rights copyright = Rights.NewInstance();
268
							copyright.setType(RightsTerm.COPYRIGHT());
269
							Person copyrightOwner;
270
							if (artist != null && !artist.getLastname().equalsIgnoreCase(getLastName(metaData.get(MetaData.COPYRIGHT)))){
271
								copyrightOwner = Person.NewInstance();
272
														
273
								copyrightOwner.setFirstname(getFirstName(metaData.get(MetaData.COPYRIGHT)));
274
								copyrightOwner.setLastname(getLastName(metaData.get(MetaData.COPYRIGHT)));
275
							}else
276
							{
277
								copyrightOwner = artist;
278
							}
279
							copyright.setAgent(copyrightOwner);
280
							//IMatchStrategy matchStrategy = DefaultMatchStrategy.NewInstance(Rights.class);
281
							media.addRights(copyright);
282
						}
283
						
284
						Reference sourceRef = config.getSourceReference();
285
						TaxonDescription description = taxon.getOrCreateImageGallery(sourceRef == null ? null :sourceRef.getTitleCache());
286
						
287
						
288
						TextData textData = null;
289
						for (DescriptionElementBase element : description.getElements()){
290
							if (element.isInstanceOf(TextData.class)){
291
								textData = CdmBase.deproxy(element, TextData.class);
292
							}
293
						}
294
						if (textData == null){
295
							textData = TextData.NewInstance();
296
						}
297
						
298
						
299
						textData.addMedia(media);
300
						
301
						textData.setFeature(Feature.IMAGE());
302
						
303
						description.addElement(textData);
304
						
305
						taxonService.saveOrUpdate(taxon);
306
						}catch(Exception e) {
307
							e.printStackTrace();
308
						}
309
					}
310
				}
311
			}
312
		}else{
313
			logger.error("given source folder is not a directory");
314
		}
315
		return true;
316
	}
317
	
318
	private String getFirstName(String artist){
319
		if (artist == null){
320
			return "";
321
		}
322
		if (!artist.contains(" ")) {
323
			return "";
324
		}
325
		if (artist.contains(",")){
326
			String [] artistSplits = artist.split(",");
327
			artist = artistSplits[0];
328
			 
329
		}
330
		
331
		try{
332
		return artist.substring(0, artist.lastIndexOf(' ')).replace("'", "");
333
		}catch (Exception e){
334
			return "";
335
		}
336
	}
337
	
338
	private String getLastName(String artist){
339
		
340
		if (artist.contains(",")){
341
			String [] artistSplits = artist.split(",");
342
			artist = artistSplits[0];
343
			
344
		}
345
		if (!artist.contains(" ")) {
346
			
347
			return artist;
348
		}
349
		try{
350
		return artist.substring(artist.lastIndexOf(' ')).replace(" ", "");
351
		}
352
		catch(Exception e){
353
			return "";
354
		}
355
	}
356
			
357
	protected void doCount(int count, int modCount, String pluralString){
358
		if ((count % modCount ) == 0 && count!= 0 ){ logger.info(pluralString + " handled: " + (count));}
359
	}
360

    
361
}
(2-2/4)