org.codehaus.plexus.util.dag.DAG Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of plexus-utils Show documentation
Show all versions of plexus-utils Show documentation
A collection of various utility classes to ease working with strings, files, command lines, XML and more.
package org.codehaus.plexus.util.dag;
/*
* Copyright The Codehaus Foundation.
*
* 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.
*/
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* DAG = Directed Acyclic Graph
*
* @author Michal Maczka
* @version $Id$
* TODO this class should be renamed from DAG to Dag
*/
public class DAG
implements Cloneable, Serializable
{
// ------------------------------------------------------------
// Fields
// ------------------------------------------------------------
/**
* Nodes will be kept in two data structures at the same time for faster processing
*/
/**
* Maps vertex's label to vertex
*/
private Map vertexMap = new HashMap();
/**
* Conatin list of all vertices
*/
private List vertexList = new ArrayList();
// ------------------------------------------------------------
// Constructors
// ------------------------------------------------------------
/**
*
*/
public DAG()
{
super();
}
// ------------------------------------------------------------
// Accessors
// ------------------------------------------------------------
/**
* @return
*/
public List getVertices()
{
return vertexList;
}
/**
* @deprecated instead use {@link #getVertices()}
*/
@Deprecated
public List getVerticies()
{
return getVertices();
}
public Set getLabels()
{
return vertexMap.keySet();
}
// ------------------------------------------------------------
// Implementation
// ------------------------------------------------------------
/**
* Adds vertex to DAG. If vertex of given label already exist in DAG no vertex is added
*
* @param label The label of the Vertex
* @return New vertex if vertex of given label was not present in the DAG or existing vertex if vertex of given
* label was already added to DAG
*/
public Vertex addVertex( final String label )
{
Vertex retValue = null;
// check if vertex is already in DAG
if ( vertexMap.containsKey( label ) )
{
retValue = vertexMap.get( label );
}
else
{
retValue = new Vertex( label );
vertexMap.put( label, retValue );
vertexList.add( retValue );
}
return retValue;
}
public void addEdge( final String from, final String to )
throws CycleDetectedException
{
final Vertex v1 = addVertex( from );
final Vertex v2 = addVertex( to );
addEdge( v1, v2 );
}
public void addEdge( final Vertex from, final Vertex to )
throws CycleDetectedException
{
from.addEdgeTo( to );
to.addEdgeFrom( from );
final List cycle = CycleDetector.introducesCycle( to );
if ( cycle != null )
{
// remove edge which introduced cycle
removeEdge( from, to );
final String msg = "Edge between '" + from + "' and '" + to + "' introduces to cycle in the graph";
throw new CycleDetectedException( msg, cycle );
}
}
public void removeEdge( final String from, final String to )
{
final Vertex v1 = addVertex( from );
final Vertex v2 = addVertex( to );
removeEdge( v1, v2 );
}
public void removeEdge( final Vertex from, final Vertex to )
{
from.removeEdgeTo( to );
to.removeEdgeFrom( from );
}
public Vertex getVertex( final String label )
{
final Vertex retValue = (Vertex) vertexMap.get( label );
return retValue;
}
public boolean hasEdge( final String label1, final String label2 )
{
final Vertex v1 = getVertex( label1 );
final Vertex v2 = getVertex( label2 );
final boolean retValue = v1.getChildren().contains( v2 );
return retValue;
}
/**
* @param label
* @return
*/
public List getChildLabels( final String label )
{
final Vertex vertex = getVertex( label );
return vertex.getChildLabels();
}
/**
* @param label
* @return
*/
public List getParentLabels( final String label )
{
final Vertex vertex = getVertex( label );
return vertex.getParentLabels();
}
/**
* @see java.lang.Object#clone()
*/
public Object clone()
throws CloneNotSupportedException
{
// this is what's failing..
final Object retValue = super.clone();
return retValue;
}
/**
* Indicates if there is at least one edge leading to or from vertex of given label
*
* @return true
if this vertex is connected with other vertex,false
otherwise
*/
public boolean isConnected( final String label )
{
final Vertex vertex = getVertex( label );
final boolean retValue = vertex.isConnected();
return retValue;
}
/**
* Return the list of labels of successor in order decided by topological sort
*
* @param label The label of the vertex whose predecessors are searched
* @return The list of labels. Returned list contains also the label passed as parameter to this method. This label
* should always be the last item in the list.
*/
public List getSuccessorLabels( final String label )
{
final Vertex vertex = getVertex( label );
final List retValue;
// optimization.
if ( vertex.isLeaf() )
{
retValue = new ArrayList( 1 );
retValue.add( label );
}
else
{
retValue = TopologicalSorter.sort( vertex );
}
return retValue;
}
}