o start the tests over from scratch


git-svn-id: https://svn.apache.org/repos/asf/maven/artifact/branches/CAP@659891 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/maven/mercury/conflict/ConflictResolutionPolicy.java b/src/main/java/org/apache/maven/mercury/conflict/ConflictResolutionPolicy.java
index 70bd8b9..1479d44 100644
--- a/src/main/java/org/apache/maven/mercury/conflict/ConflictResolutionPolicy.java
+++ b/src/main/java/org/apache/maven/mercury/conflict/ConflictResolutionPolicy.java
@@ -1,6 +1,6 @@
 package org.apache.maven.mercury.conflict;
 
-import org.apache.maven.mercury.resolver.MetadataGraphEdge;
+import org.apache.maven.mercury.representation.MetadataGraphEdge;
 
 /*
  * MetadataGraph edge selection policy. Complements GraphConflictResolver by being injected into it
diff --git a/src/main/java/org/apache/maven/mercury/conflict/ConflictResolver.java b/src/main/java/org/apache/maven/mercury/conflict/ConflictResolver.java
index ef2b3e0..b271105 100644
--- a/src/main/java/org/apache/maven/mercury/conflict/ConflictResolver.java
+++ b/src/main/java/org/apache/maven/mercury/conflict/ConflictResolver.java
@@ -16,7 +16,7 @@
  */
 
 import org.apache.maven.mercury.ArtifactScopeEnum;
