Project

General

Profile

« Previous | Next » 

Revision c40252b2

Added by Andreas Müller almost 10 years ago

cleaning up TaxonNode class and also refactoring solution for #4200

View differences:

cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/taxon/TaxonNode.java
117 117
    private List<TaxonNode> childNodes = new ArrayList<TaxonNode>();
118 118

  
119 119
    //see https://dev.e-taxonomy.eu/trac/ticket/3722
120
    //see https://dev.e-taxonomy.eu/trac/ticket/4200
120 121
    private Integer sortIndex = -1;
121
    public Integer getSortIndex() {
122
		return sortIndex;
123
	}
124
    public Integer setSortIndex(Integer i) {
125
		return sortIndex = i;
126
	}
127
	
128 122

  
129 123
	@XmlElement(name = "reference")
130 124
    @XmlIDREF
......
176 170
        setTaxon(taxon);
177 171
    }
178 172

  
173
// ************************* GETTER / SETTER *******************************/
174
    
175
    public Integer getSortIndex() {
176
		return sortIndex;
177
	}
178
    /**
179
     * SortIndex shall be handled only internally, therefore not public.
180
     * However, as javaassist only supports protected methods it needs to be protected, not private
181
     * @param i
182
     * @return
183
     * @deprecated for internal use only
184
     */
185
     protected Integer setSortIndex(Integer i) { 										 // 
186
		return sortIndex = i;
187
	}
188
    
179 189

  
190
    public Taxon getTaxon() {
191
        return taxon;
192
    }
193
    protected void setTaxon(Taxon taxon) {
194
        this.taxon = taxon;
195
        if (taxon != null){
196
            taxon.addTaxonNode(this);
197
        }
198
    }
199
    
180 200

  
181
//************************ METHODS **************************/
201
    @Override
202
    public List<TaxonNode> getChildNodes() {
203
        return childNodes;
204
    }
205
	protected void setChildNodes(List<TaxonNode> childNodes) {
206
		this.childNodes = childNodes;	
207
	}
208

  
209
    
210
    public Classification getClassification() {
211
        return classification;
212
    }
213
    /**
214
     * THIS METHOD SHOULD NOT BE CALLED!
215
     * invisible part of the bidirectional relationship, for public use TaxonomicView.addRoot() or TaxonNode.addChild()
216
     * @param classification
217
     * @deprecated for internal use only
218
     */
219
    protected void setClassification(Classification classification) {
220
        this.classification = classification;
221
    }
222
    
182 223

  
183 224
    @Override
225
    public String getMicroReference() {
226
        return microReferenceForParentChildRelation;
227
    }
228
    public void setMicroReference(String microReference) {
229
        this.microReferenceForParentChildRelation = microReference;
230
    }
231
    
232

  
233
    @Override
234
    public Reference getReference() {
235
        return referenceForParentChildRelation;
236
    }
237
    public void setReference(Reference reference) {
238
        this.referenceForParentChildRelation = reference;
239
    }
240

  
241
    //countChildren
242
    public int getCountChildren() {
243
        return countChildren;
244
    }
245
    /**
246
     * @deprecated for internal use only
247
     * @param countChildren
248
     */
249
    protected void setCountChildren(int countChildren) {
250
        this.countChildren = countChildren;
251
    }
252
    
253

  
254
    //parent
255
    @Override
256
    public TaxonNode getParent(){
257
        return parent;
258
    }
259
    /**
260
     * Sets the parent of this taxon node.<BR>
261
     *
262
     * In most cases you would want to call setParentTreeNode(ITreeNode) which
263
     * handles updating of the bidirectional relationship
264
     *
265
     * @see setParentTreeNode(ITreeNode)
266
     * @param parent
267
     *
268
     */
269
    protected void setParent(TaxonNode parent) {
270
        this.parent = parent;
271
    }
272
    
273

  
274
    //synonymToBeused
275
    public Synonym getSynonymToBeUsed() {
276
        return synonymToBeUsed;
277
    }
278
    public void setSynonymToBeUsed(Synonym synonymToBeUsed) {
279
        this.synonymToBeUsed = synonymToBeUsed;
280
    }
281
    
282

  
283
    //treeindex
284
    @Override
285
    public String treeIndex() {
286
        return treeIndex;
287
    }
