001    package org.sonar.squid.api;
002    
003    import java.util.Observable;
004    import java.util.Set;
005    import java.util.SortedSet;
006    import java.util.TreeSet;
007    
008    public abstract class TreeNode<E extends TreeNode> extends Observable {
009    
010      private TreeNode     parent;
011      private SortedSet<E> children = new TreeSet<E>();
012    
013      public E addChild(E resource) {
014        resource.setParent(this);
015        if (!children.contains(resource)) {
016          children.add(resource);
017          setChanged();
018          notifyObservers(resource);
019        } 
020        return (E) this;
021      }
022    
023      public E getParent(Class<? extends TreeNode> squidUnit) {
024        if (parent == null) {
025          return null;
026        } else if (parent.getClass().equals(squidUnit)) {
027          return (E) parent;
028        } else {
029          return (E) parent.getParent(squidUnit);
030        }
031      }
032    
033      public E getFirstChild() {
034        return !children.isEmpty() ? children.first() : null;
035      }
036    
037      public E getLastChild() {
038        return !children.isEmpty() ? children.last() : null;
039      }
040    
041      private void setParent(TreeNode parent) {
042        this.parent = parent;
043      }
044    
045      public E getParent() {
046        return (E) parent;
047      }
048    
049      public Set<E> getChildren() {
050        return children;
051      }
052    
053      public boolean hasChild(TreeNode squidUnit) {
054        if (children.contains(squidUnit)) {
055          return true;
056        }
057        for (TreeNode child : children) {
058          if (child.hasChild(squidUnit)) {
059            return true;
060          }
061        }
062        return false;
063      }
064    
065      public boolean hasAmongParents(TreeNode expectedParent) {
066        if (parent == null) {
067          return false;
068        } else if (parent.equals(expectedParent)) {
069          return true;
070        } else {
071          return parent.hasAmongParents(expectedParent);
072        }
073      }
074    
075    }