Project

General

Profile

Download (22.4 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.api.service;
12

    
13
import java.util.ArrayList;
14
import java.util.Collection;
15
import java.util.Collections;
16
import java.util.Comparator;
17
import java.util.HashMap;
18
import java.util.List;
19
import java.util.Map;
20
import java.util.TreeMap;
21
import java.util.UUID;
22

    
23
import org.apache.commons.collections.CollectionUtils;
24
import org.apache.log4j.Logger;
25
import org.springframework.beans.factory.annotation.Autowired;
26
import org.springframework.stereotype.Service;
27
import org.springframework.transaction.annotation.Transactional;
28

    
29
import eu.etaxonomy.cdm.api.service.config.CreateHierarchyForClassificationConfigurator;
30
import eu.etaxonomy.cdm.api.service.pager.Pager;
31
import eu.etaxonomy.cdm.api.service.pager.PagerUtils;
32
import eu.etaxonomy.cdm.api.service.pager.impl.AbstractPagerImpl;
33
import eu.etaxonomy.cdm.api.service.pager.impl.DefaultPagerImpl;
34
import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
35
import eu.etaxonomy.cdm.model.common.CdmBase;
36
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
37
import eu.etaxonomy.cdm.model.description.TaxonDescription;
38
import eu.etaxonomy.cdm.model.media.Media;
39
import eu.etaxonomy.cdm.model.media.MediaRepresentation;
40
import eu.etaxonomy.cdm.model.media.MediaUtils;
41
import eu.etaxonomy.cdm.model.name.NonViralName;
42
import eu.etaxonomy.cdm.model.name.Rank;
43
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
44
import eu.etaxonomy.cdm.model.taxon.Classification;
45
import eu.etaxonomy.cdm.model.taxon.ITaxonNodeComparator;
46
import eu.etaxonomy.cdm.model.taxon.ITaxonTreeNode;
47
import eu.etaxonomy.cdm.model.taxon.Taxon;
48
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
49
import eu.etaxonomy.cdm.persistence.dao.initializer.IBeanInitializer;
50
import eu.etaxonomy.cdm.persistence.dao.taxon.IClassificationDao;
51
import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao;
52
import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonNodeDao;
53
import eu.etaxonomy.cdm.persistence.dto.UuidAndTitleCache;
54
import eu.etaxonomy.cdm.persistence.query.OrderHint;
55
import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy;
56
import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImpl;
57

    
58
/**
59
 * @author n.hoffmann
60
 * @created Sep 21, 2009
61
 */
62
@Service
63
@Transactional(readOnly = true)
64
public class ClassificationServiceImpl extends IdentifiableServiceBase<Classification, IClassificationDao>
65
    implements IClassificationService {
66
    private static final Logger logger = Logger.getLogger(ClassificationServiceImpl.class);
67

    
68
    @Autowired
69
    private ITaxonNodeDao taxonNodeDao;
70

    
71
    @Autowired
72
    private ITaxonDao taxonDao;
73

    
74
    @Autowired
75
    private IBeanInitializer defaultBeanInitializer;
76

    
77
    @Override
78
    @Autowired
79
    protected void setDao(IClassificationDao dao) {
80
        this.dao = dao;
81
    }
82

    
83
    private Comparator<? super TaxonNode> taxonNodeComparator;
84

    
85
    @Autowired
86
    public void setTaxonNodeComparator(ITaxonNodeComparator<? super TaxonNode> taxonNodeComparator){
87
        this.taxonNodeComparator = (Comparator<? super TaxonNode>) taxonNodeComparator;
88
    }
89

    
90
    @Override
91
    public TaxonNode loadTaxonNodeByTaxon(Taxon taxon, UUID classificationUuid, List<String> propertyPaths){
92
        Classification tree = dao.load(classificationUuid);
93
        TaxonNode node = tree.getNode(taxon);
94

    
95
        return loadTaxonNode(node.getUuid(), propertyPaths);
96
    }
97

    
98
    @Override
99
    @Deprecated // use loadTaxonNode(UUID, List<String>) instead
100
    public TaxonNode loadTaxonNode(TaxonNode taxonNode, List<String> propertyPaths){
101
        return taxonNodeDao.load(taxonNode.getUuid(), propertyPaths);
102
    }
103

    
104
    public TaxonNode loadTaxonNode(UUID taxonNodeUuid, List<String> propertyPaths){
105
        return taxonNodeDao.load(taxonNodeUuid, propertyPaths);
106
    }
107

    
108
    @Override
109
    public List<TaxonNode> listRankSpecificRootNodes(Classification classification, Rank rank, Integer pageSize,
110
            Integer pageIndex, List<String> propertyPaths) {
111
        return pageRankSpecificRootNodes(classification, rank, pageSize, pageIndex, propertyPaths).getRecords();
112
    }
113

    
114
    @Override
115
    public Pager<TaxonNode> pageRankSpecificRootNodes(Classification classification, Rank rank, Integer pageSize,
116
            Integer pageIndex, List<String> propertyPaths) {
117
        long[] numberOfResults = dao.countRankSpecificRootNodes(classification, rank);
118
        long totalNumberOfResults = numberOfResults[0] + (numberOfResults.length > 1 ? numberOfResults[1] : 0);
119

    
120
        List<TaxonNode> results = new ArrayList<TaxonNode>();
121

    
122
        if (AbstractPagerImpl.hasResultsInRange(totalNumberOfResults, pageIndex, pageSize)) { // no point checking again
123
            Integer limit = PagerUtils.limitFor(pageSize);
124
            Integer start = PagerUtils.startFor(pageSize, pageIndex);
125

    
126
            Integer remainingLimit = limit;
127
            int[] queryIndexes = rank == null ? new int[]{0} : new int[]{0,1};
128

    
129
            for(int queryIndex: queryIndexes) {
130
                if(start != null && start > numberOfResults[queryIndex]) {
131
                    // start in next query with new start value
132
                    start = start - (int)numberOfResults[queryIndex];
133
                    continue;
134
                }
135

    
136
                List<TaxonNode> perQueryResults = dao.listRankSpecificRootNodes(classification, rank, remainingLimit, start, propertyPaths, queryIndex);
137
                results.addAll(perQueryResults);
138
                if(remainingLimit != null ){
139
                    remainingLimit = remainingLimit - results.size();
140
                    if(remainingLimit <= 0) {
141
                        // no need to run further queries if first query returned enough items!
142
                        break;
143
                    }
144
                    // start at with fist item of next query to fetch the remaining items
145
                    start = 0;
146
                }
147
            }
148
        }
149

    
150
        Collections.sort(results, taxonNodeComparator); // FIXME this is only a HACK, order during the hibernate query in the dao
151
        return new DefaultPagerImpl<TaxonNode>(pageIndex, (int) totalNumberOfResults, pageSize, results);
152

    
153
    }
154

    
155
    /**
156
     * @implements {@link IClassificationService#loadTreeBranch(TaxonNode, Rank, List)
157
     * @see eu.etaxonomy.cdm.api.service.ITaxonService#loadTreeBranchTo(eu.etaxonomy.cdm.model.taxon.TaxonNode, eu.etaxonomy.cdm.model.name.Rank, java.util.List)
158
     * FIXME Candidate for harmonization
159
     * move to classification service
160
     */
161
    @Override
162
    public List<TaxonNode> loadTreeBranch(TaxonNode taxonNode, Rank baseRank, List<String> propertyPaths){
163

    
164
        TaxonNode thisNode = taxonNodeDao.load(taxonNode.getUuid(), propertyPaths);
165
        List<TaxonNode> pathToRoot = new ArrayList<TaxonNode>();
166
        pathToRoot.add(thisNode);
167

    
168
        while(!thisNode.isTopmostNode()){
169
            //TODO why do we need to deproxy here?
170
            //     without this thisNode.getParent() will return NULL in
171
            //     some cases (environment dependend?) even if the parent exits
172
            TaxonNode parentNode = CdmBase.deproxy(thisNode, TaxonNode.class).getParent();
173

    
174
            if(parentNode == null){
175
                throw new NullPointerException("taxonNode " + thisNode + " must have a parent since it is not top most");
176
            }
177
            if(parentNode.getTaxon() == null){
178
                throw new NullPointerException("The taxon associated with taxonNode " + parentNode + " is NULL");
179
            }
180
            if(parentNode.getTaxon().getName() == null){
181
                throw new NullPointerException("The name of the taxon associated with taxonNode " + parentNode + " is NULL");
182
            }
183

    
184
            Rank parentNodeRank = parentNode.getTaxon().getName() == null ? null : parentNode.getTaxon().getName().getRank();
185
            // stop if the next parent is higher than the baseRank
186
            if(baseRank != null && parentNodeRank != null && baseRank.isLower(parentNodeRank)){
187
                break;
188
            }
189

    
190
            pathToRoot.add(parentNode);
191
            thisNode = parentNode;
192
        }
193

    
194
        // initialize and invert order of nodes in list
195
        defaultBeanInitializer.initializeAll(pathToRoot, propertyPaths);
196
        Collections.reverse(pathToRoot);
197

    
198
        return pathToRoot;
199
    }
200

    
201
    @Override
202
    public List<TaxonNode> loadTreeBranchToTaxon(Taxon taxon, Classification classification, Rank baseRank, List<String> propertyPaths){
203
        Classification tree = dao.load(classification.getUuid());
204
        taxon = (Taxon) taxonDao.load(taxon.getUuid());
205
        TaxonNode node = tree.getNode(taxon);
206
        if(node == null){
207
            logger.warn("The specified taxon is not found in the given tree.");
208
            return null;
209
        }
210
        return loadTreeBranch(node, baseRank, propertyPaths);
211
    }
212

    
213

    
214
    @Override
215
    public List<TaxonNode> loadChildNodesOfTaxonNode(TaxonNode taxonNode,
216
            List<String> propertyPaths) {
217
        taxonNode = taxonNodeDao.load(taxonNode.getUuid());
218
        List<TaxonNode> childNodes = new ArrayList<TaxonNode>(taxonNode.getChildNodes());
219
        defaultBeanInitializer.initializeAll(childNodes, propertyPaths);
220
        Collections.sort(childNodes, taxonNodeComparator);
221
        return childNodes;
222
    }
223

    
224
    @Override
225
    public List<TaxonNode> listChildNodesOfTaxon(UUID taxonUuid, UUID classificationUuid, Integer pageSize,
226
            Integer pageIndex, List<String> propertyPaths){
227

    
228
        Classification classification = dao.load(classificationUuid);
229
        Taxon taxon = (Taxon) taxonDao.load(taxonUuid);
230

    
231
        List<TaxonNode> results = dao.listChildrenOf(taxon, classification, pageSize, pageIndex, propertyPaths);
232
        Collections.sort(results, taxonNodeComparator); // FIXME this is only a HACK, order during the hibernate query in the dao
233
        return results;
234
    }
235

    
236
    @Override
237
    public TaxonNode getTaxonNodeByUuid(UUID uuid) {
238
        return taxonNodeDao.findByUuid(uuid);
239
    }
240

    
241
    @Override
242
    public ITaxonTreeNode getTreeNodeByUuid(UUID uuid){
243
        ITaxonTreeNode treeNode = taxonNodeDao.findByUuid(uuid);
244
        if(treeNode == null){
245
            treeNode = dao.findByUuid(uuid);
246
        }
247

    
248
        return treeNode;
249
    }
250

    
251
    @Override
252
    public List<Classification> listClassifications(Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {
253
        return dao.list(limit, start, orderHints, propertyPaths);
254
    }
255

    
256
    @Override
257
    public UUID removeTaxonNode(TaxonNode taxonNode) {
258
        return taxonNodeDao.delete(taxonNode);
259
    }
260
    @Override
261
    public UUID removeTreeNode(ITaxonTreeNode treeNode) {
262
        if(treeNode instanceof Classification){
263
            return dao.delete((Classification) treeNode);
264
        }else if(treeNode instanceof TaxonNode){
265
            return taxonNodeDao.delete((TaxonNode)treeNode);
266
        }
267
        return null;
268
    }
269
    @Override
270
    public UUID saveTaxonNode(TaxonNode taxonNode) {
271
        return taxonNodeDao.save(taxonNode).getUuid();
272
    }
273

    
274
    @Override
275
    public Map<UUID, TaxonNode> saveTaxonNodeAll(
276
            Collection<TaxonNode> taxonNodeCollection) {
277
        return taxonNodeDao.saveAll(taxonNodeCollection);
278
    }
279

    
280
    @Override
281
    public UUID saveTreeNode(ITaxonTreeNode treeNode) {
282
        if(treeNode instanceof Classification){
283
            return dao.save((Classification) treeNode).getUuid();
284
        }else if(treeNode instanceof TaxonNode){
285
            return taxonNodeDao.save((TaxonNode)treeNode).getUuid();
286
        }
287
        return null;
288
    }
289

    
290
    @Override
291
    public List<TaxonNode> getAllNodes(){
292
        return taxonNodeDao.list(null,null);
293
    }
294

    
295
    @Override
296
    public List<UuidAndTitleCache<TaxonNode>> getTaxonNodeUuidAndTitleCacheOfAcceptedTaxaByClassification(UUID classificationUuid, List<UUID> excludeTaxa) {
297
        return taxonDao.getTaxonNodeUuidAndTitleCacheOfAcceptedTaxaByClassification(dao.load(classificationUuid), excludeTaxa);
298
    }
299

    
300
    @Override
301
    public List<UuidAndTitleCache<TaxonNode>> getTaxonNodeUuidAndTitleCacheOfAcceptedTaxaByClassification(Classification classification, List<UUID> excludeTaxa) {
302
        return taxonDao.getTaxonNodeUuidAndTitleCacheOfAcceptedTaxaByClassification(classification, excludeTaxa);
303
    }
304

    
305
    @Override
306
    public List<UuidAndTitleCache<Classification>> getUuidAndTitleCache() {
307
        return dao.getUuidAndTitleCache();
308
    }
309

    
310
    @Override
311
    public Map<UUID, List<MediaRepresentation>> getAllMediaForChildNodes(
312
            TaxonNode taxonNode, List<String> propertyPaths, int size,
313
            int height, int widthOrDuration, String[] mimeTypes) {
314

    
315
        TreeMap<UUID, List<MediaRepresentation>> result = new TreeMap<UUID, List<MediaRepresentation>>();
316
        List<Media> taxonMedia = new ArrayList<Media>();
317
        List<MediaRepresentation> mediaRepresentations = new ArrayList<MediaRepresentation>();
318

    
319
        //add all media of the children to the result map
320
        if (taxonNode != null){
321

    
322
            List<TaxonNode> nodes = new ArrayList<TaxonNode>();
323

    
324
            nodes.add(loadTaxonNode(taxonNode, propertyPaths));
325
            nodes.addAll(loadChildNodesOfTaxonNode(taxonNode, propertyPaths));
326

    
327
            if (nodes != null){
328
                for(TaxonNode node : nodes){
329
                    Taxon taxon = node.getTaxon();
330
                    for (TaxonDescription taxonDescription: taxon.getDescriptions()){
331
                        for (DescriptionElementBase descriptionElement: taxonDescription.getElements()){
332
                            for(Media media : descriptionElement.getMedia()){
333
                                taxonMedia.add(media);
334

    
335
                                //find the best matching representation
336
                                mediaRepresentations.add(MediaUtils.findBestMatchingRepresentation(media,null, size, height, widthOrDuration, mimeTypes));
337

    
338
                            }
339
                        }
340
                    }
341
                    result.put(taxon.getUuid(), mediaRepresentations);
342

    
343
                }
344
            }
345

    
346
        }
347

    
348
        return result;
349

    
350
    }
351

    
352
    @Override
353
    public Map<UUID, List<MediaRepresentation>> getAllMediaForChildNodes(Taxon taxon, Classification taxTree, List<String> propertyPaths, int size, int height, int widthOrDuration, String[] mimeTypes){
354
        TaxonNode node = taxTree.getNode(taxon);
355

    
356
        return getAllMediaForChildNodes(node, propertyPaths, size, height, widthOrDuration, mimeTypes);
357
    }
358

    
359
    @Override
360
    @Transactional(readOnly = false)
361
    public void updateTitleCache(Class<? extends Classification> clazz, Integer stepSize, IIdentifiableEntityCacheStrategy<Classification> cacheStrategy, IProgressMonitor monitor) {
362
        if (clazz == null){
363
            clazz = Classification.class;
364
        }
365
        super.updateTitleCacheImpl(clazz, stepSize, cacheStrategy, monitor);
366
    }
367

    
368
    /**
369
     *
370
     * @param allNodesOfClassification
371
     * @return null - if  allNodesOfClassification is empty <br>
372
     */
373

    
374
    private Map<String, List<TaxonNode>> getSortedGenusList(Collection<TaxonNode> allNodesOfClassification){
375

    
376
    	if(allNodesOfClassification == null || allNodesOfClassification.isEmpty()){
377
    		return null;
378
    	}
379
    	Map<String, List<TaxonNode>> sortedGenusMap = new HashMap<String, List<TaxonNode>>();
380
    	for(TaxonNode node:allNodesOfClassification){
381
    		final TaxonNode tn = node;
382
    		Taxon taxon = node.getTaxon();
383
    		NonViralName name = CdmBase.deproxy(taxon.getName(), NonViralName.class);
384
    		String genusOrUninomial = name.getGenusOrUninomial();
385
    		//if rank unknown split string and take first word
386
    		if(genusOrUninomial == null){
387
    			String titleCache = taxon.getTitleCache();
388
    			String[] split = titleCache.split("\\s+");
389
    			for(String s:split){
390
    				genusOrUninomial = s;
391
    				break;
392
    			}
393
    		}
394
    		//if node has children
395

    
396
    		//retrieve list from map if not create List
397
    		if(sortedGenusMap.containsKey(genusOrUninomial)){
398
    			List<TaxonNode> list = sortedGenusMap.get(genusOrUninomial);
399
    			list.add(node);
400
    			sortedGenusMap.put(genusOrUninomial, list);
401
    		}else{
402
    			//create List for genus
403
    			List<TaxonNode> list = new ArrayList<TaxonNode>();
404
    			list.add(node);
405
    			sortedGenusMap.put(genusOrUninomial, list);
406
    		}
407
    	}
408
    	return sortedGenusMap;
409
    }
410

    
411
    /**
412
     *
413
     * creates new Classification and parent TaxonNodes at genus level
414
     *
415
     *
416
     * @param map GenusMap which holds a name (Genus) and all the same Taxa as a list
417
     * @param classification you want to improve the hierarchy (will not be modified)
418
     * @param configurator to change certain settings, if null then standard settings will be taken
419
     * @return new classification with parentNodes for each entry in the map
420
     */
421
    @SuppressWarnings({ "rawtypes", "unchecked" })
422
	@Transactional(readOnly = false)
423
	@Override
424
    public UpdateResult createHierarchyInClassification(Classification classification, CreateHierarchyForClassificationConfigurator configurator){
425
        UpdateResult result = new UpdateResult();
426
    	classification = dao.findByUuid(classification.getUuid());
427
    	Map<String, List<TaxonNode>> map = getSortedGenusList(classification.getAllNodes());
428

    
429
    	final String APPENDIX = "repaired";
430
    	String titleCache = org.apache.commons.lang.StringUtils.isBlank(classification.getTitleCache()) ? " " : classification.getTitleCache() ;
431
    	//TODO classification clone???
432
    	Classification newClassification = Classification.NewInstance(titleCache +" "+ APPENDIX);
433
    	newClassification.setReference(classification.getReference());
434

    
435
    	for(Map.Entry<String, List<TaxonNode>> entry:map.entrySet()){
436
    		String genus = entry.getKey();
437
    		List<TaxonNode> listOfTaxonNodes = entry.getValue();
438
    		TaxonNode parentNode = null;
439
    		//Search for genus in list
440
    		for(TaxonNode tNode:listOfTaxonNodes){
441
    			//take that taxonNode as parent and remove from list with all it possible children
442
    			//FIXME NPE for name
443
    			TaxonNameBase name = tNode.getTaxon().getName();
444
				NonViralName nonViralName = CdmBase.deproxy(name, NonViralName.class);
445
    			if(nonViralName.getNameCache().equalsIgnoreCase(genus)){
446
    				TaxonNode clone = (TaxonNode) tNode.clone();
447
    				if(!tNode.hasChildNodes()){
448
    					//FIXME remove classification
449
//    					parentNode = newClassification.addChildNode(clone, 0, classification.getCitation(), classification.getMicroReference());
450
    					parentNode = newClassification.addChildNode(clone, 0, clone.getReference(), clone.getMicroReference());
451
    					//remove taxonNode from list because just added to classification
452
    					result.addUpdatedObject(tNode);
453
    					listOfTaxonNodes.remove(tNode);
454
    				}else{
455
    					//get all childNodes
456
    					//save prior Hierarchy and remove them from the list
457
    					List<TaxonNode> copyAllChildrenToTaxonNode = copyAllChildrenToTaxonNode(tNode, clone, result);
458
//    					parentNode = newClassification.addChildNode(clone, 0, classification.getCitation(), classification.getMicroReference());
459
      					//FIXME remove classification
460
    					parentNode = newClassification.addChildNode(clone, 0, clone.getReference(), clone.getMicroReference());
461
    					//remove taxonNode from list because just added to classification
462
    					result.addUpdatedObject(tNode);
463
    					listOfTaxonNodes.remove(tNode);
464
    					if(copyAllChildrenToTaxonNode != null){
465
    						listOfTaxonNodes = (List<TaxonNode>) CollectionUtils.removeAll(listOfTaxonNodes, copyAllChildrenToTaxonNode);
466
    					}
467
    				}
468
    				break;
469
    			}
470
    		}
471
    		if(parentNode == null){
472
    			//if no match found in list, create parentNode
473
    			NonViralNameParserImpl parser = NonViralNameParserImpl.NewInstance();
474
    			NonViralName nonViralName = parser.parseFullName(genus);
475
    			TaxonNameBase taxonNameBase = nonViralName;
476
    			//TODO Sec via configurator
477
    			Taxon taxon = Taxon.NewInstance(taxonNameBase, null);
478
    			parentNode = newClassification.addChildTaxon(taxon, 0, null, null);
479
    			result.addUpdatedObject(parentNode);
480
    		}
481
    		//iterate over the rest of the list
482
    		for(TaxonNode tn : listOfTaxonNodes){
483
    			//if TaxonNode has a parent and this is not the classification then skip it
484
    			//and add to new classification via the parentNode as children of it
485
    			//this should assures to keep the already existing hierarchy
486
    			//FIXME: Assert is not rootnode --> entrypoint is not classification in future but rather rootNode
487

    
488
    			if(!tn.isTopmostNode()){
489
    				continue; //skip to next taxonNode
490
    			}
491

    
492
    			TaxonNode clone = (TaxonNode) tn.clone();
493
    			//FIXME: citation from node
494
    			//TODO: addchildNode without citation and references
495
//    			TaxonNode taxonNode = parentNode.addChildNode(clone, classification.getCitation(), classification.getMicroReference());
496
    			TaxonNode taxonNode = parentNode.addChildNode(clone, clone.getReference(), clone.getMicroReference());
497
    			result.addUnChangedObject(clone);
498
    			if(tn.hasChildNodes()){
499
    				//save hierarchy in new classification
500
    				List<TaxonNode> copyAllChildrenToTaxonNode = copyAllChildrenToTaxonNode(tn, taxonNode, result);
501
    				if(copyAllChildrenToTaxonNode != null){
502
    					listOfTaxonNodes = (List<TaxonNode>) CollectionUtils.removeAll(listOfTaxonNodes, copyAllChildrenToTaxonNode);
503
    				}
504
    			}
505
    		}
506
    	}
507
    	dao.saveOrUpdate(newClassification);
508
    	result.setCdmEntity(newClassification);
509
    	return result;
510
    }
511

    
512
    /**
513
     *
514
     * recursive method to get all childnodes of taxonNode in classification.
515
     *
516
     * @param classification just for References and Citation, can be null
517
     * @param copyFromNode TaxonNode with Children
518
     * @param copyToNode TaxonNode which will receive the children
519
     * @return List of ChildNode which has been added. If node has no children returns null
520
     */
521
   private List<TaxonNode> copyAllChildrenToTaxonNode(TaxonNode copyFromNode, TaxonNode copyToNode, UpdateResult result) {
522
		List<TaxonNode> childNodes;
523
		if(!copyFromNode.hasChildNodes()){
524
			return null;
525
		}else{
526
			childNodes = copyFromNode.getChildNodes();
527
		}
528
		for(TaxonNode childNode:childNodes){
529
			TaxonNode clone = (TaxonNode) childNode.clone();
530
			result.addUnChangedObject(clone);
531
			if(childNode.hasChildNodes()){
532
				copyAllChildrenToTaxonNode(childNode, clone, result);
533
			}
534
			//FIXME: citation from node instead of classification
535
//			copyToNode.addChildNode(clone,classification.getCitation(), classification.getMicroReference());
536
			copyToNode.addChildNode(clone, clone.getReference(), clone.getMicroReference());
537
		}
538
		return childNodes;
539
	}
540

    
541
}
(7-7/92)