001package org.apache.maven.graph;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *   http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.util.ArrayList;
023import java.util.Collection;
024import java.util.HashSet;
025import java.util.List;
026import java.util.Set;
027
028import org.apache.commons.lang3.Validate;
029import org.apache.maven.execution.ProjectDependencyGraph;
030import org.apache.maven.project.DuplicateProjectException;
031import org.apache.maven.project.MavenProject;
032import org.apache.maven.project.ProjectSorter;
033import org.codehaus.plexus.util.dag.CycleDetectedException;
034
035/**
036 * Describes the inter-dependencies between projects in the reactor.
037 *
038 * @author Benjamin Bentmann
039 */
040public class DefaultProjectDependencyGraph
041    implements ProjectDependencyGraph
042{
043
044    private ProjectSorter sorter;
045
046    /**
047     * Creates a new project dependency graph based on the specified projects.
048     *
049     * @param projects The projects to create the dependency graph with
050     * @throws DuplicateProjectException
051     * @throws CycleDetectedException
052     */
053    public DefaultProjectDependencyGraph( Collection<MavenProject> projects )
054        throws CycleDetectedException, DuplicateProjectException
055    {
056        this.sorter = new ProjectSorter( projects );
057    }
058
059    public List<MavenProject> getSortedProjects()
060    {
061        return new ArrayList<>( sorter.getSortedProjects() );
062    }
063
064    public List<MavenProject> getDownstreamProjects( MavenProject project, boolean transitive )
065    {
066        Validate.notNull( project, "project cannot be null" );
067
068        Set<String> projectIds = new HashSet<>();
069
070        getDownstreamProjects( ProjectSorter.getId( project ), projectIds, transitive );
071
072        return getSortedProjects( projectIds );
073    }
074
075    private void getDownstreamProjects( String projectId, Set<String> projectIds, boolean transitive )
076    {
077        for ( String id : sorter.getDependents( projectId ) )
078        {
079            if ( projectIds.add( id ) && transitive )
080            {
081                getDownstreamProjects( id, projectIds, transitive );
082            }
083        }
084    }
085
086    public List<MavenProject> getUpstreamProjects( MavenProject project, boolean transitive )
087    {
088        Validate.notNull( project, "project cannot be null" );
089
090        Set<String> projectIds = new HashSet<>();
091
092        getUpstreamProjects( ProjectSorter.getId( project ), projectIds, transitive );
093
094        return getSortedProjects( projectIds );
095    }
096
097    private void getUpstreamProjects( String projectId, Collection<String> projectIds, boolean transitive )
098    {
099        for ( String id : sorter.getDependencies( projectId ) )
100        {
101            if ( projectIds.add( id ) && transitive )
102            {
103                getUpstreamProjects( id, projectIds, transitive );
104            }
105        }
106    }
107
108    private List<MavenProject> getSortedProjects( Set<String> projectIds )
109    {
110        List<MavenProject> result = new ArrayList<>( projectIds.size() );
111
112        for ( MavenProject mavenProject : sorter.getSortedProjects() )
113        {
114            if ( projectIds.contains( ProjectSorter.getId( mavenProject ) ) )
115            {
116                result.add( mavenProject );
117            }
118        }
119
120        return result;
121    }
122
123    @Override
124    public String toString()
125    {
126        return sorter.getSortedProjects().toString();
127    }
128
129}