001/* 002 * Copyright 2006 - 2013 003 * Stefan Balev <stefan.balev@graphstream-project.org> 004 * Julien Baudry <julien.baudry@graphstream-project.org> 005 * Antoine Dutot <antoine.dutot@graphstream-project.org> 006 * Yoann Pigné <yoann.pigne@graphstream-project.org> 007 * Guilhelm Savin <guilhelm.savin@graphstream-project.org> 008 * 009 * This file is part of GraphStream <http://graphstream-project.org>. 010 * 011 * GraphStream is a library whose purpose is to handle static or dynamic 012 * graph, create them from scratch, file or any source and display them. 013 * 014 * This program is free software distributed under the terms of two licenses, the 015 * CeCILL-C license that fits European law, and the GNU Lesser General Public 016 * License. You can use, modify and/ or redistribute the software under the terms 017 * of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following 018 * URL <http://www.cecill.info> or under the terms of the GNU LGPL as published by 019 * the Free Software Foundation, either version 3 of the License, or (at your 020 * option) any later version. 021 * 022 * This program is distributed in the hope that it will be useful, but WITHOUT ANY 023 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 024 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 025 * 026 * You should have received a copy of the GNU Lesser General Public License 027 * along with this program. If not, see <http://www.gnu.org/licenses/>. 028 * 029 * The fact that you are presently reading this means that you have had 030 * knowledge of the CeCILL-C and LGPL licenses and that you accept their terms. 031 */ 032package org.graphstream.graph.implementations; 033 034import org.graphstream.graph.Edge; 035import org.graphstream.graph.Node; 036import org.graphstream.stream.SourceBase.ElementType; 037 038/** 039 * <p> 040 * This class provides a basic implementation of {@code Edge} interface, to 041 * minimize the effort required to implement this interface. 042 * </p> 043 * 044 * <p> 045 * Although this class is abstract it implements all the methods of 046 * {@link org.graphstream.graph.Edge} and 047 * {@link org.graphstream.graph.implementations.AbstractElement}. It has a low 048 * memory overhead (3 references and a boolean as fields). All {@code Edge} 049 * methods are executed in O(1) time. 050 * </p> 051 */ 052public class AbstractEdge extends AbstractElement implements Edge { 053 054 // *** Fields *** 055 056 /** 057 * The source node 058 */ 059 protected AbstractNode source; 060 061 /** 062 * The target node 063 */ 064 protected AbstractNode target; 065 066 /** 067 * Is this edge directed ? 068 */ 069 protected boolean directed; 070 071 /** 072 * The graph to which this edge belongs 073 */ 074 protected AbstractGraph graph; 075 076 // *** Constructors *** 077 078 /** 079 * Constructs a new edge. This constructor copies the parameters into the 080 * corresponding fields. 081 * 082 * @param id 083 * Unique identifier of this edge. 084 * @param source 085 * Source node. 086 * @param target 087 * Target node. 088 * @param directed 089 * Indicates if the edge is directed. 090 */ 091 protected AbstractEdge(String id, AbstractNode source, AbstractNode target, 092 boolean directed) { 093 super(id); 094 assert source != null && target != null : "An edge cannot have null endpoints"; 095 this.source = source; 096 this.target = target; 097 this.directed = directed; 098 this.graph = (AbstractGraph) source.getGraph(); 099 } 100 101 // *** Inherited from AbstractElement *** 102 103 @Override 104 protected void attributeChanged(AttributeChangeEvent event, 105 String attribute, Object oldValue, Object newValue) { 106 graph.listeners.sendAttributeChangedEvent(id, ElementType.EDGE, 107 attribute, event, oldValue, newValue); 108 } 109 110 /** 111 * This implementation calls the corresponding method of the parent graph 112 * 113 * @see org.graphstream.graph.implementations.AbstractElement#nullAttributesAreErrors() 114 */ 115 @Override 116 protected boolean nullAttributesAreErrors() { 117 return graph.nullAttributesAreErrors(); 118 } 119 120 @Override 121 public String toString() { 122 return String.format("%s[%s-%s%s]", getId(), source, directed ? ">" 123 : "-", target); 124 } 125 126 // *** Inherited from Edge *** 127 128 @SuppressWarnings("unchecked") 129 public <T extends Node> T getNode0() { 130 return (T) source; 131 } 132 133 @SuppressWarnings("unchecked") 134 public <T extends Node> T getNode1() { 135 return (T) target; 136 } 137 138 @SuppressWarnings("unchecked") 139 public <T extends Node> T getOpposite(Node node) { 140 if (node == source) 141 return (T) target; 142 if (node == target) 143 return (T) source; 144 return null; 145 } 146 147 @SuppressWarnings("unchecked") 148 public <T extends Node> T getSourceNode() { 149 return (T) source; 150 } 151 152 @SuppressWarnings("unchecked") 153 public <T extends Node> T getTargetNode() { 154 return (T) target; 155 } 156 157 public boolean isDirected() { 158 return directed; 159 } 160 161 public boolean isLoop() { 162 return source == target; 163 } 164}