288
    @Override
289
    @Deprecated //for CDM lib internal use only, may be removed in future versions
290
    public void setTreeIndex(String treeIndex) {
291
        this.treeIndex = treeIndex;
292
    }
293
    
294

  
295

  
296
//************************ METHODS **************************/
297

  
298
   @Override
184 299
    public TaxonNode addChildTaxon(Taxon taxon, Reference citation, String microCitation) {
185 300
        return addChildTaxon(taxon, this.childNodes.size(), citation, microCitation);
186

  
187 301
    }
188 302

  
189 303

  
......
232 346
            throw new IllegalAncestryException("New parent node is a descendant of the node to be moved.");
233 347
        }
234 348

  
235
        child.setParentTreeNode(this, index);
236

  
237
//        //TODO workaround (see sortIndex doc) => not really required anymore here, 
238
//        //     as it is done in child.setParentTreeNode already
239
//        int childrenCount = childNodes.size();
240
//        for(int i = 0; i < childrenCount; i++){
241
//        	TaxonNode pc = childNodes.get(i);
242
//        	if (pc != null){
243
//        		pc = CdmBase.deproxy(pc, TaxonNode.class); //unfortunately this is required as the new sortindex is not persisted otherwise for some strange reason #4200 
244
//        		pc.setSortIndex(i);
245
//        	}else{
246
//        		throw new IllegalStateException("A node in a taxon tree must never be null but is (ParentId: " + getId() + "; sort index: " + sortIndex);
247
//        	}
248
//        }
249
//        child.setSortIndex(index);
250

  
349
        child.setParentTreeNode(this, index); 
350
        
251 351
        child.setReference(reference);
252 352
        child.setMicroReference(microReference);
253 353

  
254 354
        return child;
255

  
256 355
    }
257 356

  
258 357
    /**
......
284 383
        node.setTaxon(null);
285 384
        taxon.removeTaxonNode(node);
286 385

  
287

  
288 386
        ArrayList<TaxonNode> childNodes = new ArrayList<TaxonNode>(node.getChildNodes());
289 387
        for(TaxonNode childNode : childNodes){
290 388
            node.deleteChildNode(childNode);
291 389
        }
292 390

  
293
//		// two iterations because of ConcurrentModificationErrors
294
//        Set<TaxonNode> removeNodes = new HashSet<TaxonNode>();
295
//        for (TaxonNode grandChildNode : node.getChildNodes()) {
296
//                removeNodes.add(grandChildNode);
297
//        }
298
//        for (TaxonNode childNode : removeNodes) {
299
//                childNode.deleteChildNode(node);
300
//        }
301

  
302 391
        return result;
303 392
    }
304 393

  
394
    /**
395
     * Deletes the child node and also removes children of childnode 
396
     * recursively if delete children is <code>true</code>
397
     * @param node
398
     * @param deleteChildren
399
     * @return
400
     */
305 401
    public boolean deleteChildNode(TaxonNode node, boolean deleteChildren) {
306 402
        boolean result = removeChildNode(node);
307 403
        Taxon taxon = node.getTaxon();
......
319 415
            }
320 416
        }
321 417

  
322
//		// two iterations because of ConcurrentModificationErrors
323
//        Set<TaxonNode> removeNodes = new HashSet<TaxonNode>();
324
//        for (TaxonNode grandChildNode : node.getChildNodes()) {
325
//                removeNodes.add(grandChildNode);
326
//        }
327
//        for (TaxonNode childNode : removeNodes) {
328
//                childNode.deleteChildNode(node);
329
//        }
330

  
331 418
        return result;
332 419
    }
333 420

  
......
350 437
        } else {
351 438
            result = false;
352 439
        }
353

  
354

  
355
//		OLD
356
//        if(HibernateProxyHelper.deproxy(childNode.getParent(), TaxonNode.class) != this){
357
//            throw new IllegalArgumentException("TaxonNode must be a child of this node");
358
//        }
359
//
360
//        result = childNodes.remove(childNode);
361
//        this.countChildren--;
362
//        if (this.countChildren < 0){
363
//            throw new IllegalStateException("Children count must not be negative ");
364
//        }
365
//        childNode.setParent(null);
366
//        childNode.setClassification(null);
367

  
368 440
        return result;
369 441
    }