-import org.apache.maven.mercury.resolver.MetadataGraph;
+import org.apache.maven.mercury.representation.MetadataGraph;
 
 /*
  * Resolves conflicts in the supplied dependency graph. Different implementations will implement
diff --git a/src/main/java/org/apache/maven/mercury/conflict/DefaultConflictResolutionPolicy.java b/src/main/java/org/apache/maven/mercury/conflict/DefaultConflictResolutionPolicy.java
index c21358c..09c9168 100644
--- a/src/main/java/org/apache/maven/mercury/conflict/DefaultConflictResolutionPolicy.java
+++ b/src/main/java/org/apache/maven/mercury/conflict/DefaultConflictResolutionPolicy.java
@@ -1,6 +1,6 @@
 package org.apache.maven.mercury.conflict;
 
-import org.apache.maven.mercury.resolver.MetadataGraphEdge;
+import org.apache.maven.mercury.representation.MetadataGraphEdge;
 import org.apache.maven.mercury.version.ArtifactVersion;
 import org.apache.maven.mercury.version.DefaultArtifactVersion;
 
diff --git a/src/main/java/org/apache/maven/mercury/conflict/DefaultConflictResolver.java b/src/main/java/org/apache/maven/mercury/conflict/DefaultConflictResolver.java
index d095582..bea0c9b 100644
--- a/src/main/java/org/apache/maven/mercury/conflict/DefaultConflictResolver.java
+++ b/src/main/java/org/apache/maven/mercury/conflict/DefaultConflictResolver.java
@@ -20,11 +20,11 @@
 import java.util.TreeSet;
 
 import org.apache.maven.mercury.ArtifactScopeEnum;
-import org.apache.maven.mercury.resolver.ArtifactMetadata;
-import org.apache.maven.mercury.resolver.MetadataGraph;
-import org.apache.maven.mercury.resolver.MetadataGraphEdge;
-import org.apache.maven.mercury.resolver.MetadataGraphVertex;
-import org.apache.maven.mercury.resolver.MetadataResolutionException;
+import org.apache.maven.mercury.representation.ArtifactMetadata;
+import org.apache.maven.mercury.representation.MetadataGraph;
+import org.apache.maven.mercury.representation.MetadataGraphEdge;
+import org.apache.maven.mercury.representation.MetadataGraphVertex;
+import org.apache.maven.mercury.representation.MetadataResolutionException;
 
 /*
  * Default conflict resolver.Implements closer newer first policy by default, but could be
diff --git a/src/main/java/org/apache/maven/mercury/representation/ArtifactMetadata.java b/src/main/java/org/apache/maven/mercury/representation/ArtifactMetadata.java
new file mode 100644
index 0000000..31eafb2
--- /dev/null
+++ b/src/main/java/org/apache/maven/mercury/representation/ArtifactMetadata.java
@@ -0,0 +1,273 @@
+package org.apache.maven.mercury.representation;
+
+import java.util.Collection;
+
+import org.apache.maven.mercury.Artifact;
+import org.apache.maven.mercury.ArtifactScopeEnum;
+
+/*
+ * Artifact Metadata that is resolved independent of Artifact itself.
+ * 
+ * @author <a href="oleg@codehaus.org">Oleg Gusakov</a>
+ */
+public class ArtifactMetadata
+{
+    /** 
+     * standard glorified artifact coordinates
+     */
+    protected String groupId;
+
+    protected String artifactId;
+
+    protected String version;
+
+    protected String type = "jar";
+
+    protected ArtifactScopeEnum artifactScope;
+
+    protected String classifier;
+
+    /** 
+     * explanation: why this MD was chosen over it's siblings
+     * in the resulting structure (classpath for now) 
+     */
+    protected String why;
+
+    /** dependencies of the artifact behind this metadata */
+    protected Collection<ArtifactMetadata> dependencies;
+
+    /** metadata URI */
+    protected String uri;
+
+    /** is metadata found anywhere */
+    protected boolean resolved = false;
+
+    /** does the actual artifact for this metadata exists */
+    protected boolean artifactExists = false;
+
+    /** artifact URI */
+    protected String artifactUri;
+
+    /** error message  */
+    private String error;
+
+    public ArtifactMetadata( String groupId, String name, String version )
+    {
+        this( groupId, name, version, null );
+    }
+
+    public ArtifactMetadata( String groupId, String name, String version, String type )
+    {
+        this( groupId, name, version, type, null );
+    }
+
+    public ArtifactMetadata( String groupId, String name, String version, String type, ArtifactScopeEnum artifactScope )
+    {
+        this( groupId, name, version, type, artifactScope, null );
+    }
+
+    public ArtifactMetadata( String groupId, String name, String version, String type, ArtifactScopeEnum artifactScope, String classifier )
+    {
+        this( groupId, name, version, type, artifactScope, classifier, null );
+    }
+
+    public ArtifactMetadata( String groupId, String name, String version, String type, ArtifactScopeEnum artifactScope, String classifier, String artifactUri )
+    {
+        this( groupId, name, version, type, artifactScope, classifier, artifactUri, null, true, null );
+    }
+
+    public ArtifactMetadata( String groupId, String name, String version, String type, ArtifactScopeEnum artifactScope, String classifier, String artifactUri, String why, boolean resolved,
+                             String error )
+    {
+        this.groupId = groupId;
+        this.artifactId = name;
+        this.version = version;
+        this.type = type;
+        this.artifactScope = artifactScope;
+        this.classifier = classifier;
+        this.artifactUri = artifactUri;
+        this.why = why;
+        this.resolved = resolved;
+        this.error = error;
+    }
+
+    public ArtifactMetadata( String groupId, String name, String version, String type, String scopeString, String classifier, String artifactUri, String why, boolean resolved, String error )
+    {
+        this( groupId, name, version, type, scopeString == null ? ArtifactScopeEnum.DEFAULT_SCOPE : ArtifactScopeEnum.valueOf( scopeString ), classifier, artifactUri, why, resolved, error );
+    }
+
+    public ArtifactMetadata( Artifact af )
+    {
+    }
+
+    @Override
+    public String toString()
+    {
+        return groupId + ":" + artifactId + ":" + version;
+    }
+
+    public String toDomainString()
+    {
+        return groupId + ":" + artifactId;
+    }
+
+    public String getGroupId()
+    {
+        return groupId;
+    }
+
+    public void setGroupId( String groupId )
+    {
+        this.groupId = groupId;
+    }
+
+    public String getArtifactId()
+    {
+        return artifactId;
+    }
+
+    public void setArtifactId( String name )
+    {
+        this.artifactId = name;
+    }
+
+    public String getVersion()
+    {
+        return version;
+    }
+
+    public void setVersion( String version )
+    {
+        this.version = version;
+    }
+
+    public String getType()
+    {
+        return type;
+    }
+
+    public String getCheckedType()
+    {
+        return type == null ? "jar" : type;
+    }
+
+    public void setType( String type )
+    {
+        this.type = type;
+    }
+
+    public ArtifactScopeEnum getArtifactScope()
+    {
+        return artifactScope == null ? ArtifactScopeEnum.DEFAULT_SCOPE : artifactScope;
+    }
+
+    public void setArtifactScope( ArtifactScopeEnum artifactScope )
+    {
+        this.artifactScope = artifactScope;
+    }
+
+    public void setScope( String scope )
+    {
+        this.artifactScope = scope == null ? ArtifactScopeEnum.DEFAULT_SCOPE : ArtifactScopeEnum.valueOf( scope );
+    }
+
+    public String getClassifier()
+    {
+        return classifier;
+    }
+
+    public void setClassifier( String classifier )
+    {
+        this.classifier = classifier;
+    }
+
+    public boolean isResolved()
+    {
+        return resolved;
+    }
+
+    public void setResolved( boolean resolved )
+    {
+        this.resolved = resolved;
+    }
+
+    public String getUri()
+    {
+        return uri;
+    }
+
+    public void setUri( String uri )
+    {
+        this.uri = uri;
+    }
+
+    public String getScope()
+    {
+        return getArtifactScope().getScope();
+    }
+
+    public ArtifactScopeEnum getScopeAsEnum()
+    {
+        return artifactScope == null ? ArtifactScopeEnum.DEFAULT_SCOPE : artifactScope;
+    }
+
+    public boolean isArtifactExists()
+    {
+        return artifactExists;
+    }
+
+    public void setArtifactExists( boolean artifactExists )
+    {
+        this.artifactExists = artifactExists;
+    }
+
+    public Collection<ArtifactMetadata> getDependencies()
+    {
+        return dependencies;
+    }
+
+    public void setDependencies( Collection<ArtifactMetadata> dependencies )
+    {
+        this.dependencies = dependencies;
+    }
+
+    public String getArtifactUri()
+    {
+        return artifactUri;
+    }
+
+    public void setArtifactUri( String artifactUri )
+    {
+        this.artifactUri = artifactUri;
+    }
+
+    public String getWhy()
+    {
+        return why;
+    }
+
+    public void setWhy( String why )
+    {
+        this.why = why;
+    }
+
+    public String getError()
+    {
+        return error;
+    }
+
+    public void setError( String error )
+    {
+        this.error = error;
+    }
+
+    public boolean isError()
+    {
+        return error == null;
+    }
+
+    public String getDependencyConflictId()
+    {
+        return groupId + ":" + artifactId;
+    }
+}
diff --git a/src/main/java/org/apache/maven/mercury/representation/DefaultMetadataResolver.java b/src/main/java/org/apache/maven/mercury/representation/DefaultMetadataResolver.java
new file mode 100644
index 0000000..20825b6
--- /dev/null
+++ b/src/main/java/org/apache/maven/mercury/representation/DefaultMetadataResolver.java
@@ -0,0 +1,98 @@
+package org.apache.maven.mercury.representation;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.maven.mercury.Artifact;
+import org.apache.maven.mercury.ArtifactRepository;
+import org.apache.maven.mercury.DefaultArtifact;
+import org.apache.maven.mercury.retrieve.ArtifactRetriever;
+import org.apache.maven.mercury.retrieve.ResolutionRequest;
+import org.apache.maven.mercury.retrieve.ResolutionResult;
+
+/*
+ * default implementation of the metadata resolver
+ * 
+ * @author Oleg Gusakov
+ * 
+ * @plexus.component
+ */
+public class DefaultMetadataResolver
+    implements MetadataResolver
+{
+    //------------------------------------------------------------------------
+
+    /** @plexus.requirement */
+    ArtifactRetriever artifactResolver;
+
+    /** @plexus.requirement */
+    MetadataSource metadataSource;
+
+    //------------------------------------------------------------------------
+    public MetadataResolutionResult resolveMetadata( MetadataResolutionRequest request )
+        throws MetadataResolutionException
+    {
+        MetadataResolutionResult result = new MetadataResolutionResult();
+
+        MetadataTreeNode tree = resolveMetadataTree( request.getQuery(), null, request.getLocalRepository(), request.getRemoteRepositories() );
+
+        result.setTree( tree );
+
+        return result;
+    }
+
+    //------------------------------------------------------------------------
+    private MetadataTreeNode resolveMetadataTree( ArtifactMetadata query, MetadataTreeNode parent, ArtifactRepository localRepository, List<ArtifactRepository> remoteRepositories )
+        throws MetadataResolutionException
+    {
+        try
+        {
+            Artifact pomArtifact = new DefaultArtifact( query.getGroupId(), query.getArtifactId(), query.getVersion(), query.getType(), null, false, query.getScope(), null );
+
+            ResolutionRequest request = new ResolutionRequest().setArtifact( pomArtifact ).setLocalRepository( localRepository ).setRemoteRepostories( remoteRepositories );
+
+            ResolutionResult result = artifactResolver.retrieve( request );
+
+            // Here we just need to deal with basic retrieval problems.
+            if ( result.hasExceptions() )
+            {
+                pomArtifact.setResolved( false );
+            }
+
+            if ( pomArtifact.isResolved() )
+            {
+                MetadataResolution metadataResolution = metadataSource.retrieve( query, localRepository, remoteRepositories );
+                ArtifactMetadata found = metadataResolution.getArtifactMetadata();
+
+                if ( pomArtifact.getFile() != null && pomArtifact.getFile().toURI() != null )
+                {
+                    found.setArtifactUri( pomArtifact.getFile().toURI().toString() );
+                }
+
+                MetadataTreeNode node = new MetadataTreeNode( found, parent, true, found.getScopeAsEnum() );
+                Collection<ArtifactMetadata> dependencies = metadataResolution.getArtifactMetadata().getDependencies();
+
+                if ( dependencies != null && dependencies.size() > 0 )
+                {
+                    int numberOfChildren = dependencies.size();
+                    node.setNChildren( numberOfChildren );
+                    int kidNo = 0;
+                    for ( ArtifactMetadata a : dependencies )
+                    {
+                        MetadataTreeNode kidNode = resolveMetadataTree( a, node, localRepository, remoteRepositories );
+                        node.addChild( kidNo++, kidNode );
+                    }
+                }
+                return node;
+            }
+            else
+            {
+                return new MetadataTreeNode( pomArtifact, parent, false, query.getArtifactScope() );
+            }
+        }
+        catch ( Exception anyEx )
+        {
+            throw new MetadataResolutionException( anyEx );
+        }
+    }
+}
diff --git a/src/main/java/org/apache/maven/mercury/representation/MetadataGraph.java b/src/main/java/org/apache/maven/mercury/representation/MetadataGraph.java
new file mode 100644
index 0000000..3319a6b
--- /dev/null
+++ b/src/main/java/org/apache/maven/mercury/representation/MetadataGraph.java
@@ -0,0 +1,462 @@
+package org.apache.maven.mercury.representation;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeSet;
+
+import org.apache.maven.mercury.ArtifactScopeEnum;
+
+
+/**
+ * maven dependency metadata graph
+ * 
+ * @author <a href="oleg@codehaus.org">Oleg Gusakov</a>
+ *
+ */
+
+public class MetadataGraph
+{
+	public static int DEFAULT_VERTICES = 32;
+	public static int DEFAULT_EDGES    = 64;
+	
+	// flags to indicate the granularity of vertices
+	private boolean versionedVertices = false;
+	private boolean scopedVertices    = false;
+	/**
+	 * the entry point we started building the graph from
+	 */
+    MetadataGraphVertex entry;
+    
+    // graph vertices
+    TreeSet< MetadataGraphVertex >  vertices;
+
+    /** 
+     * incident and excident edges per node
+     */
+    Map<MetadataGraphVertex, List<MetadataGraphEdge>> incidentEdges;
+    Map<MetadataGraphVertex, List<MetadataGraphEdge>> excidentEdges;
+    
+    /**
+     *  null in dirty graph, actual 
+     *  scope for conflict-resolved graph
+     */
+    ArtifactScopeEnum scope;
+
+    //------------------------------------------------------------------------
+    /**
+     * init graph
+     */
+    public MetadataGraph( int nVertices )
+    {
+    	init( nVertices, 2*nVertices );
+    }
+    public MetadataGraph( int nVertices, int nEdges )
+    {
+    	init( nVertices, nEdges );
+    }
+    //------------------------------------------------------------------------
+    /**
+     * construct a single vertex
+     */
+    public MetadataGraph( MetadataGraphVertex entry )
+    throws MetadataResolutionException
+    {
+    	checkVertex(entry);
+    	checkVertices(1);
+
+    	entry.setCompareVersion( versionedVertices );
+    	entry.setCompareScope( scopedVertices );
+
+    	vertices.add( entry );
+    	this.entry = entry;
+    }
+    //------------------------------------------------------------------------
+    /**
+     * construct graph from a "dirty" tree
+     */
+    public MetadataGraph( MetadataTreeNode tree )
+    throws MetadataResolutionException
+    {
+    	this( tree, false, false );
+    }
+    //------------------------------------------------------------------------
+    /**
+     * construct graph from a "dirty" tree
+     * 
+     * @param tree "dirty" tree root
+     * @param versionedVertices true if graph nodes should be versioned (different versions -> different nodes)
+     * @param scopedVertices true if graph nodes should be versioned and scoped (different versions and/or scopes -> different nodes)
+     * 
+     */
+    public MetadataGraph( MetadataTreeNode tree, boolean versionedVertices, boolean scopedVertices )
+    throws MetadataResolutionException
+    {
+        if ( tree == null )
+        {
+            throw new MetadataResolutionException( "tree is null" );
+        }
+
+        setVersionedVertices(versionedVertices);
+        setScopedVertices(scopedVertices);
+        
+        this.versionedVertices = scopedVertices || versionedVertices;
+        this.scopedVertices = scopedVertices;
+        
+        int count = countNodes( tree );
+
+        init( count, count + ( count / 2 ) );
+
+        processTreeNodes( null, tree, 0, 0 );
+    }
+    //------------------------------------------------------------------------
+    private void processTreeNodes(   MetadataGraphVertex parentVertex
+                               , MetadataTreeNode node
+                               , int depth
+                               , int pomOrder
+    						)
+    throws MetadataResolutionException
+    {
+        if ( node == null )
+        {
+            return;
+        }
+
+        MetadataGraphVertex vertex = new MetadataGraphVertex( node.md, versionedVertices, scopedVertices );
+        if( ! vertices.contains(vertex) )
+        {
+        	vertices.add(vertex);
+        }
+
+        if( parentVertex != null ) // then create the edge
+        { 
+            ArtifactMetadata md = node.getMd();
+            MetadataGraphEdge e = new MetadataGraphEdge( md.version, md.resolved, md.artifactScope, md.artifactUri, depth, pomOrder );
+            addEdge( parentVertex, vertex, e);
+        }
+        else
+        {
+        	entry = vertex;
+        }
+
+        MetadataTreeNode[] kids = node.getChildren();
+        if ( kids == null || kids.length < 1 )
+        {
+            return;
+        }
+
+        for( int i = 0; i< kids.length; i++ )
+        {
+        	MetadataTreeNode n = kids[i];
+            processTreeNodes( vertex, n, depth + 1, i );
+        }
+    }
+    //------------------------------------------------------------------------
+    public MetadataGraphVertex findVertex( ArtifactMetadata md )
+    {
+    	if( md == null || vertices == null || vertices.size() < 1 )
+    		return null;
+    	
+    	MetadataGraphVertex v = new MetadataGraphVertex(md);
+    	v.setCompareVersion(versionedVertices);
+    	v.setCompareScope(scopedVertices);
+
+    	for( MetadataGraphVertex gv : vertices  )
+    	{
+    		if( gv.equals(v) )
+    			return gv;
+    	}
+    	
+    	return null;
+    }
+    //------------------------------------------------------------------------
+    public MetadataGraphVertex addVertex( ArtifactMetadata md )
+    {
+    	if( md == null )
+    		return null;
+   
+    	checkVertices();
+    	
+    	MetadataGraphVertex v = findVertex(md);
+    	if( v != null)
+    		return v;
+    	
+    	v = new MetadataGraphVertex(md);
+    	
+    	v.setCompareVersion(versionedVertices);
+    	v.setCompareScope(scopedVertices);
+
+    	vertices.add( v );
+    	return v;
+    }
+    //------------------------------------------------------------------------
+    /**
+     * init graph
+     */
+    private void init( int nVertices, int nEdges )
+    {
+    	int nV = nVertices;
+    	if( nVertices < 1 )
+    		nV = 1;
+ 
+    	checkVertices(nV);
+
+    	int nE = nVertices;
+    	if( nEdges <= nV )
+    		nE = 2*nE;
+ 
+    	checkEdges(nE);
+    }
+
+    private void checkVertices()
+    {
+    	checkVertices(DEFAULT_VERTICES);
+    }
+
+    private void checkVertices( int nVertices )
+    {
+    	if( vertices == null )
+    		vertices = new TreeSet<MetadataGraphVertex>();
+    }
+    private void checkEdges()
+    {
+    	int count = DEFAULT_EDGES;
+    	
+    	if( vertices != null )
+    		count = vertices.size() + vertices.size() / 2;
+
+    	checkEdges( count );
+    }
+    private void checkEdges( int nEdges )
+    {
+    	if( incidentEdges == null )
+    		incidentEdges = new HashMap<MetadataGraphVertex, List<MetadataGraphEdge>>( nEdges );
+    	if( excidentEdges == null )
+    		excidentEdges = new HashMap<MetadataGraphVertex, List<MetadataGraphEdge>>( nEdges );
+    }
+    //------------------------------------------------------------------------
+    private static void checkVertex( MetadataGraphVertex v )
+    throws MetadataResolutionException
+    {
+    	if( v == null )
+    		throw new MetadataResolutionException( "null vertex" );
+    	if( v.getMd() == null )
+    		throw new MetadataResolutionException( "vertex without metadata" );
+    }
+    //------------------------------------------------------------------------
+    private static void checkEdge( MetadataGraphEdge e )
+    throws MetadataResolutionException
+    {
+    	if( e == null )
+    		throw new MetadataResolutionException( "badly formed edge" );
+    }
+    //------------------------------------------------------------------------
+    public List<MetadataGraphEdge> getEdgesBetween(
+    							  MetadataGraphVertex vFrom
+    							, MetadataGraphVertex vTo
+    							)
+    {
+    	List<MetadataGraphEdge> edges = getIncidentEdges(vTo);
+    	if( edges == null || edges.isEmpty() )
+    		return null;
+    	
+    	List<MetadataGraphEdge> res = new ArrayList<MetadataGraphEdge>( edges.size() );
+    	
+    	for( MetadataGraphEdge e : edges )
+    	{
+    		if( e.getSource().equals(vFrom) )
+    			res.add(e);
+    	}
+    	
+    	return res;
+    }
+    //------------------------------------------------------------------------
+    public MetadataGraph addEdge( MetadataGraphVertex vFrom
+    							, MetadataGraphVertex vTo
+    							, MetadataGraphEdge e
+    							)
+    throws MetadataResolutionException
+    {
+    	checkVertex(vFrom);
+    	checkVertex(vTo);
+
+    	checkVertices();
+    	
+    	checkEdge(e);
+    	checkEdges();
+    	
+    	e.setSource(vFrom);
+    	e.setTarget(vTo);
+
+    	vFrom.setCompareVersion(versionedVertices);
+    	vFrom.setCompareScope(scopedVertices);
+    	
+    	List<MetadataGraphEdge> exList = excidentEdges.get(vFrom);
+    	if( exList == null ) {
+    		exList = new ArrayList<MetadataGraphEdge>();
+    		excidentEdges.put( vFrom, exList );
+    	}
+    	
+    	if( !exList.contains(e) )
+    		exList.add(e);
+    	
+    	List<MetadataGraphEdge> inList = incidentEdges.get(vTo);
+    	if( inList == null ) {
+    		inList = new ArrayList<MetadataGraphEdge>();
+    		incidentEdges.put( vTo, inList );
+    	}
+    	
+    	if( !inList.contains(e) )
+    		inList.add(e);
+    	
+    	return this;
+    }
+    //------------------------------------------------------------------------
+    public MetadataGraph removeVertex( MetadataGraphVertex v )
+    {
+    	if( vertices!= null && v != null )
+    		vertices.remove(v);
+    	
+    	if( incidentEdges!= null )
+    		incidentEdges.remove(v);
+    	
+    	if( excidentEdges!= null )
+    		excidentEdges.remove(v);
+
+    	return this;
+    		
+    }
+    //------------------------------------------------------------------------
+    private static int countNodes( MetadataTreeNode tree )
+    {
+        if ( tree == null )
+        {
+            return 0;
+        }
+
+        int count = 1;
+        MetadataTreeNode[] kids = tree.getChildren();
+        if ( kids == null || kids.length < 1 )
+        {
+            return count;
+        }
+        for ( MetadataTreeNode n : kids )
+        {
+            count += countNodes( n );
+        }
+
+        return count;
+    }
+
+    //------------------------------------------------------------------------
+    public MetadataGraphVertex getEntry()
+    {
+        return entry;
+    }
+
+    public void setEntry( MetadataGraphVertex entry )
+    {
+        this.entry = entry;
+    }
+
+    public TreeSet<MetadataGraphVertex> getVertices()
+    {
+        return vertices;
+    }
+    
+	public List<MetadataGraphEdge> getIncidentEdges( MetadataGraphVertex vertex )
+	{
+		checkEdges();
+		return incidentEdges.get(vertex);
+	}
+    
+	public List<MetadataGraphEdge> getExcidentEdges( MetadataGraphVertex vertex )
+	{
+		checkEdges();
+		return excidentEdges.get(vertex);
+	}
+    
+    public boolean isVersionedVertices()
+	{
+		return versionedVertices;
+	}
+	public void setVersionedVertices(boolean versionedVertices)
+	{
+		this.versionedVertices = versionedVertices;
+	}
+	public boolean isScopedVertices()
+	{
+		return scopedVertices;
+	}
+	public void setScopedVertices(boolean scopedVertices)
+	{
+		this.scopedVertices = scopedVertices;
+
+		// scoped graph is versioned by definition
+		if( scopedVertices )
+			versionedVertices = true;
+	}
+	public ArtifactScopeEnum getScope()
+	{
+		return scope;
+	}
+	public void setScope(ArtifactScopeEnum scope)
+	{
+		this.scope = scope;
+	}
+    //------------------------------------------------------------------------
+	public boolean isEmpty()
+	{
+		return
+			entry == null
+			|| vertices == null
+			|| vertices.isEmpty()
+		;
+	}
+    //------------------------------------------------------------------------
+	public boolean isEmptyEdges()
+	{
+		return
+			   isEmpty()
+			|| incidentEdges == null
+			|| incidentEdges.isEmpty()
+		;
+	}
+    //------------------------------------------------------------------------
+	@Override
+	public String toString()
+	{
+		StringBuilder sb = new StringBuilder(512);
+		if( isEmpty() )
+			return "empty";
+		for( MetadataGraphVertex v : vertices )
+		{
+			sb.append("Vertex:  "+v.getMd().toString()+ "\n");
+			List<MetadataGraphEdge> ins = getIncidentEdges(v);
+			if( ins != null )
+				for( MetadataGraphEdge e : ins )
+				{
+					sb.append("       from :  "+e.toString()+"\n");
+				}
+			else
+				sb.append("      no entries\n");
+				
+			List<MetadataGraphEdge> outs = getExcidentEdges(v);
+			if( outs != null )
+				for( MetadataGraphEdge e : outs )
+				{
+					sb.append("        to :  "+e.toString()+ "\n");
+				}
+			else
+				sb.append("      no exit\n");
+				
+			sb.append("-------------------------------------------------\n");
+		}
+		sb.append("=============================================================\n");
+		return sb.toString();
+	}
+	
+    //------------------------------------------------------------------------
+    //------------------------------------------------------------------------
+}
diff --git a/src/main/java/org/apache/maven/mercury/representation/MetadataGraphEdge.java b/src/main/java/org/apache/maven/mercury/representation/MetadataGraphEdge.java
new file mode 100644
index 0000000..a13c6e2
--- /dev/null
+++ b/src/main/java/org/apache/maven/mercury/representation/MetadataGraphEdge.java
@@ -0,0 +1,180 @@
+package org.apache.maven.mercury.representation;
+
+import org.apache.maven.mercury.ArtifactScopeEnum;
+
+
+/**
+ * metadata graph edge - combination of version, scope and depth define 
+ * an edge in the graph
+ * 
+ * @author <a href="oleg@codehaus.org">Oleg Gusakov</a>
+ *
+ */
+
+public class MetadataGraphEdge
+{
+    String            version;
+    ArtifactScopeEnum scope;
+    int               depth = -1;
+    int               pomOrder = -1;
+    boolean           resolved = true;
+    String            artifactUri;
+    
+    /**
+     * capturing where this link came from
+     * and where it is linked to.
+     * 
+     *   In the first implementation only source used for explanatory function
+     */
+    MetadataGraphVertex  source;
+    MetadataGraphVertex  target;
+
+    //----------------------------------------------------------------------------
+    public MetadataGraphEdge( String version
+    						, boolean resolved
+                            , ArtifactScopeEnum scope
+                            , String artifactUri
+                            , int depth
+                            , int pomOrder
+                            )
+    {
+        super();
+        this.version = version;
+        this.scope = scope;
+        this.artifactUri = artifactUri;
+        this.depth = depth;
+        this.resolved = resolved;
+        this.pomOrder = pomOrder;
+    }
+    //----------------------------------------------------------------------------
+    /**
+     * helper for equals
+     */
+    private static boolean objectsEqual( Object o1,
+                                         Object o2 )
+    {
+        if ( o1 == null && o2 == null )
+        {
+            return true;
+        }
+        if ( ( o1 == null && o2 != null )
+            || ( o1 != null && o2 == null )
+            )
+        {
+            return false;
+        }
+        return o1.equals( o2 );
+    }
+
+    //----------------------------------------------------------------------------
+    /**
+     * used to eliminate exact duplicates in the edge list
+     */
+    @Override
+    public boolean equals( Object o )
+    {
+        if ( o instanceof MetadataGraphEdge )
+        {
+            MetadataGraphEdge e = (MetadataGraphEdge) o;
+            
+            return
+                objectsEqual( version, e.version )
+                && ArtifactScopeEnum.checkScope(scope).getScope().equals( 
+                		ArtifactScopeEnum.checkScope(e.scope).getScope()
+                														)
+                && depth == e.depth
+                ;
+        }
+        return false;
+    }
+
+    //----------------------------------------------------------------------------
+    public String getVersion()
+    {
+        return version;
+    }
+
+    public void setVersion( String version )
+    {
+        this.version = version;
+    }
+
+    public ArtifactScopeEnum getScope()
+    {
+        return scope;
+    }
+
+    public void setScope( ArtifactScopeEnum scope )
+    {
+        this.scope = scope;
+    }
+
+    public int getDepth()
+    {
+        return depth;
+    }
+
+    public void setDepth( int depth )
+    {
+        this.depth = depth;
+    }
+
+	public boolean isResolved()
+	{
+		return resolved;
+	}
+
+	public void setResolved(boolean resolved)
+	{
+		this.resolved = resolved;
+	}
+
+	public int getPomOrder()
+	{
+		return pomOrder;
+	}
+
+	public void setPomOrder(int pomOrder)
+	{
+		this.pomOrder = pomOrder;
+	}
+
+	public String getArtifactUri()
+	{
+		return artifactUri;
+	}
+	public void setArtifactUri(String artifactUri)
+	{
+		this.artifactUri = artifactUri;
+	}
+	
+	public MetadataGraphVertex getSource()
+	{
+		return source;
+	}
+	public void setSource(MetadataGraphVertex source)
+	{
+		this.source = source;
+	}
+	public MetadataGraphVertex getTarget()
+	{
+		return target;
+	}
+	public void setTarget(MetadataGraphVertex target)
+	{
+		this.target = target;
+	}
+	@Override
+	public String toString()
+	{
+		return "[ " 
+				+ "FROM:("+( source==null?"no source":(source.md==null?"no source MD":source.md.toString()) )+") "
+				+ "TO:("+( target==null?"no target":(target.md==null?"no target MD":target.md.toString()) )+") "
+					+"version="+version
+					+", scope="+(scope == null ? "null" : scope.getScope())
+					+", depth="+depth+"]"
+				;
+	}
+    //----------------------------------------------------------------------------
+    //----------------------------------------------------------------------------
+}
diff --git a/src/main/java/org/apache/maven/mercury/representation/MetadataGraphVertex.java b/src/main/java/org/apache/maven/mercury/representation/MetadataGraphVertex.java
new file mode 100644
index 0000000..9a411e7
--- /dev/null
+++ b/src/main/java/org/apache/maven/mercury/representation/MetadataGraphVertex.java
@@ -0,0 +1,165 @@
+package org.apache.maven.mercury.representation;
+
+import org.apache.maven.mercury.ArtifactScopeEnum;
+
+
+/**
+ * metadata graph vertice - just a wrapper around artifact's metadata
+ * 
+ * @author <a href="oleg@codehaus.org">Oleg Gusakov</a>
+ *
+ */
+
+public class MetadataGraphVertex
+implements Comparable<MetadataGraphVertex>
+{
+    ArtifactMetadata md;
+
+    // indications to use these in comparrison
+    private boolean compareVersion = false;
+    private boolean compareScope   = false;
+    
+	public MetadataGraphVertex( ArtifactMetadata md )
+    {
+        super();
+        this.md = md;
+    }
+    
+	public MetadataGraphVertex( ArtifactMetadata md, boolean compareVersion, boolean compareScope )
+    {
+        this(md);
+        this.compareVersion = compareVersion;
+        this.compareScope = compareScope;
+    }
+
+    public ArtifactMetadata getMd()
+    {
+        return md;
+    }
+
+    public void setMd( ArtifactMetadata md )
+    {
+        this.md = md;
+    }
+	//---------------------------------------------------------------------
+    public boolean isCompareVersion()
+	{
+		return compareVersion;
+	}
+
+	public void setCompareVersion(boolean compareVersion)
+	{
+		this.compareVersion = compareVersion;
+	}
+
+	public boolean isCompareScope()
+	{
+		return compareScope;
+	}
+
+	public void setCompareScope(boolean compareScope)
+	{
+		this.compareScope = compareScope;
+	}
+
+	//---------------------------------------------------------------------
+	@Override
+	public String toString()
+	{
+		return "["+ (md == null ? "no metadata" : md.toString()) + "]";
+	}
+	//---------------------------------------------------------------------
+	private static int compareStrings( String s1, String s2 )
+	{
+		if( s1 == null && s2 == null )
+			return 0;
+
+		if( s1 == null && s2 != null )
+			return -1;
+
+		if( s1 != null && s2 == null )
+			return 1;
+		
+		return s1.compareTo(s2);
+	}
+	//---------------------------------------------------------------------
+	public int compareTo(MetadataGraphVertex vertex)
+	{
+		if( vertex == null || vertex.getMd() == null )
+			return 1;
+		
+		ArtifactMetadata vmd = vertex.getMd();
+
+		if( vmd == null )
+		{
+			if( md == null )
+				return 0;
+			else
+				return 1;
+		}
+		
+		int g = compareStrings( md.groupId, vmd.groupId );
+		
+		if( g == 0 )
+		{
+			int a = compareStrings( md.artifactId, vmd.artifactId );
+			if( a == 0 )
+			{
+				if( compareVersion )
+				{
+					int v = compareStrings( md.version, vmd.version );
+					if( v == 0) {
+						if( compareScope ) {
+							String s1 = ArtifactScopeEnum.checkScope( md.artifactScope).getScope();
+							String s2 = ArtifactScopeEnum.checkScope(vmd.artifactScope).getScope();
+							return s1.compareTo(s2);
+						}
+						else
+							return 0;
+					}
+					else
+						return v;
+				}
+				else
+					return 0;
+			}
+			else
+				return a;
+		}
+		
+		return g;
+	}
+	//---------------------------------------------------------------------
+	@Override
+	public boolean equals(Object vo)
+	{
+		if( vo == null || !(vo instanceof MetadataGraphVertex) )
+			return false;
+		return compareTo( (MetadataGraphVertex)vo ) == 0;
+	}
+	//---------------------------------------------------------------------
+
+	@Override
+	public int hashCode()
+	{
+		if( md == null )
+			return super.hashCode();
+		StringBuilder hashString = new StringBuilder(128);
+		hashString.append( md.groupId+"|" );
+		hashString.append( md.artifactId+"|" );
+		
+		if( compareVersion )
+			hashString.append(md.version + "|");
+		
+		if( compareScope )
+			hashString.append(md.getArtifactScope() + "|");
+		
+		return  hashString.toString().hashCode();
+
+//		BASE64Encoder b64 = new BASE64Encoder();
+//		return  b64.encode( hashString.toString().getBytes() ).hashCode();
+	}
+	
+	//---------------------------------------------------------------------
+	//---------------------------------------------------------------------
+}
diff --git a/src/main/java/org/apache/maven/mercury/representation/MetadataResolution.java b/src/main/java/org/apache/maven/mercury/representation/MetadataResolution.java
new file mode 100644
index 0000000..9fca383
--- /dev/null
+++ b/src/main/java/org/apache/maven/mercury/representation/MetadataResolution.java
@@ -0,0 +1,54 @@
+package org.apache.maven.mercury.representation;
+
+import java.util.Collection;
+
+import org.apache.maven.mercury.ArtifactRepository;
+
+/**
+ * 
+ * @author Jason van Zyl
+ *  
+ */
+public class MetadataResolution
+{
+    /** resolved MD  */
+    private ArtifactMetadata artifactMetadata;
+
+    /** repositories, added by this POM  */
+    private Collection<ArtifactRepository> metadataRepositories;
+    //-------------------------------------------------------------------
+    public MetadataResolution( ArtifactMetadata artifactMetadata )
+    {
+        this.artifactMetadata = artifactMetadata;
+    }
+    //-------------------------------------------------------------------
+    public MetadataResolution( ArtifactMetadata artifactMetadata,
+    		Collection<ArtifactRepository> metadataRepositories )
+    {
+    	this( artifactMetadata );
+        this.metadataRepositories = metadataRepositories;
+    }
+    //-------------------------------------------------------------------
+	public Collection<ArtifactRepository> getMetadataRepositories()
+	{
+		return metadataRepositories;
+	}
+
+	public void setMetadataRepositories(
+			Collection<ArtifactRepository> metadataRepositories)
+	{
+		this.metadataRepositories = metadataRepositories;
+	}
+    //-------------------------------------------------------------------
+	public ArtifactMetadata getArtifactMetadata()
+	{
+		return artifactMetadata;
+	}
+
+	public void setArtifactMetadata(ArtifactMetadata artifactMetadata)
+	{
+		this.artifactMetadata = artifactMetadata;
+	}
+    //-------------------------------------------------------------------
+    //-------------------------------------------------------------------
+}
diff --git a/src/main/java/org/apache/maven/mercury/representation/MetadataResolutionException.java b/src/main/java/org/apache/maven/mercury/representation/MetadataResolutionException.java
new file mode 100644
index 0000000..d7faa2d
--- /dev/null
+++ b/src/main/java/org/apache/maven/mercury/representation/MetadataResolutionException.java
@@ -0,0 +1,31 @@
+package org.apache.maven.mercury.representation;
+
+public class MetadataResolutionException
+    extends Exception
+{
+
+    public MetadataResolutionException()
+    {
+        // TODO Auto-generated constructor stub
+    }
+
+    public MetadataResolutionException( String message )
+    {
+        super( message );
+        // TODO Auto-generated constructor stub
+    }
+
+    public MetadataResolutionException( Throwable cause )
+    {
+        super( cause );
+        // TODO Auto-generated constructor stub
+    }
+
+    public MetadataResolutionException( String message,
+                                        Throwable cause )
+    {
+        super( message, cause );
+        // TODO Auto-generated constructor stub
+    }
+
+}
diff --git a/src/main/java/org/apache/maven/mercury/representation/MetadataResolutionRequest.java b/src/main/java/org/apache/maven/mercury/representation/MetadataResolutionRequest.java
new file mode 100644
index 0000000..7a4860e
--- /dev/null
+++ b/src/main/java/org/apache/maven/mercury/representation/MetadataResolutionRequest.java
@@ -0,0 +1,62 @@
+package org.apache.maven.mercury.representation;
+
+import java.util.List;
+
+import org.apache.maven.mercury.ArtifactRepository;
+
+
+/** @author Oleg Gusakov */
+public class MetadataResolutionRequest
+{
+    protected ArtifactMetadata query;
+    protected ArtifactRepository localRepository;
+    protected List<ArtifactRepository> remoteRepositories;
+
+    //--------------------------------------------------------------------
+    public MetadataResolutionRequest()
+    {
+    }
+
+    //--------------------------------------------------------------------
+    public MetadataResolutionRequest( ArtifactMetadata query,
+                                      ArtifactRepository localRepository,
+                                      List<ArtifactRepository> remoteRepositories )
+    {
+        this.query = query;
+        this.localRepository = localRepository;
+        this.remoteRepositories = remoteRepositories;
+    }
+
+    //--------------------------------------------------------------------
+    public ArtifactMetadata getQuery()
+    {
+        return query;
+    }
+
+    public void setQuery( ArtifactMetadata query )
+    {
+        this.query = query;
+    }
+
+    public ArtifactRepository getLocalRepository()
+    {
+        return localRepository;
+    }
+
+    public void setLocalRepository( ArtifactRepository localRepository )
+    {
+        this.localRepository = localRepository;
+    }
+
+    public List<ArtifactRepository> getRemoteRepositories()
+    {
+        return remoteRepositories;
+    }
+
+    public void setRemoteRepositories( List<ArtifactRepository> remoteRepositories )
+    {
+        this.remoteRepositories = remoteRepositories;
+    }
+    //--------------------------------------------------------------------
+    //--------------------------------------------------------------------
+}
diff --git a/src/main/java/org/apache/maven/mercury/representation/MetadataResolutionRequestTypeEnum.java b/src/main/java/org/apache/maven/mercury/representation/MetadataResolutionRequestTypeEnum.java
new file mode 100644
index 0000000..32c1c92
--- /dev/null
+++ b/src/main/java/org/apache/maven/mercury/representation/MetadataResolutionRequestTypeEnum.java
@@ -0,0 +1,26 @@
+package org.apache.maven.mercury.representation;
+
+public enum MetadataResolutionRequestTypeEnum
+{
+      tree( 1 )
+    , graph( 2 )
+    , classpathCompile( 3 )
+    , classpathTest( 4 )
+    , classpathRuntime( 5 )
+    , versionedGraph( 6 )
+    , scopedGraph( 7 )
+    ;
+
+    private int id;
+
+    // Constructor
+    MetadataResolutionRequestTypeEnum( int id )
+    {
+        this.id = id;
+    }
+
+    int getId()
+    {
+        return id;
+    }
+}
diff --git a/src/main/java/org/apache/maven/mercury/representation/MetadataResolutionResult.java b/src/main/java/org/apache/maven/mercury/representation/MetadataResolutionResult.java
new file mode 100644
index 0000000..ac37953
--- /dev/null
+++ b/src/main/java/org/apache/maven/mercury/representation/MetadataResolutionResult.java
@@ -0,0 +1,130 @@
+package org.apache.maven.mercury.representation;
+
+import org.apache.maven.mercury.ArtifactScopeEnum;
+import org.apache.maven.mercury.conflict.ConflictResolutionException;
+import org.apache.maven.mercury.conflict.ConflictResolver;
+import org.apache.maven.mercury.transform.ClasspathContainer;
+import org.apache.maven.mercury.transform.ClasspathTransformation;
+import org.apache.maven.mercury.transform.MetadataGraphTransformationException;
+import org.codehaus.plexus.PlexusContainer;
+import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
+
+/** 
+ * This object is tinted with ClasspathTransformation and GraphConflictResolver. 
+ * Get rid of them after debugging
+ * 
+ * @author <a href="oleg@codehaus.org">Oleg Gusakov</a>
+ */
+public class MetadataResolutionResult
+{
+    MetadataTreeNode treeRoot;
+    
+    /** 
+     * these components are are initialized on demand by
+     * explicit call of the initTreeProcessing() 
+     */ 
+    ClasspathTransformation classpathTransformation;
+    ConflictResolver conflictResolver;
+
+    //----------------------------------------------------------------------------
+    public MetadataResolutionResult( )
+    {
+    }
+    //----------------------------------------------------------------------------
+    public MetadataResolutionResult( MetadataTreeNode root )
+    {
+        this.treeRoot = root;
+    }
+    //----------------------------------------------------------------------------
+    public MetadataTreeNode getTree()
+    {
+        return treeRoot;
+    }
+    //----------------------------------------------------------------------------
+    public void setTree( MetadataTreeNode root )
+    {
+        this.treeRoot = root;
+    }
+    
+    public void initTreeProcessing( PlexusContainer plexus )
+    throws ComponentLookupException
+    {
+        classpathTransformation = (ClasspathTransformation)plexus.lookup(ClasspathTransformation.class);
+        conflictResolver = (ConflictResolver)plexus.lookup(ConflictResolver.class);
+    }
+    //----------------------------------------------------------------------------
+    public MetadataGraph getGraph()
+    throws MetadataResolutionException
+    {
+        return treeRoot == null ? null : new MetadataGraph(treeRoot);
+    }
+    //----------------------------------------------------------------------------
+    public MetadataGraph getGraph( ArtifactScopeEnum scope )
+    throws MetadataResolutionException, ConflictResolutionException
+    {
+    	if( treeRoot == null )
+    		return null;
+    	
+    	if( conflictResolver == null )
+    		return null;
+    	
+        return conflictResolver.resolveConflicts( getGraph(), scope );
+    }
+    //----------------------------------------------------------------------------
+    public MetadataGraph getGraph( MetadataResolutionRequestTypeEnum requestType )
+    throws MetadataResolutionException, ConflictResolutionException
+    {
+    	if( requestType == null )
+    		return null;
+    	
+    	if( treeRoot == null )
+    		return null;
+    	
+    	if( conflictResolver == null )
+    		return null;
+    	
+    	if( requestType.equals(MetadataResolutionRequestTypeEnum.classpathCompile) )
+    		return conflictResolver.resolveConflicts( getGraph(), ArtifactScopeEnum.compile );
+    	else if( requestType.equals(MetadataResolutionRequestTypeEnum.classpathRuntime) )
+    		return conflictResolver.resolveConflicts( getGraph(), ArtifactScopeEnum.runtime );
+    	else if( requestType.equals(MetadataResolutionRequestTypeEnum.classpathRuntime) )
+    		return conflictResolver.resolveConflicts( getGraph(), ArtifactScopeEnum.test );
+    	else if( requestType.equals(MetadataResolutionRequestTypeEnum.classpathRuntime) )
+    		return conflictResolver.resolveConflicts( getGraph(), ArtifactScopeEnum.test );
+    	else if( requestType.equals(MetadataResolutionRequestTypeEnum.graph) )
+    		return getGraph();
+    	else if( requestType.equals(MetadataResolutionRequestTypeEnum.versionedGraph) ) {
+    		return new MetadataGraph( getTree(), true, false );
+    	}
+    	else if( requestType.equals(MetadataResolutionRequestTypeEnum.scopedGraph) ) {
+    		return new MetadataGraph( getTree(), true, true );
+    	}
+		return null;
+    }
+    //----------------------------------------------------------------------------
+    public ClasspathContainer getClasspath( ArtifactScopeEnum scope )
+    throws MetadataGraphTransformationException, MetadataResolutionException
+    {
+        if( classpathTransformation == null )
+        	return null;
+        
+        MetadataGraph dirtyGraph = getGraph();
+        if( dirtyGraph == null )
+        	return null;
+        
+        return classpathTransformation.transform( dirtyGraph, scope, false );
+    }
+    
+    //----------------------------------------------------------------------------
+    public MetadataTreeNode getClasspathTree( ArtifactScopeEnum scope )
+    throws MetadataGraphTransformationException, MetadataResolutionException
+    {
+        ClasspathContainer cpc = getClasspath(scope);
+        if( cpc == null )
+        	return null;
+        
+        return cpc.getClasspathAsTree();
+    }
+    //----------------------------------------------------------------------------
+    //----------------------------------------------------------------------------
+}
diff --git a/src/main/java/org/apache/maven/mercury/representation/MetadataResolver.java b/src/main/java/org/apache/maven/mercury/representation/MetadataResolver.java
new file mode 100644
index 0000000..425f436
--- /dev/null
+++ b/src/main/java/org/apache/maven/mercury/representation/MetadataResolver.java
@@ -0,0 +1,22 @@
+package org.apache.maven.mercury.representation;
+
+/**
+ * entry point into metadata resolution component
+ * 
+ * @author Jason van Zyl
+ * @author Oleg Gusakov
+ */
+public interface MetadataResolver
+{
+    String ROLE = MetadataResolver.class.getName();
+
+    /**
+     * collect all dependency metadata into one "dirty" tree
+     * 
+     * @param request
+     * @return
+     * @throws MetadataResolutionException
+     */
+    MetadataResolutionResult resolveMetadata( MetadataResolutionRequest request )
+        throws MetadataResolutionException;
+}
diff --git a/src/main/java/org/apache/maven/mercury/representation/MetadataRetrievalException.java b/src/main/java/org/apache/maven/mercury/representation/MetadataRetrievalException.java
new file mode 100644
index 0000000..2681c29
--- /dev/null
+++ b/src/main/java/org/apache/maven/mercury/representation/MetadataRetrievalException.java
@@ -0,0 +1,63 @@
+package org.apache.maven.mercury.representation;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+/**
+ * Error while retrieving repository metadata from the repository.
+ *
+ * @author Jason van Zyl
+ * @version $Id$
+ */
+public class MetadataRetrievalException
+    extends Exception
+{
+
+    private ArtifactMetadata artifact;
+
+    public MetadataRetrievalException( String message )
+    {
+        this( message, null, null );
+    }
+
+    public MetadataRetrievalException( Throwable cause )
+    {
+        this( null, cause, null );
+    }
+
+    public MetadataRetrievalException( String message,
+                                       Throwable cause )
+    {
+        this( message, cause, null );
+    }
+
+    public MetadataRetrievalException( String message,
+                                       Throwable cause,
+                                       ArtifactMetadata artifact )
+    {
+        super( message, cause );
+
+        this.artifact = artifact;
+    }
+
+    public ArtifactMetadata getArtifactMetadata()
+    {
+        return artifact;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/org/apache/maven/mercury/representation/MetadataSource.java b/src/main/java/org/apache/maven/mercury/representation/MetadataSource.java
new file mode 100644
index 0000000..215ff08
--- /dev/null
+++ b/src/main/java/org/apache/maven/mercury/representation/MetadataSource.java
@@ -0,0 +1,41 @@
+package org.apache.maven.mercury.representation;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.util.List;
+
+import org.apache.maven.mercury.ArtifactRepository;
+
+/**
+ * Provides some metadata operations, like querying the remote repository for a list of versions available for an
+ * artifact.
+ *
+ * @author Jason van Zyl
+ * @version $Id$
+ */
+public interface MetadataSource
+{
+    String ROLE = MetadataSource.class.getName();
+
+    MetadataResolution retrieve( ArtifactMetadata artifact,
+                                 ArtifactRepository localRepository,
+                                 List<ArtifactRepository> remoteRepositories )
+        throws MetadataRetrievalException;
+}
\ No newline at end of file
diff --git a/src/main/java/org/apache/maven/mercury/representation/MetadataTreeNode.java b/src/main/java/org/apache/maven/mercury/representation/MetadataTreeNode.java
new file mode 100644
index 0000000..8357064
--- /dev/null
+++ b/src/main/java/org/apache/maven/mercury/representation/MetadataTreeNode.java
@@ -0,0 +1,132 @@
+package org.apache.maven.mercury.representation;
+
+import org.apache.maven.mercury.Artifact;
+import org.apache.maven.mercury.ArtifactScopeEnum;
+/**
+ * metadata [dirty] Tree
+ * 
+ * @author <a href="oleg@codehaus.org">Oleg Gusakov</a>
+ *
+ */
+
+public class MetadataTreeNode
+{
+    ArtifactMetadata md; // this node
+
+    MetadataTreeNode parent; // papa
+
+    /** default # of children. Used for tree creation optimization only */
+    int nChildren = 8;
+
+    MetadataTreeNode[] children; // of cause
+
+    public int getNChildren()
+	{
+		return nChildren;
+	}
+
+	public void setNChildren(int children)
+	{
+		nChildren = children;
+	}
+
+	//------------------------------------------------------------------------
+    public MetadataTreeNode()
+    {
+    }
+    //------------------------------------------------------------------------
+    public MetadataTreeNode( ArtifactMetadata md,
+                             MetadataTreeNode parent,
+                             boolean resolved,
+                             ArtifactScopeEnum scope )
+    {
+        if ( md != null )
+        {
+            md.setArtifactScope( ArtifactScopeEnum.checkScope(scope) );
+            md.setResolved(resolved);
+        }
+
+        this.md = md;
+        this.parent = parent;
+    }
+    //------------------------------------------------------------------------
+    public MetadataTreeNode( Artifact af,
+                             MetadataTreeNode parent,
+                             boolean resolved,
+                             ArtifactScopeEnum scope
+                           )
+    {
+        this( new ArtifactMetadata( af ), parent, resolved, scope );
+    }
+    //------------------------------------------------------------------------
+    public void addChild( int index, MetadataTreeNode kid )
+    {
+        if ( kid == null )
+        {
+            return;
+        }
+
+        if( children == null )
+        	children = new MetadataTreeNode[nChildren];
+        
+        children[index % nChildren] = kid;
+    }
+    //------------------------------------------------------------------
+    @Override
+    public String toString()
+    {
+        return md == null ? "no metadata" : md.toString();
+    }
+    //------------------------------------------------------------------
+    public String graphHash()
+        throws MetadataResolutionException
+    {
+        if ( md == null )
+        {
+            throw new MetadataResolutionException( "treenode without metadata, parent: "
+                + ( parent == null ? "null" : parent.toString() )
+            );
+        }
+
+        return md.groupId + ":" + md.artifactId;
+    }
+
+    //------------------------------------------------------------------------
+    public boolean hasChildren()
+    {
+        return children != null;
+    }
+    //------------------------------------------------------------------------
+    public ArtifactMetadata getMd()
+    {
+        return md;
+    }
+
+    public void setMd( ArtifactMetadata md )
+    {
+        this.md = md;
+    }
+
+    public MetadataTreeNode getParent()
+    {
+        return parent;
+    }
+
+    public void setParent( MetadataTreeNode parent )
+    {
+        this.parent = parent;
+    }
+
+    public MetadataTreeNode[] getChildren()
+    {
+        return children;
+    }
+
+    public void setChildren( MetadataTreeNode[] children )
+    {
+        this.children = children;
+    }
+    //------------------------------------------------------------------------
+    //------------------------------------------------------------------------
+
+}
diff --git a/src/main/java/org/apache/maven/mercury/transform/ClasspathContainer.java b/src/main/java/org/apache/maven/mercury/transform/ClasspathContainer.java
index 275170a..087fafc 100644
--- a/src/main/java/org/apache/maven/mercury/transform/ClasspathContainer.java
+++ b/src/main/java/org/apache/maven/mercury/transform/ClasspathContainer.java
@@ -5,9 +5,9 @@
 import java.util.List;
 
 import org.apache.maven.mercury.ArtifactScopeEnum;
-import org.apache.maven.mercury.resolver.ArtifactMetadata;
-import org.apache.maven.mercury.resolver.MetadataResolutionException;
-import org.apache.maven.mercury.resolver.MetadataTreeNode;
+import org.apache.maven.mercury.representation.ArtifactMetadata;
+import org.apache.maven.mercury.representation.MetadataResolutionException;
+import org.apache.maven.mercury.representation.MetadataTreeNode;
 
 /*
  * classpath container that is aware of the classpath scope
diff --git a/src/main/java/org/apache/maven/mercury/transform/ClasspathTransformation.java b/src/main/java/org/apache/maven/mercury/transform/ClasspathTransformation.java
index ce7543b..4eca3f8 100644
--- a/src/main/java/org/apache/maven/mercury/transform/ClasspathTransformation.java
+++ b/src/main/java/org/apache/maven/mercury/transform/ClasspathTransformation.java
@@ -1,7 +1,7 @@
 package org.apache.maven.mercury.transform;
 
 import org.apache.maven.mercury.ArtifactScopeEnum;
-import org.apache.maven.mercury.resolver.MetadataGraph;
+import org.apache.maven.mercury.representation.MetadataGraph;
 
 /*
  * Helper class to conver an Md Graph into some form of a classpath
diff --git a/src/main/java/org/apache/maven/mercury/transform/DefaultClasspathTransformation.java b/src/main/java/org/apache/maven/mercury/transform/DefaultClasspathTransformation.java
index ff28e8c..c7da347 100644
--- a/src/main/java/org/apache/maven/mercury/transform/DefaultClasspathTransformation.java
+++ b/src/main/java/org/apache/maven/mercury/transform/DefaultClasspathTransformation.java
@@ -8,10 +8,10 @@
 import org.apache.maven.mercury.ArtifactScopeEnum;
 import org.apache.maven.mercury.conflict.ConflictResolutionException;
 import org.apache.maven.mercury.conflict.ConflictResolver;
-import org.apache.maven.mercury.resolver.ArtifactMetadata;
-import org.apache.maven.mercury.resolver.MetadataGraph;
-import org.apache.maven.mercury.resolver.MetadataGraphEdge;
-import org.apache.maven.mercury.resolver.MetadataGraphVertex;
+import org.apache.maven.mercury.representation.ArtifactMetadata;
+import org.apache.maven.mercury.representation.MetadataGraph;
+import org.apache.maven.mercury.representation.MetadataGraphEdge;
+import org.apache.maven.mercury.representation.MetadataGraphVertex;
 
 /*
  * default implementation of the metadata classpath transformer
diff --git a/src/test/resources/artifact-install/artifact-1.0.jar b/src/test/resources/artifact-install/artifact-1.0.jar
deleted file mode 100644
index 421376d..0000000
--- a/src/test/resources/artifact-install/artifact-1.0.jar
+++ /dev/null
@@ -1 +0,0 @@
-dummy
diff --git a/src/test/resources/org/apache/maven/artifact/deployer/ArtifactDeployerTest.xml b/src/test/resources/org/apache/maven/artifact/deployer/ArtifactDeployerTest.xml
deleted file mode 100644
index 0e5ffb0..0000000
--- a/src/test/resources/org/apache/maven/artifact/deployer/ArtifactDeployerTest.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<!--
-Licensed to the Apache Software Foundation (ASF) under one
-or more contributor license agreements.  See the NOTICE file
-distributed with this work for additional information
-regarding copyright ownership.  The ASF licenses this file
-to you 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.
--->
-
-<plexus>
-  <components>
-    <component>
-      <role>org.apache.maven.artifact.repository.authentication.AuthenticationInfoProvider</role>
-      <implementation>org.apache.maven.artifact.repository.authentication.DummyAuthenticationInfoProvider</implementation>
-    </component>
-    <component>
-      <role>org.apache.maven.artifact.metadata.ArtifactMetadataSource</role>
-      <implementation>org.apache.maven.artifact.deployer.SimpleArtifactMetadataSource</implementation>      
-    </component>
-  </components>
-</plexus>
\ No newline at end of file
diff --git a/src/test/resources/org/apache/maven/artifact/installer/ArtifactInstallerTest.xml b/src/test/resources/org/apache/maven/artifact/installer/ArtifactInstallerTest.xml
deleted file mode 100644
index 5da76cc..0000000
--- a/src/test/resources/org/apache/maven/artifact/installer/ArtifactInstallerTest.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<!--
-Licensed to the Apache Software Foundation (ASF) under one
-or more contributor license agreements.  See the NOTICE file
-distributed with this work for additional information
-regarding copyright ownership.  The ASF licenses this file
-to you 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.
--->
-
-<plexus>
-  <components>
-    <component>
-      <role>org.apache.maven.artifact.repository.authentication.AuthenticationInfoProvider</role>
-      <implementation>org.apache.maven.artifact.repository.authentication.DummyAuthenticationInfoProvider</implementation>
-    </component>
-  </components>
-</plexus>
\ No newline at end of file
diff --git a/src/test/resources/org/apache/maven/artifact/manager/DefaultWagonManagerTest.xml b/src/test/resources/org/apache/maven/artifact/manager/DefaultWagonManagerTest.xml
deleted file mode 100644
index d0c034c..0000000
--- a/src/test/resources/org/apache/maven/artifact/manager/DefaultWagonManagerTest.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-<!--
-Licensed to the Apache Software Foundation (ASF) under one
-or more contributor license agreements.  See the NOTICE file
-distributed with this work for additional information
-regarding copyright ownership.  The ASF licenses this file
-to you 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.
--->
-
-<plexus>
-  <components>
-    <component>
-      <role>org.apache.maven.wagon.Wagon</role>
-      <role-hint>a</role-hint>
-      <implementation>org.apache.maven.artifact.manager.WagonA</implementation>
-    </component>
-    <component>
-      <role>org.apache.maven.wagon.Wagon</role>
-      <role-hint>b1</role-hint>
-      <implementation>org.apache.maven.artifact.manager.WagonB</implementation>
-    </component>
-    <component>
-      <role>org.apache.maven.wagon.Wagon</role>
-      <role-hint>b2</role-hint>
-      <implementation>org.apache.maven.artifact.manager.WagonB</implementation>
-    </component>
-    <component>
-      <role>org.apache.maven.wagon.Wagon</role>
-      <role-hint>c</role-hint>
-      <implementation>org.apache.maven.artifact.manager.WagonC</implementation>
-    </component>
-    <component>
-      <role>org.apache.maven.wagon.Wagon</role>
-      <role-hint>noop</role-hint>
-      <implementation>org.apache.maven.artifact.manager.WagonNoOp</implementation>
-    </component>
-    <component>
-      <role>org.apache.maven.artifact.repository.authentication.AuthenticationInfoProvider</role>
-      <implementation>org.apache.maven.artifact.repository.authentication.DummyAuthenticationInfoProvider</implementation>
-    </component>
-  </components>
-</plexus>
\ No newline at end of file
diff --git a/src/test/resources/org/apache/maven/artifact/resolver/ArtifactResolverTest.xml b/src/test/resources/org/apache/maven/artifact/resolver/ArtifactResolverTest.xml
deleted file mode 100644
index 5da76cc..0000000
--- a/src/test/resources/org/apache/maven/artifact/resolver/ArtifactResolverTest.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<!--
-Licensed to the Apache Software Foundation (ASF) under one
-or more contributor license agreements.  See the NOTICE file
-distributed with this work for additional information
-regarding copyright ownership.  The ASF licenses this file
-to you 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.
--->
-
-<plexus>
-  <components>
-    <component>
-      <role>org.apache.maven.artifact.repository.authentication.AuthenticationInfoProvider</role>
-      <implementation>org.apache.maven.artifact.repository.authentication.DummyAuthenticationInfoProvider</implementation>
-    </component>
-  </components>
-</plexus>
\ No newline at end of file
diff --git a/src/test/resources/pom.xml b/src/test/resources/pom.xml
deleted file mode 100644
index 9443d87..0000000
--- a/src/test/resources/pom.xml
+++ /dev/null
@@ -1,155 +0,0 @@
-<!--
-Licensed to the Apache Software Foundation (ASF) under one
-or more contributor license agreements.  See the NOTICE file
-distributed with this work for additional information
-regarding copyright ownership.  The ASF licenses this file
-to you 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.
--->
-
-<!--
-Licensed to the Apache Software Foundation (ASF) under one
-or more contributor license agreements.  See the NOTICE file
-distributed with this work for additional information
-regarding copyright ownership.  The ASF licenses this file
-to you 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.
--->
-
-<model xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-  <groupId>org.apache.maven</groupId>
-  <artifactId>maven-core</artifactId>
-  <packaging>jar</packaging>
-  <name>Maven</name>
-  <version>2.0-SNAPSHOT</version>
-  <inceptionYear>2001</inceptionYear>
-  <dependencies>
-    <dependency>
-      <groupId>org.apache.maven</groupId>
-      <artifactId>maven-model</artifactId>
-      <version>2.0-SNAPSHOT</version>
-      <type>jar</type>
-      <scope>compile</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven</groupId>
-      <artifactId>maven-plugin</artifactId>
-      <version>2.0-SNAPSHOT</version>
-      <type>jar</type>
-      <scope>compile</scope>
-    </dependency>
-    <dependency>
-      <groupId>commons-cli</groupId>
-      <artifactId>commons-cli</artifactId>
-      <version>1.0-beta-2</version>
-      <type>jar</type>
-      <scope>compile</scope>
-    </dependency>
-    <dependency>
-      <groupId>plexus</groupId>
-      <artifactId>plexus-i18n</artifactId>
-      <version>1.0-beta-2-SNAPSHOT</version>
-      <type>jar</type>
-      <scope>compile</scope>
-    </dependency>
-    <dependency>
-      <groupId>ognl</groupId>
-      <artifactId>ognl</artifactId>
-      <version>2.5.1</version>
-      <type>jar</type>
-      <scope>compile</scope>
-    </dependency>
-    <dependency>
-      <groupId>marmalade</groupId>
-      <artifactId>marmalade-core</artifactId>
-      <version>0.1</version>
-      <type>jar</type>
-      <scope>compile</scope>
-    </dependency>
-    <dependency>
-      <groupId>marmalade</groupId>
-      <artifactId>marmalade-el-ognl</artifactId>
-      <version>0.1</version>
-      <type>jar</type>
-      <scope>compile</scope>
-    </dependency>
-    <dependency>
-      <groupId>plexus</groupId>
-      <artifactId>plexus-compiler-api</artifactId>
-      <version>1.0</version>
-      <type>jar</type>
-      <scope>compile</scope>
-    </dependency>
-    <dependency>
-      <groupId>plexus</groupId>
-      <artifactId>plexus-compiler-javac</artifactId>
-      <version>1.0</version>
-      <type>jar</type>
-      <scope>compile</scope>
-    </dependency>
-    <dependency>
-      <groupId>surefire</groupId>
-      <artifactId>surefire-booter</artifactId>
-      <version>1.1</version>
-      <type>jar</type>
-      <scope>compile</scope>
-    </dependency>
-    <dependency>
-      <groupId>maven</groupId>
-      <artifactId>wagon-api</artifactId>
-      <version>0.9-SNAPSHOT</version>
-      <type>jar</type>
-      <scope>compile</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.maven</groupId>
-      <artifactId>wagon-http-lightweight</artifactId>
-      <version>0.9-SNAPSHOT</version>
-      <type>jar</type>
-      <scope>compile</scope>
-    </dependency>
-    <dependency>
-      <groupId>maven</groupId>
-      <artifactId>wagon-ssh</artifactId>
-      <version>0.9-SNAPSHOT</version>
-      <type>jar</type>
-      <scope>compile</scope>
-    </dependency>
-    <dependency>
-      <groupId>jsch</groupId>
-      <artifactId>jsch</artifactId>
-      <version>0.1.14</version>
-      <type>jar</type>
-      <scope>compile</scope>
-    </dependency>
-    <dependency>
-      <groupId>qdox</groupId>
-      <artifactId>qdox</artifactId>
-      <version>1.2</version>
-      <type>jar</type>
-      <scope>compile</scope>
-    </dependency>
-  </dependencies>
-</model>