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.graph;
021    
022    import ch.bfh.algo.InvalidAccessorException;
023    import ch.bfh.algo.core.sequence.GenericLinkedPosition;
024    import ch.bfh.algo.sequence.LinkedPosition;
025    import ch.bfh.algo.sequence.LinkedSequence;
026    
027    public class GenericEdge<E,V,PE extends GenericEdge<E,V,PE,PV>,PV extends GenericVertex<E,V,PE,PV>> extends GenericLinkedPosition<E,PE>{
028            
029            private static final int ORIGIN=0, DESTINATION=1, GRAPH=2;
030            private final LinkedPosition<PE>[] edgePos=new LinkedPosition[3];
031    
032            private PV origin;      
033            private PV destination; 
034    
035            private LinkedPosition<PE> attachEdgeAfter(int index, LinkedSequence<PE> sequence, LinkedPosition<PE> position){
036                    this.edgePos[index]=sequence.insertAfter(position,(PE)this);
037                    return this.edgePos[index];
038            }
039    
040            private LinkedPosition<PE> attachEdgeBefore(int index, LinkedSequence<PE> sequence, LinkedPosition<PE> position){
041                    this.edgePos[index]=sequence.insertBefore(position,(PE)this);
042                    return this.edgePos[index];
043            }
044    
045            private LinkedPosition<PE> attachEdge(int index, LinkedSequence<PE> sequence){
046                    this.edgePos[index]=sequence.insert((PE)this);
047                    return this.edgePos[index];
048            }
049    
050            private void detachEdge(int index){
051                    this.edgePos[index].container().delete(this.edgePos[index]);
052                    this.edgePos[index]=null;
053            }
054            
055            protected void insert(LinkedSequence<PE> type){
056                    this.attachEdge(GRAPH,type);
057            }
058    
059            protected void delete(){
060                    this.clearOrigin();
061                    this.clearDestination();
062                    this.detachEdge(GRAPH);
063            }
064            
065            protected boolean isDirected(LinkedSequence<PE> type){
066                    return this.edgePos[GRAPH].container()==type;
067            }
068    
069            protected void setDirected(LinkedSequence<PE> type){
070                    this.detachEdge(GRAPH);
071                    this.attachEdge(GRAPH,type);
072                    if(this.origin!=null){
073                            this.detachEdge(ORIGIN);
074                            this.origin.attachOutDirected(this);
075                    }
076                    if(this.destination!=null){
077                            this.detachEdge(DESTINATION);
078                            this.destination.attachInDirected(this);
079                    }
080            }
081    
082            protected void setUndirected(LinkedSequence<PE> type){
083                    this.detachEdge(GRAPH);
084                    this.attachEdge(GRAPH,type);
085                    if(this.origin!=null){
086                            this.detachEdge(ORIGIN);
087                            this.origin.attachOutUndirected(this);
088                    }
089                    if(this.destination!=null){
090                            this.detachEdge(DESTINATION);
091                            this.destination.attachInUndirected(this);
092                    }
093            }
094    
095            protected PV origin(){
096                    return this.origin;
097            }
098            
099            protected PV destination(){
100                    return this.destination;
101            }
102            
103            protected LinkedPosition<PE> setOrigin(PV origin, LinkedSequence<PE> allEdges){
104                    this.origin=origin;
105                    return this.attachEdge(ORIGIN,allEdges);
106            }
107            
108            protected LinkedPosition<PE> setOriginBefore(PV origin, LinkedSequence<PE> allEdges, LinkedPosition<PE> position){
109                    this.origin=origin;
110                    return this.attachEdgeBefore(ORIGIN,allEdges,position);
111            }
112            
113            protected LinkedPosition<PE> setOriginAfter(PV origin, LinkedSequence<PE> allEdges, LinkedPosition<PE> position){
114                    this.origin=origin;
115                    return this.attachEdgeAfter(ORIGIN,allEdges,position);
116            }
117            
118            protected void setDestination(PV destination, LinkedSequence<PE> allEdges){
119                    this.destination=destination;
120                    this.attachEdge(DESTINATION,allEdges);
121            }
122            
123            protected void clearOrigin(){
124                    if(this.origin!=null){
125                            this.detachEdge(ORIGIN);
126                            this.origin=null;
127                    }
128            }
129            
130            protected void clearDestination(){
131                    if(this.destination!=null){
132                            this.detachEdge(DESTINATION);
133                            this.destination=null;
134                    }
135            }
136            
137            protected void clearVertex(GenericVertex<E,V,PE,PV> vertex){
138                    if(vertex==this.origin) this.clearOrigin();
139                    if(vertex==this.destination) this.clearDestination();
140            }
141            
142            protected PV oppositeVertex(GenericVertex<?,?,PE,PV> vertex){
143                    if(vertex==this.origin) return this.destination;
144                    if(vertex==this.destination) return this.origin;
145                    throw new InvalidAccessorException();
146            }
147    }