370 442

  
......
397 469
                throw new IllegalStateException("Parent of child is null in TaxonNode.removeChild(int). This should not happen.");
398 470
            }
399 471
            childNodes.remove(index);
472
            child.setClassification(null);
473
            
474
            //update sortindex
475
            //TODO workaround (see sortIndex doc)
400 476
            this.countChildren = childNodes.size();
401 477
            child.setParent(null);
402
            //TODO workaround (see sortIndex doc)
403
            for(int i = 0; i < countChildren; i++){
404
                TaxonNode childAt = childNodes.get(i);
405
                if (childAt != null){
406
                	childAt = CdmBase.deproxy(childAt, TaxonNode.class);
407
            		childAt.setSortIndex(i);
408
                }else{
409
               		String message = "A node in a taxon tree must never be null but is (ParentId: %d; sort index: %d; index: %d; i: %d)";
410
            		throw new IllegalStateException(String.format(message, getId(), sortIndex, index, i));
411
                }
412
            }
478
            
479
            updateSortIndex(childNodes, index);
413 480
            child.setSortIndex(null);
414
            child.setClassification(null);
415 481
        }
416 482
    }
417 483

  
......
442 508
        }
443 509
    }
444 510

  
445
//*********** GETTER / SETTER ***********************************/
446

  
447
    @Override
448
    public String treeIndex() {
449
        return treeIndex;
450
    }
451

  
452
    @Override
453
    @Deprecated //for CDM lib internal use only, may be removed in future versions
454
    public void setTreeIndex(String treeIndex) {
455
        this.treeIndex = treeIndex;
456
    }
457

  
458

  
459 511
    @Override
460 512
    @Deprecated //for CDM lib internal use only, may be removed in future versions
461 513
    public int treeId() {
......
467 519
        }
468 520
    }
469 521

  
470
    public Taxon getTaxon() {
471
        return taxon;
472
    }
473
    protected void setTaxon(Taxon taxon) {
474
        this.taxon = taxon;
475
        if (taxon != null){
476
            taxon.addTaxonNode(this);
477
        }
478
    }
479

  
480

  
481
    @Override
482
    public TaxonNode getParent(){
483
        return parent;
484
    }
485

  
486
    /**
487
     * Sets the parent of this taxon node.
488
     *
489
     * In most cases you would want to call setParentTreeNode(ITreeNode) which
490
     * handles updating of the bidirectional relationship
491
     *
492
     * @param parent
493
     *
494
     * @see setParentTreeNode(ITreeNode)
495
     */
496
    protected void setParent(TaxonNode parent) {
497
        this.parent = parent;
498
    }
499 522

  
500 523
    /**
501 524
     * Sets the parent of this taxon node to the given parent. Cleans up references to
......
543 566
            parentChildren.add(index, this);
544 567
        }
545 568

  
569
        
570
        //sortIndex
546 571
        //TODO workaround (see sortIndex doc)
547
        for(int i = 0; i < parentChildren.size(); i++){
548
        	TaxonNode pc = parentChildren.get(i);
549
        	if (pc != null){
550
        		pc = CdmBase.deproxy(pc, TaxonNode.class);  //unfortunately this is required as the new sortindex is not persisted otherwise for some strange reason #4200 
551
        		pc.setSortIndex(i);
552
        	}else{
553
        		String message = "A node in a taxon tree must never be null but is (ParentId: %d; sort index: %d; index: %d; i: %d)";
554
        		throw new IllegalStateException(String.format(message, getId(), sortIndex, index, i));
555
        	}
556
        }
572
        updateSortIndex(parentChildren, index);
557 573
        //only for debugging
558 574
        if (! this.getSortIndex().equals(index)){
559 575
        	logger.warn("index and sortindex are not equal");
560 576
        }
561 577
        
562

  
563 578
        // update the children count
564 579
        parent.setCountChildren(parent.getChildNodes().size());
565 580
    }
581
    
582
	/**
583
	 * As long as the sort index is not correctly handled through hibernate this is a workaround method
584
	 * to update the sort index manually
585
	 * @param parentChildren
586
	 * @param index
587
	 */
