/*
* Copyright 2017 Red Hat, Inc. and/or its affiliates.
*
* 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.
*/
package org.kie.workbench.common.services.backend.builder.ala;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.inject.Named;
import org.guvnor.ala.pipeline.Input;
import org.guvnor.ala.pipeline.Pipeline;
import org.guvnor.ala.pipeline.execution.PipelineExecutor;
import org.guvnor.ala.registry.PipelineRegistry;
import org.guvnor.common.services.project.model.Project;
import org.uberfire.backend.vfs.Path;
import org.uberfire.workbench.events.ResourceChange;
/**
* Helper class for invoking the build system pipeline.
*/
@ApplicationScoped
public class BuildPipelineInvoker {
private PipelineExecutor executor;
private PipelineRegistry pipelineRegistry;
public BuildPipelineInvoker( ) {
//Empty constructor for Weld proxying
}
@Inject
public BuildPipelineInvoker( @Named("buildPipelineExecutor") final PipelineExecutor executor,
final PipelineRegistry pipelineRegistry ) {
this.executor = executor;
this.pipelineRegistry = pipelineRegistry;
}
/**
* Invokes the local build pipeline.
*
* @param buildRequest the buildRequest configures the build to perform.
*
* @param consumer a consumer for getting the pipeline output.
*/
public void invokeLocalBuildPipeLine( LocalBuildRequest buildRequest,
Consumer< LocalBinaryConfig > consumer ) {
Pipeline pipe = pipelineRegistry.getPipelineByName( BuildPipelineInitializer.LOCAL_BUILD_PIPELINE );
Input input = new Input( ) {
{
put( LocalSourceConfig.ROOT_PATH, buildRequest.getProject( ).getRootPath( ).toURI( ) );
put( LocalBuildConfig.BUILD_TYPE, buildRequest.getBuildType( ).name( ) );
if ( buildRequest.isSingleResource( ) ) {
put( LocalBuildConfig.RESOURCE, encodePath( buildRequest.getResource( ) ) );
} else {
addResourceChanges( this, buildRequest.getResourceChanges( ) );
}
if ( buildRequest.getDeploymentType( ) != null ) {
put( LocalBuildConfig.DEPLOYMENT_TYPE, buildRequest.getDeploymentType( ).name( ) );
put( LocalBuildConfig.SUPPRESS_HANDLERS, Boolean.toString( buildRequest.isSuppressHandlers( ) ) );
}
}
};
executor.execute( input, pipe, consumer );
}
/**
* Invokes the local build pipeline.
*
* @param buildRequest the buildRequest configures the build to perform.
*
* @return the pipeline output.
*/
public LocalBinaryConfig invokeLocalBuildPipeLine( LocalBuildRequest buildRequest ) {
final LocalBinaryConfig[] result = new LocalBinaryConfig[ 1 ];
invokeLocalBuildPipeLine( buildRequest, localBinaryConfig -> {
result[ 0 ] = localBinaryConfig;
} );
return result[ 0 ];
}
private void addResourceChanges( Input input, Map< Path, Collection< ResourceChange > > resourceChanges ) {
resourceChanges.entrySet( ).forEach( entry -> {
input.put( encodeResourceChangePath( entry.getKey( ) ), encodeResourceChanges( entry.getValue( ) ) );
} );
}
private String encodePath( Path path ) {
return path.toURI( );
}
private String encodeResourceChangePath( Path path ) {
return LocalBuildConfig.RESOURCE_CHANGE + encodePath( path );
}
private String encodeResourceChanges( Collection< ResourceChange > resourceChanges ) {
return resourceChanges
.stream( )
.map( change -> change.getType( ).name( ) )
.collect( Collectors.joining( "," ) );
}
/**
* This class models the configuration parameters for a project build execution.
*/
public static class LocalBuildRequest {
private Project project;
private LocalBuildConfig.BuildType buildType = LocalBuildConfig.BuildType.FULL_BUILD;
private Path resource;
private Map< Path, Collection< ResourceChange > > resourceChanges = new HashMap<>( );
private LocalBuildConfig.DeploymentType deploymentType;
private boolean suppressHandlers;
private LocalBuildRequest( Project project ) {
this.project = project;
this.buildType = LocalBuildConfig.BuildType.FULL_BUILD;
}
private LocalBuildRequest( Project project, LocalBuildConfig.BuildType buildType, Path resource ) {
this.project = project;
this.buildType = buildType;
this.resource = resource;
}
private LocalBuildRequest( Project project, Map< Path, Collection< ResourceChange > > resourceChanges ) {
this.project = project;
this.resourceChanges = resourceChanges;
this.buildType = LocalBuildConfig.BuildType.INCREMENTAL_BATCH_CHANGES;
}
private LocalBuildRequest( Project project, LocalBuildConfig.DeploymentType deploymentType, boolean suppressHandlers ) {
this.project = project;
this.deploymentType = deploymentType;
this.suppressHandlers = suppressHandlers;
this.buildType = LocalBuildConfig.BuildType.FULL_BUILD_AND_DEPLOY;
}
/**
* Creates a full build request for the given project.
*
* @param project the project to build.
*
* @return a properly constructed build request.
*/
public static final LocalBuildRequest newFullBuildRequest( Project project ) {
return new LocalBuildRequest( project );
}
/**
* Creates a full build request for the given project, and additionally performs the deployment for the build
* in current m2repository.
*
* @param project the project to build.
*
* @param deploymentType the type of deployment to perform.
*
* @param suppressHandlers true if PostBuildHandlers invocation should be canceled, false in any other case.
*
* @return a properly constructed build request.
*/
public static final LocalBuildRequest newFullBuildAndDeployRequest( Project project, LocalBuildConfig.DeploymentType deploymentType, boolean suppressHandlers ) {
return new LocalBuildRequest( project, deploymentType, suppressHandlers );
}
/**
* Creates an incremental build request for the given project.
*
* @param project the project to build incrementally.
*
* @param buildType the incremental build type to perform.
*
* @param resource the resource that was added, updated or deleted.
*
* @return a properly constructed build request.
*/
public static final LocalBuildRequest newIncrementalBuildRequest( Project project, LocalBuildConfig.BuildType buildType, Path resource ) {
return new LocalBuildRequest( project, buildType, resource );
}
/**
* Creates an incremental build request for the given project.
*
* @param project the project to build incrementally.
*
* @param resourceChanges the set of changes. This incremental build type supports changes for multiple resources.
*
* @return a properly constructed build request.
*/
public static final LocalBuildRequest newIncrementalBuildRequest( Project project, Map< Path, Collection< ResourceChange > > resourceChanges ) {
return new LocalBuildRequest( project, resourceChanges );
}
public LocalBuildConfig.BuildType getBuildType( ) {
return buildType;
}
public Project getProject( ) {
return project;
}
public Path getResource( ) {
return resource;
}
public Map< Path, Collection< ResourceChange > > getResourceChanges( ) {
return resourceChanges;
}
public LocalBuildConfig.DeploymentType getDeploymentType( ) {
return deploymentType;
}
public boolean isSuppressHandlers( ) {
return suppressHandlers;
}
public boolean isSingleResource( ) {
return resource != null;
}
@Override
public boolean equals( Object o ) {
if ( this == o ) return true;
if ( o == null || getClass( ) != o.getClass( ) ) return false;
LocalBuildRequest that = ( LocalBuildRequest ) o;
if ( suppressHandlers != that.suppressHandlers ) return false;
if ( project != null ? !project.equals( that.project ) : that.project != null ) return false;
if ( buildType != that.buildType ) return false;
if ( resource != null ? !resource.equals( that.resource ) : that.resource != null ) return false;
if ( resourceChanges != null ? !resourceChanges.equals( that.resourceChanges ) : that.resourceChanges != null )
return false;
return deploymentType == that.deploymentType;
}
@Override
public int hashCode( ) {
int result = project != null ? project.hashCode( ) : 0;
result = 31 * result + ( buildType != null ? buildType.hashCode( ) : 0 );
result = 31 * result + ( resource != null ? resource.hashCode( ) : 0 );
result = 31 * result + ( resourceChanges != null ? resourceChanges.hashCode( ) : 0 );
result = 31 * result + ( deploymentType != null ? deploymentType.hashCode( ) : 0 );
result = 31 * result + ( suppressHandlers ? 1 : 0 );
return result;
}
}
}