Project

General

Profile

Download (9.41 KB) Statistics
| Branch: | Tag: | Revision:
1
// $Id$
2
/**
3
* Copyright (C) 2007 EDIT
4
* European Distributed Institute of Taxonomy 
5
* http://www.e-taxonomy.eu
6
* 
7
* The contents of this file are subject to the Mozilla Public License Version 1.1
8
* See LICENSE.TXT at the top of this package for the full license terms.
9
*/
10

    
11
package eu.etaxonomy.cdm.print;
12

    
13
import java.util.ArrayList;
14
import java.util.List;
15
import java.util.Locale;
16
import java.util.UUID;
17

    
18
import org.apache.log4j.Logger;
19
import org.jdom.Document;
20
import org.jdom.Element;
21
import org.jdom.JDOMException;
22
import org.jdom.xpath.XPath;
23

    
24
import eu.etaxonomy.cdm.common.IProgressMonitor;
25
import eu.etaxonomy.cdm.print.out.IPublishOutputModule;
26

    
27
/**
28
 * Retrieves all necessary data from an {@link IXMLEntityFactory}.
29
 * 
30
 * @author n.hoffmann
31
 * @created Apr 8, 2010
32
 * @version 1.0
33
 */
34
public class XMLHarvester {
35
	private static final Logger logger = Logger.getLogger(XMLHarvester.class);
36
	
37
	private IXMLEntityFactory factory;
38

    
39
	private PublishConfigurator configurator;
40
	
41
	private List<SimplifiedFeatureNode> simplifiedFeatureTree;
42
	
43
	private IProgressMonitor progressMonitor;
44
	
45
	/**
46
	 * 
47
	 * @param configurator
48
	 */
49
	public XMLHarvester(PublishConfigurator configurator){
50
		this.configurator = configurator;
51
		this.factory = configurator.getFactory();
52
		this.progressMonitor = configurator.getProgressMonitor();
53
		
54
		Element featureTreeElement = factory.getFeatureTree(configurator.getFeatureTreeUuid());
55
		createSimplifiedFeatureTree(featureTreeElement);
56
	}
57
	
58
	private void createSimplifiedFeatureTree(Element featureTreeElement) {
59
		Element root = featureTreeElement.getChild("root");
60
		
61
		Element realRoot = factory.getFeatureNode(XMLHelper.getUuid(root));
62
		
63
		progressMonitor.subTask("Generating simplified Feature Tree.");
64
		simplifiedFeatureTree = featureTreeRecursive(realRoot);
65
		
66
		logger.info("Simplified FeeatureTree created");
67
	}
68
	
69
	private List<SimplifiedFeatureNode> featureTreeRecursive(Element featureNode){
70
		List<SimplifiedFeatureNode> result = new ArrayList<SimplifiedFeatureNode>();
71
		
72
		if(featureNode != null){
73
			Element children = featureNode.getChild("children");
74
			
75
			List<Element> childFeatureNodes = children.getChildren();
76
			
77
			for(Element childNode : childFeatureNodes){
78
				UUID uuid = XMLHelper.getUuid(childNode);
79
				Element featureNodeElement = factory.getFeatureNode(uuid);
80
				Element featureElement = factory.getFeatureForFeatureNode(uuid);
81
				featureElement.setName(featureElement.getName().toLowerCase(Locale.ENGLISH));
82
				SimplifiedFeatureNode simplifiedFeatureNode = new SimplifiedFeatureNode(featureElement, featureTreeRecursive(featureNodeElement));
83
				
84
				result.add(simplifiedFeatureNode);
85
			}
86
		}
87
		return result;
88
	}
89
	
90
	private class SimplifiedFeatureNode{
91
		private Element featureElement;
92
		private List<SimplifiedFeatureNode> children;
93
		
94
		public SimplifiedFeatureNode(Element featureElement, List<SimplifiedFeatureNode> children){
95
			this.featureElement = featureElement;
96
			this.children = children;
97
		}
98

    
99
		/**
100
		 * @return the uuid
101
		 */
102
		public Element getFeatureElement() {
103
			return featureElement;
104
		}
105

    
106
		/**
107
		 * @return the children
108
		 */
109
		public List<SimplifiedFeatureNode> getChildren() {
110
			return children;
111
		}
112
	}
113

    
114
	/**
115
	 * Commences harvesting the given {@link List} of taxonNodeElements
116
	 * 
117
	 * @param taxonNodeElements
118
	 * @return a {@link Document} containing the necessary XML needed by the {@link IPublishOutputModule IPublishOutputModules}
119
	 */
120
	public Document harvest(List<Element> taxonNodeElements){
121
		
122
		Element root = new Element(IXMLElements.ROOT);
123
		
124
		for(Element taxonNodeElement : taxonNodeElements){
125
						
126
			taxonNodeElement.detach();
127
			
128
			populateTreeNodeContainer(taxonNodeElement);
129
			
130
			root.addContent(taxonNodeElement);
131
		}
132
		
133
		
134
		Document result = new Document();
135
		
136
		result.addContent(root);
137
		
138
		cleanDateFields(result);
139
		
140
		return result;
141
	}
142
	
143
	/**
144
	 * FIXME
145
	 * This is a hack to circumvent problems with the serialized version of
146
	 * datePublished objects. Remove this once this was fixed in the library
147
	 * @param element the context 
148
	 */
149
	@Deprecated
150
	private void cleanDateFields(Object context) {
151
		String path = "//datePublished/start";
152
		
153
		try {
154
			List<Element> nodes = XPath.selectNodes(context, path);
155
			
156
			for(Element node : nodes){
157
				String textWithRubbish = node.getText() ;
158
				String cleanedText = textWithRubbish.substring(0, 4);
159
				node.setText(cleanedText);	
160
				
161
				Element parent = (Element) node.getParent().getParent();
162
				if(parent.getName().equals("citation")){
163
					Element parent2 = (Element) parent.getParent();
164
					parent2.setAttribute("sort", cleanedText);
165
				}
166
			}
167
		} catch (JDOMException e) {
168
			logger.error("Error tryong to clean dat published field");
169
		}
170
	}
171

    
172
	/**
173
	 * Get all additional content that is not included in taxon node initialization
174
	 * 
175
	 * @param container
176
	 */
177
	private void populateTreeNodeContainer(Element taxonNodeElement){
178
		
179
		// get the taxon from the generic service to have the uuid for further processing
180
		Element taxonElement = factory.getTaxonForTaxonNode(taxonNodeElement);
181
		
182
		progressMonitor.subTask("Gathering data for taxon: " + XMLHelper.getTitleCache(taxonElement));
183
		
184
		// get initialized accepted taxon
185
		// TODO right now we are getting that from the portal service but should consider to use the generic service
186
		// as the portal service is more likely to change
187
		Element fullTaxonElement = factory.getAcceptedTaxonElement(taxonElement);
188
		
189
		populateTypeDesignations(fullTaxonElement);
190
		
191
		// get descriptions
192
		if(configurator.isDoDescriptions()){
193
			populateDescriptions(fullTaxonElement);
194
		}
195
		
196
		// get synonym
197
		if(configurator.isDoSynonymy()){
198
			populateSynonyms(fullTaxonElement);
199
		}
200
		
201
		// get media
202
		if(configurator.isDoImages()){
203
			populateImages(fullTaxonElement);
204
		}
205
		
206
		// add taxon element to the node element
207
		XMLHelper.addContent(fullTaxonElement, taxonNodeElement);
208
		
209
		// get taxonomically included taxa
210
		if(configurator.isDoPublishEntireBranches()){
211
			populateChildren(taxonNodeElement);
212
		}
213
		
214
	}	
215
	
216
	private void populateTypeDesignations(Element fullTaxonElement) {
217
		
218
		Element nameElement = fullTaxonElement.getChild("name");
219
		
220
		List<Element> typeDesignations = factory.getTypeDesignations(nameElement);
221
		
222
		nameElement.removeChild("typeDesignations");
223
		
224
		for(Element typeDesignation: typeDesignations){
225
			XMLHelper.addContent(typeDesignation, "typeDesignations", nameElement);
226
		}
227
	}
228

    
229
	/**
230
	 * Populates all child nodes of the given taxonNodeElement
231
	 * 
232
	 * @param container
233
	 */
234
	private void populateChildren(Element taxonNodeElement){
235
		
236
		logger.info("populating branch");
237
		
238
		List<Element> childNodeElements = factory.getChildNodes(taxonNodeElement);
239
		
240
		for(Element childNodeElement : childNodeElements){
241
			logger.info("Creating content for child node");
242
			
243
			populateTreeNodeContainer(childNodeElement);			
244
			XMLHelper.addContent(childNodeElement, "childNodes", taxonNodeElement);
245
		}
246
	}
247
	
248
	/**
249
	 * Retrieves descriptions for the given taxonElement
250
	 * 
251
	 * @param taxonElement
252
	 */
253
	private void populateDescriptions(Element taxonElement){
254
		taxonElement.removeChild("descriptions");
255
		
256
		Element rawDescriptions = factory.getDescriptions(taxonElement);
257
		
258
		Element descriptions = new Element("descriptions");
259
		
260
		Element features = new Element("features");
261
		
262
		for(SimplifiedFeatureNode simplifiedFeatureNode : simplifiedFeatureTree){
263
			
264
			try {
265
				processFeatureNode(simplifiedFeatureNode, rawDescriptions, features);
266
			} catch (JDOMException e) {
267
				logger.error(e);
268
			}
269
		}
270
		XMLHelper.addContent(features, descriptions);
271
		XMLHelper.addContent(descriptions, taxonElement);
272
	}
273
	
274
	private void processFeatureNode(SimplifiedFeatureNode featureNode, Object context, Element parentElement)  throws JDOMException{
275
		// gets the feature elements with the current feature uuid
276
		UUID featureUuid = XMLHelper.getUuid(featureNode.getFeatureElement());
277
		String featurePattern = "//feature[contains(uuid,'" + featureUuid + "')]";
278
		
279
		Element feature = (Element) XPath.selectSingleNode(context, featurePattern);
280
		
281
		if(feature != null){
282
			// get the parents of all feature elements with the current uuid
283
			List<Element> descriptionElementElements = XPath.selectNodes(context, featurePattern + "/..");
284
			// add matching description elements as children to this feature element
285
			for(Element descriptionElementElement : descriptionElementElements){
286
				descriptionElementElement.removeChild("feature");
287
				descriptionElementElement.setName("descriptionelement");
288
				XMLHelper.addContent(descriptionElementElement, "descriptionelements", feature);
289
			}
290
			XMLHelper.addContent(feature, parentElement);	
291
		}else if(featureNode.getChildren().size() > 0){
292
			Element featureElement = featureNode.getFeatureElement();
293
			Element featureElementClone = (Element) featureElement.clone();
294
			feature = (Element) featureElementClone.detach();
295
			XMLHelper.addContent(feature, parentElement);
296
		}		
297
		
298
		// recurse into children
299
		for(SimplifiedFeatureNode childFeatureNode : featureNode.getChildren()){
300
			processFeatureNode(childFeatureNode, context, feature);
301
		}
302
	}
303
	
304
	/**
305
	 * Retrieves the synonymy for the given taxonElement 
306
	 * 
307
	 * @param taxonElement
308
	 */
309
	private void populateSynonyms(Element taxonElement){
310
		List<Element> synonymy = factory.getSynonymy(taxonElement);
311
		
312
		for(Element synonymyNode : synonymy){
313
			XMLHelper.addContent(synonymyNode, "synonymy", taxonElement);
314
		}
315
	}
316
	
317
	
318
	
319
	/**
320
	 * TODO not implemented yet
321
	 * @param taxonElement
322
	 */
323
	private void populateImages(Element taxonElement){
324
		logger.warn("not implemented yet");
325
	}
326
}
(9-9/10)