588
	private void updateSortIndex(List<TaxonNode> children, int index) {
589
		for(int i = index; i < children.size(); i++){
590
        	TaxonNode child = children.get(i);
591
        	if (child != null){
592
//        		child = CdmBase.deproxy(child, TaxonNode.class);  //deproxy not needed as long as setSortIndex is protected or public #4200
593
        		child.setSortIndex(i);
594
        	}else{
595
        		String message = "A node in a taxon tree must never be null but is (ParentId: %d; sort index: %d; index: %d; i: %d)";
596
        		throw new IllegalStateException(String.format(message, getId(), sortIndex, index, i));
597
        	}
598
        }
599
	}
600

  
566 601

  
567
    public Classification getClassification() {
568
        return classification;
569
    }
570
    /**
571
     * THIS METHOD SHOULD NOT BE CALLED!
572
     * invisible part of the bidirectional relationship, for public use TaxonomicView.addRoot() or TaxonNode.addChild()
573
     * @param classification
574
     */
575
    protected void setClassification(Classification classification) {
576
        this.classification = classification;
577
    }
578 602

  
579
    @Override
580
    public List<TaxonNode> getChildNodes() {
581
        return childNodes;
582
    }
583 603

  
584 604
    /**
585 605
     * Returns a set containing this node and all nodes that are descendants of this node
......
615 635
                childClone.addChildNode(childChild.cloneDescendants(), childChild.getReference(), childChild.getMicroReference());
616 636
            }
617 637
            clone.addChildNode(childClone, childNode.getReference(), childNode.getMicroReference());
618

  
619

  
620 638
            //childClone.addChildNode(childNode.cloneDescendants());
621 639
        }
622 640
        return clone;
......
638 656
    }
639 657

  
640 658

  
641
    @Override
642
    public Reference getReference() {
643
        return referenceForParentChildRelation;
644
    }
645
   public void setReference(Reference reference) {
646
        this.referenceForParentChildRelation = reference;
647
    }
648

  
649

  
650
    @Override
651
    public String getMicroReference() {
652
        return microReferenceForParentChildRelation;
653
    }
654
    public void setMicroReference(String microReference) {
655
        this.microReferenceForParentChildRelation = microReference;
656
    }
657

  
658
    /**
659
     * @return the count of children this taxon node has
660
     */
661
    public int getCountChildren() {
662
        return countChildren;
663
    }
664

  
665
    /**
666
     * @param countChildren
667
     */
668
    private void setCountChildren(int countChildren) {
669
        this.countChildren = countChildren;
670
    }
671

  
672
    public Synonym getSynonymToBeUsed() {
673
        return synonymToBeUsed;
674
    }
675
    public void setSynonymToBeUsed(Synonym synonymToBeUsed) {
676
        this.synonymToBeUsed = synonymToBeUsed;
677
    }
678

  
679 659
    /**
680 660
     * Whether this TaxonNode is a direct child of the classification TreeNode
681 661
     * @return
......
691 671
    		}
692 672
    	}
693 673

  
694
    	// FIXME This should work but doesn't, due to missing sort indexes
674
    	//TODO remove
675
    	// FIXME This should work but doesn't, due to missing sort indexes, can be removed after fixing #4200, #4098
695 676
    	if (classification != null){          	
696 677
    		classificationCheck = classification.getRootNode().getChildNodes().contains(this);
697 678
    	}else{
......
735 716
     */
736 717
    @Transient
737 718
    public boolean isDescendant(TaxonNode possibleParent){
738
        return possibleParent.getDescendants().contains(this);
719
        return possibleParent == null ? false : possibleParent.isAncestor(this);
739 720
    }
740 721

  
741 722
    /**
742 723
     * Whether this TaxonNode is an ascendant of the given TaxonNode
743 724
     *
744
     *
745 725
     * @param possibleChild
746 726
     * @return true if there are ascendants
747 727
     */
748 728
    @Transient
749 729
    public boolean isAncestor(TaxonNode possibleChild){
750
        return possibleChild.getAncestors().contains(this);
730
        return possibleChild == null ? false : possibleChild.getAncestors().contains(this);
751 731
    }
752 732

  
753 733
    /**
......
793 773
		return (taxon!= null);
794 774
	}
795 775

  
796
	protected void setChildNodes(List<TaxonNode> childNodes) {
797
		this.childNodes = childNodes;
798
		
799
	}
800

  
801 776

  
802 777

  
803 778
}

Also available in: Unified diff