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 java.util.List; 023 024 import ch.bfh.algo.Direction; 025 import ch.bfh.algo.DirectionException; 026 import ch.bfh.algo.InvalidAccessorException; 027 import ch.bfh.algo.Position; 028 import ch.bfh.algo.core.GenericGraph; 029 import ch.bfh.algo.core.GenericSequence; 030 import ch.bfh.algo.core.position.PositionList; 031 import ch.bfh.algo.core.position.PositionListAdapter; 032 import ch.bfh.algo.core.position.PositionListIterator; 033 import ch.bfh.algo.core.sequence.GenericLinkedSequence; 034 import ch.bfh.algo.graph.GraphFactory; 035 import ch.bfh.algo.sequence.LinkedPosition; 036 import ch.bfh.algo.sequence.LinkedSequence; 037 import ch.bfh.algo.sequence.SequenceFactory; 038 039 public class GenericAdjacencyListGraph<E,V,PE extends GenericEdge<E,V,PE,PV>,PV extends GenericVertex<E,V,PE,PV>> extends GenericLinkedSequence<V,PV> implements GenericGraph<E,V,PE,PV>{ 040 041 private final GenericSequence<E,PE> edgeElements; 042 043 private final LinkedSequence<PV> vertices=new LinkedSequence<PV>(); 044 private final LinkedSequence<PE> directed=new LinkedSequence<PE>(); 045 private final LinkedSequence<PE> undirected=new LinkedSequence<PE>(); 046 private final List<PE> all=new ListMergeAdapter<PE>(this.undirected,this.directed); 047 048 private final LinkedSequence<PE> graphType; // the type is either "this.directed" or "this.undirected" 049 050 private PositionList<V,PV> allVertices; 051 private PositionList<E,PE> allEdges; 052 private PositionList<E,PE> undirectedEdges; 053 private PositionList<E,PE> directedEdges; 054 055 protected final GraphFactory<PE,PV> factory; 056 057 public GenericAdjacencyListGraph(final GraphFactory<PE,PV> factory, boolean directed){ 058 super(new SequenceFactory<PV>(){ 059 public PV cast(Position<?> position){ return factory.castVertex(position); } 060 public PV createPosition(){ return factory.createVertex(); } 061 }); 062 this.edgeElements=new GenericLinkedSequence<E,PE>(new SequenceFactory<PE>(){ 063 public PE cast(Position<?> position){ return factory.castEdge(position); } 064 public PE createPosition(){ return factory.createEdge(); } 065 }); 066 this.factory=factory; 067 if(directed) this.graphType=this.directed; 068 else this.graphType=this.undirected; 069 } 070 071 public GraphFactory<PE,PV> getFactory(){ 072 return this.factory; 073 } 074 075 protected PV insertBetween(PV previous, PV next, V element, PV position){ 076 PV vertex=super.insertBetween(previous,next,element,position); 077 vertex.insert(this.vertices); 078 return vertex; 079 } 080 081 public PV insertVertex(V element){ 082 return this.insert(element); 083 } 084 085 public PE insertEdge(E element){ 086 PE edge=this.edgeElements.insert(element); 087 edge.insert(this.graphType); 088 return edge; 089 } 090 091 public Position<E> insertEdge(E element, Position<?> origin, Position<?> destination) throws InvalidAccessorException { 092 try{return this.insertEdge(element,this.factory.castVertex(origin),this.factory.castVertex(destination));} 093 catch(ClassCastException e){ throw new InvalidAccessorException(); } 094 } 095 096 public PE insertEdge(E element, PV origin, PV destination){ 097 PE edge=this.insertEdge(element); 098 this.setOrigin(edge,origin); 099 this.setDestination(edge,destination); 100 return edge; 101 } 102 103 public V delete(PV position){ 104 return this.deleteVertex(position); 105 } 106 107 public V deleteVertex(PV position){ 108 V element=super.delete(position); 109 position.delete(); 110 return element; 111 } 112 113 public V deleteVertex(Position<?> position) throws InvalidAccessorException { 114 return this.delete(position); 115 } 116 117 public E deleteEdge(Position<?> position) throws InvalidAccessorException { 118 try{return this.deleteEdge(this.factory.castEdge(position));} 119 catch(ClassCastException e){ throw new InvalidAccessorException(); } 120 } 121 122 public E deleteEdge(PE position){ 123 E element=this.edgeElements.delete(position); 124 position.delete(); 125 return element; 126 } 127 128 public PositionList<V,PV> vertices(){ 129 return this.allVertices(); 130 } 131 132 private PositionList<V,PV> allVertices(){ 133 if(this.allVertices==null){ this.allVertices=new PositionListAdapter<V,PV>(this.vertices); } 134 return this.allVertices; 135 } 136 137 public PositionList<E,PE> edges(){ 138 return this.allEdges; 139 } 140 141 public PositionList<E,PE> edges(Direction type){ 142 switch(type){ 143 case ALL : return this.allEdges(); 144 case DIRECTED : return this.directedEdges(); 145 case UNDIRECTED : return this.undirectedEdges(); 146 case IN : return this.directedEdges(); 147 case OUT : return this.directedEdges(); 148 } 149 throw new DirectionException(); 150 } 151 152 private PositionList<E,PE> undirectedEdges(){ 153 if(this.undirectedEdges==null){ this.undirectedEdges=new PositionListAdapter<E,PE>(this.undirected); } 154 return this.undirectedEdges; 155 } 156 157 private PositionList<E,PE> directedEdges(){ 158 if(this.directedEdges==null){ this.directedEdges=new PositionListAdapter<E,PE>(this.directed); } 159 return this.directedEdges; 160 } 161 162 private PositionList<E,PE> allEdges(){ 163 if(this.allEdges==null){ this.allEdges=new PositionListAdapter<E,PE>(this.all); } 164 return this.allEdges; 165 } 166 167 public PositionList<E,PE> incidentEdges(Position<?> vertex, Direction type){ 168 try{return this.incidentEdges(this.factory.castVertex(vertex),type);} 169 catch(ClassCastException e){ throw new InvalidAccessorException(); } 170 } 171 172 public PositionList<E,PE> incidentEdges(PV vertex, Direction type){ 173 this.validate(vertex); 174 return vertex.incidentEdges(type); 175 } 176 177 public PositionList<V,PV> adjacentVertices(Position<?> vertex, Direction type){ 178 try{return this.adjacentVertices(this.factory.castVertex(vertex),type);} 179 catch(ClassCastException e){ throw new InvalidAccessorException(); } 180 } 181 182 public PositionList<V,PV> adjacentVertices(PV vertex, Direction type){ 183 this.validate(vertex); 184 return vertex.adjacentVertices(type); 185 } 186 187 public void setOrigin(Position<?> edge, Position<?> vertex){ 188 try{this.setOrigin(this.factory.castEdge(edge),this.factory.castVertex(vertex));} 189 catch(ClassCastException e){ throw new InvalidAccessorException(); } 190 } 191 192 public LinkedPosition<PE> setOrigin(PE edge, PV origin){ 193 if(!this.edgeElements.encloses(edge)) throw new InvalidAccessorException(); 194 this.validate(origin); 195 if(edge.origin()!=origin){ 196 edge.clearOrigin(); 197 if(edge.isDirected(this.directed)){ 198 return origin.attachOutDirected(edge); 199 } 200 else{ 201 return origin.attachOutUndirected(edge); 202 } 203 } 204 return null; 205 } 206 207 public LinkedPosition<PE> setOriginBefore(PE edge, PV origin, LinkedPosition<PE> position){ 208 if(!this.edgeElements.encloses(edge)) throw new InvalidAccessorException(); 209 this.validate(origin); 210 if(edge.origin()!=origin){ 211 edge.clearOrigin(); 212 if(edge.isDirected(this.directed)){ 213 return origin.attachOutDirectedBefore(edge,position); 214 } 215 else{ 216 return origin.attachOutUndirectedBefore(edge,position); 217 } 218 } 219 return null; 220 } 221 222 public LinkedPosition<PE> setOriginAfter(PE edge, PV origin,LinkedPosition<PE> position){ 223 if(!this.edgeElements.encloses(edge)) throw new InvalidAccessorException(); 224 this.validate(origin); 225 if(edge.origin()!=origin){ 226 edge.clearOrigin(); 227 if(edge.isDirected(this.directed)){ 228 return origin.attachOutDirectedAfter(edge,position); 229 } 230 else{ 231 return origin.attachOutUndirectedAfter(edge,position); 232 } 233 } 234 return null; 235 } 236 237 public void setDestination(Position<?> edge, Position<?> vertex){ 238 try{this.setDestination(this.factory.castEdge(edge),this.factory.castVertex(vertex));} 239 catch(ClassCastException e){ throw new InvalidAccessorException(); } 240 } 241 242 public void setDestination(PE edge, PV destination){ 243 if(!this.edgeElements.encloses(edge)) throw new InvalidAccessorException(); 244 this.validate(destination); 245 if(edge.destination()!=destination){ 246 edge.clearDestination(); 247 if(edge.isDirected(this.directed)){ 248 destination.attachInDirected(edge); 249 } 250 else{ 251 destination.attachInUndirected(edge); 252 } 253 } 254 } 255 256 public void detach(Position<?> edge, Position<?> vertex){ 257 try{this.detach(this.factory.castEdge(edge),this.factory.castVertex(vertex));} 258 catch(ClassCastException e){ throw new InvalidAccessorException(); } 259 } 260 261 public void detachVertex(PE edge, PV vertex){ 262 if(!this.edgeElements.encloses(edge)) throw new InvalidAccessorException(); 263 this.validate(vertex); 264 if(vertex==edge.origin()) edge.clearOrigin(); 265 else if(vertex==edge.destination()) edge.clearDestination(); 266 267 } 268 269 public PV origin(Position<?> edge){ 270 try{return this.origin(this.factory.castEdge(edge));} 271 catch(ClassCastException e){ throw new InvalidAccessorException(); } 272 } 273 274 public PV origin(PE edge){ 275 if(!this.edgeElements.encloses(edge)) throw new InvalidAccessorException(); 276 return edge.origin(); 277 } 278 279 public PV destination(Position<?> edge){ 280 try{return this.destination(this.factory.castEdge(edge));} 281 catch(ClassCastException e){ throw new InvalidAccessorException(); } 282 } 283 284 public PV destination(PE edge){ 285 if(!this.edgeElements.encloses(edge)) throw new InvalidAccessorException(); 286 return edge.destination(); 287 } 288 289 public void setDirected(Position<?> edge){ 290 try{this.setDirected(this.factory.castEdge(edge));} 291 catch(ClassCastException e){ throw new InvalidAccessorException(); } 292 } 293 294 public void setDirected(PE edge){ 295 if(!this.isDirected(edge)){ 296 edge.setDirected(this.directed); 297 } 298 } 299 300 public void setUndirected(Position<?> edge){ 301 try{this.setUndirected(this.factory.castEdge(edge));} 302 catch(ClassCastException e){ throw new InvalidAccessorException(); } 303 } 304 305 public void setUndirected(PE edge){ 306 if(this.isDirected(edge)){ 307 edge.setUndirected(this.undirected); 308 } 309 } 310 311 public boolean isDirected(Position<?> edge){ 312 try{return this.isDirected(this.factory.castEdge(edge));} 313 catch(ClassCastException e){ throw new InvalidAccessorException(); } 314 } 315 316 public boolean isDirected(PE edge){ 317 if(!this.edgeElements.encloses(edge)) throw new InvalidAccessorException(); 318 return edge.isDirected(this.directed); 319 } 320 321 public void reverse(Position<?> edge){ 322 try{this.reverse(this.factory.castEdge(edge));} 323 catch(ClassCastException e){ throw new InvalidAccessorException(); } 324 } 325 326 public void reverse(PE edge){ 327 if(!this.edgeElements.encloses(edge)) throw new InvalidAccessorException(); 328 GenericVertex<E,V,PE,PV> v0=edge.origin(), v1=edge.destination(); 329 if(v0!=v1){ 330 if(v1!=null) this.setOrigin(edge,v1); 331 if(v0!=null) this.setDestination(edge,v0); 332 } 333 } 334 335 public PV opposite(Position<?> edge, Position<?> vertex){ 336 try{return this.opposite(this.factory.castEdge(edge),this.factory.castVertex(vertex));} 337 catch(ClassCastException e){ throw new InvalidAccessorException(); } 338 } 339 340 public PV opposite(PE edge, PV vertex){ 341 if(!this.edgeElements.encloses(edge)) throw new InvalidAccessorException(); 342 this.validate(vertex); 343 return edge.oppositeVertex(vertex); 344 } 345 346 public V replaceVertex(Position<?> vertex, V element){ 347 return this.replace(vertex,element); 348 } 349 350 public E replaceEdge(Position<?> edge, E element){ 351 return this.edgeElements.replace(edge,element); 352 } 353 354 public void swapEdge(Position<?> edge0, Position<?> edge1){ 355 this.edgeElements.swap(edge0,edge1); 356 } 357 358 public void swapVertex(Position<?> vertex0, Position<?> vertex1){ 359 this.swap(vertex0,vertex1); 360 } 361 362 public GenericSequence<V,PV> vertexElements(){ 363 return this; 364 } 365 366 public GenericSequence<E,PE> edgeElements(){ 367 return this.edgeElements; 368 } 369 370 public PV insertBefore(PV position, V element){ 371 throw new UnsupportedOperationException(); 372 } 373 374 public PV insertAfter(PV position, V element){ 375 throw new UnsupportedOperationException(); 376 } 377 378 public PositionListIterator<V,PV> positionListIterator(){ 379 return super.positionListIterator(); 380 } 381 382 public PositionListIterator<V,PV> positionListIterator(int rank){ 383 return super.positionListIterator(rank); 384 } 385 386 public E edgeElement(Position<?> edge){ 387 try{return this.edgeElement(this.factory.castEdge(edge));} 388 catch(ClassCastException e){ throw new InvalidAccessorException(); } 389 } 390 391 public E edgeElement(PE edge){ 392 return this.edgeElements.element(edge); 393 } 394 395 public V vertexElement(Position<?> vertex){ 396 return this.element(vertex); 397 } 398 399 }