Project

General

Profile

Download (11 KB) Statistics
| Branch: | Tag: | 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
import java.util.Set;
21
import java.util.Map.Entry;
22

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

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

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

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

    
104
			for (Object object : jpegMetadata.getItems()){
105
				
106
				Item item = (Item) object;
107
				
108
				if(item.getKeyword().equals("ObjectName")){
109
					logger.debug("File: " + imageFile.getName() + ". ObjectName string is: " + item.getText());
110
					String[] objectNameSplit = item.getText().split(";");
111
					
112
					try {
113
						name = objectNameSplit[1].trim();
114
					} catch (ArrayIndexOutOfBoundsException e) {
115
						logger.warn("ObjectNameSplit has no second part: " + item.getText() + " in " + imageFile.getName());
116
						//throw e;
117
					}
118
				}
119
			}
120
		}
121
		
122
		
123
		return name;
124
	}
125
	
126
	public Map<MetaData, String> getMetaData(File imageFile, List<MetaData> metaData){
127
		HashMap<MetaData, String> result = new HashMap<MetaData, String>();
128
		
129
		IImageMetadata metadata = null;
130
		List<String> metaDataStrings = new ArrayList<String>();
131
		
132
		for (MetaData data: metaData){
133
			metaDataStrings.add(data.name().toLowerCase());
134
		}
135
			
136
		
137
		try {
138
			metadata = Sanselan.getMetadata(imageFile);
139
		} catch (ImageReadException e) {
140
			logger.error("Error reading image" + " in " + imageFile.getName(), e);
141
		} catch (IOException e) {
142
			logger.error("Error reading file"  + " in " + imageFile.getName(), e);
143
		}
144
		
145
		
146
		
147
		if(metadata instanceof JpegImageMetadata){
148
			JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata;
149
			
150
			for (Object object : jpegMetadata.getItems()){
151
				Item item = (Item) object;
152
				
153
				if(metaDataStrings.contains(item.getKeyword().toLowerCase())){
154
					logger.debug("File: " + imageFile.getName() + ". "+ item.getKeyword() +"string is: " + item.getText());
155
					result.put(MetaData.valueOf(item.getKeyword().toUpperCase()), item.getText());
156
					Set<Entry<MetaData, String>> resultSet = result.entrySet();
157
				}
158
			}
159
		}
160
		
161
		return result;
162
	}
163
		
164
	
165

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

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

    
345
}
(2-2/4)