001    package org.apache.maven.lifecycle.internal;
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    
022    import org.apache.maven.execution.ProjectDependencyGraph;
023    import org.apache.maven.project.MavenProject;
024    
025    import java.util.ArrayList;
026    import java.util.HashSet;
027    import java.util.List;
028    
029    /**
030     * Presents a view of the Dependency Graph that is suited for concurrent building.
031     * 
032     * @since 3.0
033     * @author Kristian Rosenvold
034     *         <p/>
035     *         NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
036     */
037    public class ConcurrencyDependencyGraph
038    {
039    
040        private final ProjectBuildList projectBuilds;
041    
042        private final ProjectDependencyGraph projectDependencyGraph;
043    
044        private final HashSet<MavenProject> finishedProjects = new HashSet<MavenProject>();
045    
046    
047        public ConcurrencyDependencyGraph( ProjectBuildList projectBuilds, ProjectDependencyGraph projectDependencyGraph )
048        {
049            this.projectDependencyGraph = projectDependencyGraph;
050            this.projectBuilds = projectBuilds;
051        }
052    
053    
054        public int getNumberOfBuilds()
055        {
056            return projectBuilds.size();
057        }
058    
059        /**
060         * Gets all the builds that have no reactor-dependencies
061         *
062         * @return A list of all the initial builds
063         */
064    
065        public List<MavenProject> getRootSchedulableBuilds()
066        {
067            List<MavenProject> result = new ArrayList<MavenProject>();
068            for ( ProjectSegment projectBuild : projectBuilds )
069            {
070                if ( projectDependencyGraph.getUpstreamProjects( projectBuild.getProject(), false ).size() == 0 )
071                {
072                    result.add( projectBuild.getProject() );
073                }
074            }
075            return result;
076        }
077    
078        /**
079         * Marks the provided project as finished. Returns a list of
080         *
081         * @param mavenProject The project
082         * @return The list of builds that are eligible for starting now that the provided project is done
083         */
084        public List<MavenProject> markAsFinished( MavenProject mavenProject )
085        {
086            finishedProjects.add( mavenProject );
087            return getSchedulableNewProcesses( mavenProject );
088        }
089    
090        private List<MavenProject> getSchedulableNewProcesses( MavenProject finishedProject )
091        {
092            List<MavenProject> result = new ArrayList<MavenProject>();
093            // schedule dependent projects, if all of their requirements are met
094            for ( MavenProject dependentProject : projectDependencyGraph.getDownstreamProjects( finishedProject, false ) )
095            {
096                final List<MavenProject> upstreamProjects =
097                    projectDependencyGraph.getUpstreamProjects( dependentProject, false );
098                if ( finishedProjects.containsAll( upstreamProjects ) )
099                {
100                    result.add( dependentProject );
101                }
102            }
103            return result;
104        }
105    
106        public ProjectBuildList getProjectBuilds()
107        {
108            return projectBuilds;
109        }
110    }