/* * $Id$ * This file is a part of the Arakhne Foundation Classes, http://www.arakhne.org/afc * * Copyright (c) 2000-2012 Stephane GALLAND. * Copyright (c) 2005-10, Multiagent Team, Laboratoire Systemes et Transports, * Universite de Technologie de Belfort-Montbeliard. * Copyright (c) 2013-2016 The original authors, and other authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.arakhne.afc.math.graph.simple; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import org.eclipse.xtext.xbase.lib.Pure; import org.arakhne.afc.math.graph.GraphPoint; import org.arakhne.afc.references.WeakArrayList; /** This class provides a simple implementation of a graph's point * for a {@link SGraph}. * * @author $Author: sgalland$ * @version $FullVersion$ * @mavengroupid $GroupId$ * @mavenartifactid $ArtifactId$ * @since 13.0 */ public class SGraphPoint implements GraphPoint<SGraphPoint, SGraphSegment> { private final List<SGraphSegment> segments = new WeakArrayList<>(); private final WeakReference<SGraph> graph; private List<Object> userData; /** * @param graph1 is the graph in which the connection is. */ SGraphPoint(SGraph graph1) { this.graph = new WeakReference<>(graph1); } /** Clear the connection. */ void clear() { this.segments.clear(); } /** Add the given segments in the connection. * * @param segments the segments to add. */ void add(Iterable<SGraphSegment> segments) { for (final SGraphSegment segment : segments) { this.segments.add(segment); } } /** Add the given segment in the connection. * * @param segment the segment to add. */ void add(SGraphSegment segment) { this.segments.add(segment); } /** Remove the given segment from the connection. * * @param segment the segment to remove. */ void remove(SGraphSegment segment) { this.segments.remove(segment); } /** Replies the graph in which this connection is. * * @return the graph in which this connection is. */ @Pure public SGraph getGraph() { return this.graph.get(); } @Pure @Override public int getConnectedSegmentCount() { return this.segments.size(); } @Pure @Override public Iterable<SGraphSegment> getConnectedSegments() { return Collections.unmodifiableList(this.segments); } @Pure @Override public boolean isConnectedSegment(SGraphSegment segment) { return this.segments.contains(segment); } @Pure @Override public boolean isFinalConnectionPoint() { return this.segments.size() <= 1; } @Pure @Override public int compareTo(GraphPoint<SGraphPoint, SGraphSegment> pt) { if (pt == null) { return Integer.MAX_VALUE; } return hashCode() - pt.hashCode(); } @Pure @Override public Iterable<SGraphSegment> getConnectedSegmentsStartingFrom(SGraphSegment startingPoint) { final List<SGraphSegment> list = new ArrayList<>(this.segments.size()); int idx = 0; for (final SGraphSegment segment : this.segments) { if (segment != null) { if (idx > 0 || segment.equals(startingPoint)) { list.add(idx, segment); ++idx; } else { list.add(segment); } } } return list; } @Pure @Override public Iterable<? extends GraphPointConnection<SGraphPoint, SGraphSegment>> getConnectionsStartingFrom( SGraphSegment startingPoint) { final List<PointConnection> list = new ArrayList<>(this.segments.size()); int idx = 0; PointConnection connection; for (final SGraphSegment segment : this.segments) { if (segment != null) { if (equals(segment.getBeginPoint())) { connection = new PointConnection(segment, true); } else if (equals(segment.getEndPoint())) { connection = new PointConnection(segment, false); } else { connection = null; } if (connection != null) { if (idx > 0 || segment.equals(startingPoint)) { list.add(idx, connection); ++idx; } else { list.add(connection); } } } } return list; } @Pure @Override public Iterable<? extends GraphPointConnection<SGraphPoint, SGraphSegment>> getConnections() { final Collection<PointConnection> list = new ArrayList<>(this.segments.size()); for (final SGraphSegment segment : this.segments) { if (segment != null) { if (equals(segment.getBeginPoint())) { list.add(new PointConnection(segment, true)); } else if (equals(segment.getEndPoint())) { list.add(new PointConnection(segment, false)); } } } return list; } /** Add a user data in the data associated to this point. * * @param userData the user data to add. * @return <code>true</code> if the data was added; otherwise <code>false</code>. */ public boolean addUserData(Object userData) { if (this.userData == null) { this.userData = new ArrayList<>(); } return this.userData.add(userData); } /** Remove a user data from the data associated to this point. * * @param userData the user data to remove. * @return <code>true</code> if the data was removed; otherwise <code>false</code>. */ public boolean removeUserData(Object userData) { return this.userData != null && this.userData.remove(userData); } /** Replies the number of user data. * * @return the number of user data. */ @Pure public int getUserDataCount() { return (this.userData == null) ? 0 : this.userData.size(); } /** Replies the user data at the given index. * * @param index is the index of the data. * @return the data */ @Pure public Object getUserDataAt(int index) { if (this.userData == null) { throw new IndexOutOfBoundsException(); } return this.userData.get(index); } /** Set the user data at the given index. * * @param index is the index of the data. * @param data is the data */ public void setUserDataAt(int index, Object data) { if (this.userData == null) { throw new IndexOutOfBoundsException(); } this.userData.set(index, data); } /** Replies all the user data. * * @return an unmodifiable collection of user data. */ @Pure public Collection<Object> getAllUserData() { if (this.userData == null) { return Collections.emptyList(); } return Collections.unmodifiableCollection(this.userData); } /** * @author $Author: sgalland$ * @version $FullVersion$ * @mavengroupid $GroupId$ * @mavenartifactid $ArtifactId$ * @since 13.0 */ private class PointConnection implements GraphPointConnection<SGraphPoint, SGraphSegment> { private final WeakReference<SGraphSegment> segment; private boolean connectedWithBeginPoint; /** * @param segment1 is the connected segment. * @param connectedWithBeginPoint1 is <code>true</code> if the segment is connected * by its begin point, <code>false</code> if connected by its end point. */ PointConnection(SGraphSegment segment1, boolean connectedWithBeginPoint1) { this.segment = new WeakReference<>(segment1); this.connectedWithBeginPoint = connectedWithBeginPoint1; } @Pure @Override public SGraphSegment getGraphSegment() { return this.segment.get(); } @Pure @Override public SGraphPoint getGraphPoint() { return SGraphPoint.this; } @Pure @Override public boolean isSegmentStartConnected() { return this.connectedWithBeginPoint; } } }