001package 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
022import org.apache.maven.execution.ProjectDependencyGraph;
023import org.apache.maven.project.MavenProject;
024
025import java.util.ArrayList;
026import java.util.HashSet;
027import 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 */
037public 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}