001    /*
002     *  www.ti.bfh.ch
003     *
004     *  Copyright 2007, Berne University of Applied Sciences, 
005     *  School of Engineering and Information Technology
006     *  and individual contributors as indicated by the @authors tag.
007     *
008     *  This is free software; you can redistribute it and/or modify it under the terms of the 
009     *  GNU Lesser General Public License as published by the Free Software Foundation; 
010     *  either version 3 of the License, or (at your option) any later version.
011     *
012     *  This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
013     *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
014     *  See the GNU Lesser General Public License for more details.
015     *
016     *  You should have received a copy of the GNU Lesser General Public License along with this software; 
017     *  if not, see <http://www.gnu.org/licenses/>.
018     *
019     */
020    package ch.bfh.algo.core.forest;
021    
022    import ch.bfh.algo.BoundaryViolationException;
023    import ch.bfh.algo.Direction;
024    import ch.bfh.algo.InvalidAccessorException;
025    import ch.bfh.algo.Position;
026    import ch.bfh.algo.core.GenericForest;
027    import ch.bfh.algo.core.graph.GenericAdjacencyListGraph;
028    import ch.bfh.algo.core.position.PositionIterator;
029    import ch.bfh.algo.core.position.PositionList;
030    import ch.bfh.algo.core.position.PositionListAdapter;
031    import ch.bfh.algo.forest.ForestFactory;
032    import ch.bfh.algo.graph.GraphFactory;
033    import ch.bfh.algo.sequence.LinkedPosition;
034    import ch.bfh.algo.sequence.LinkedSequence;
035    
036    public class GenericForestGraph<E,P extends GenericNode<E,P>> extends GenericAdjacencyListGraph<Object,E,GenericLink<E,P>,P> implements GenericForest<E,P>{
037    
038            private final LinkedSequence<P> roots=new LinkedSequence<P>();
039            
040            public GenericForestGraph(final ForestFactory<P> factory){
041                    super(
042                            new GraphFactory<GenericLink<E,P>,P>(){
043                                    public P createVertex(){ return factory.createVertex(); }
044                                    public P castVertex(Position<?> vertex){ return factory.castVertex(vertex); }
045                                    public GenericLink<E,P> createEdge(){ return new GenericLink<E,P>(); }
046                                    public GenericLink<E,P> castEdge(Position<?> edge){ return (GenericLink<E,P>)edge; }
047                            },
048                            true
049                    );
050            }
051            
052            protected P insertBetween(P previous, P next, E element, P position){
053                    P node=super.insertBetween(previous,next,element,position);
054                    node.markRoot(this.roots);
055                    return node;
056            }
057            
058            public E deleteVertex(P node){
059                    PositionIterator<E,P> children=this.children(node).iterator();
060                    while(children.hasNext()) children.next().markRoot(this.roots);
061                    for(Position<Object> e: this.incidentEdges(node,Direction.ALL)) this.deleteEdge(e);
062                    node.unmarkRoot();
063                    return super.deleteVertex(node);
064            }
065            
066            public void link(Position<?> parent, Position<?> child){
067                    try{this.link(this.factory.castVertex(parent),this.factory.castVertex(child));}
068                    catch(ClassCastException e){ throw new InvalidAccessorException(); }
069            }
070    
071            public void link(P parent, P child){
072                    this.validate(parent);
073                    for(Position<Object> e: this.incidentEdges(child,Direction.IN)) this.deleteEdge(e);
074                    child.unmarkRoot();
075                    GenericLink<E,P> e=this.insertEdge(null);
076                    this.setDestination(e,child);
077                    LinkedPosition<GenericLink<E,P>> p=this.setOrigin(e,parent);
078                    child.setLinkPosition(p);
079            }
080    
081            public void linkAfter(Position<?> sibling, Position<?> node) {
082                    try{this.linkAfter(this.factory.castVertex(sibling),this.factory.castVertex(node));}
083                    catch(ClassCastException e){ throw new InvalidAccessorException(); }
084            }
085    
086            public void linkAfter(P sibling, P node){
087                    if(sibling==node) return;
088                    P parent=this.parent(sibling);
089                    if(parent==null) throw new BoundaryViolationException();
090                    this.linkAfter(parent,node,sibling.getLinkPosition());
091            }
092    
093            private void linkAfter(P parent, P child, LinkedPosition<GenericLink<E,P>> position){
094                    for(Position<Object> e: this.incidentEdges(child,Direction.IN)) this.deleteEdge(e);
095                    child.unmarkRoot();
096                    GenericLink<E,P> e=this.insertEdge(null);
097                    this.setDestination(e,child);
098                    LinkedPosition<GenericLink<E,P>> p=this.setOriginAfter(e,parent,position);
099                    child.setLinkPosition(p);
100            }
101    
102            public void linkBefore(Position<?> sibling, Position<?> node) {
103                    try{this.linkBefore(this.factory.castVertex(sibling),this.factory.castVertex(node));}
104                    catch(ClassCastException e){ throw new InvalidAccessorException(); }
105            }
106            
107            public void linkBefore(P sibling, P node) {
108                    if(sibling==node) return;
109                    P parent=this.parent(sibling);
110                    if(parent==null) throw new BoundaryViolationException();
111                    this.linkBefore(parent,node,sibling.getLinkPosition());
112            }
113            
114            private void linkBefore(P parent, P child, LinkedPosition<GenericLink<E,P>> position){
115                    for(Position<Object> e: this.incidentEdges(child,Direction.IN)) this.deleteEdge(e);
116                    child.unmarkRoot();
117                    GenericLink<E,P> e=this.insertEdge(null);
118                    this.setDestination(e,child);
119                    LinkedPosition<GenericLink<E,P>> p=this.setOriginBefore(e,parent,position);
120                    child.setLinkPosition(p);
121            }
122    
123            public void cut(Position<?> child) {
124                    try{this.cut(this.factory.castVertex(child));}
125                    catch(ClassCastException e){ throw new InvalidAccessorException(); }
126            }
127    
128            public void cut(P child){
129                    for(Position<Object> e: this.incidentEdges(child,Direction.IN)) this.deleteEdge(e);
130                    child.markRoot(this.roots);
131                    child.setLinkPosition(null);
132            }
133    
134            public PositionList<E,P> roots(){
135                    return new PositionListAdapter<E,P>(this.roots);
136            }
137    
138            public P parent(Position<?> child){
139                    PositionIterator<E,P> parent=this.adjacentVertices(child,Direction.IN).iterator();
140                    if(parent.hasNext()) return parent.next();
141                    else return null;
142            }
143    
144            public PositionList<E,P> children(Position<?> parent){
145                    return this.adjacentVertices(parent,Direction.OUT);
146            }
147    }