/**
* Copyright 2015 StreamSets Inc.
*
* Licensed under 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.
*/
package com.streamsets.datacollector.runner.preview;
import com.streamsets.datacollector.config.PipelineConfiguration;
import com.streamsets.datacollector.config.StageConfiguration;
import com.streamsets.datacollector.runner.Pipeline;
import com.streamsets.datacollector.runner.PipelineRunner;
import com.streamsets.datacollector.runner.PipelineRuntimeException;
import com.streamsets.datacollector.runner.UserContext;
import com.streamsets.datacollector.stagelibrary.StageLibraryTask;
import com.streamsets.datacollector.util.Configuration;
import com.streamsets.datacollector.util.ContainerError;
import com.streamsets.datacollector.util.ValidationUtil;
import com.streamsets.datacollector.validation.Issues;
import com.streamsets.datacollector.validation.PipelineConfigurationValidator;
import com.streamsets.pipeline.api.StageException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;
import java.util.UUID;
public class PreviewPipelineBuilder {
@SuppressWarnings("unchecked")
private StageConfiguration createPlugStage(List<String> lanes) {
StageConfiguration stageConf = new StageConfiguration(PreviewStageLibraryTask.NAME + UUID.randomUUID().toString(),
PreviewStageLibraryTask.LIBRARY, PreviewStageLibraryTask.NAME,
PreviewStageLibraryTask.VERSION, Collections.EMPTY_LIST,
Collections.EMPTY_MAP, lanes, Collections.EMPTY_LIST,
Collections.EMPTY_LIST);
stageConf.setSystemGenerated();
return stageConf;
}
private final StageLibraryTask stageLib;
private final Configuration configuration;
private final String name;
private final String rev;
private PipelineConfiguration pipelineConf;
private final String endStageInstanceName;
/**
* Constructor
*
* @param stageLib Stage Library Task
* @param name Name of pipeline
* @param pipelineConf Pipeline Configuration
* @param endStageInstanceName Optional parameter, if passed builder will generate a partial pipeline and
* endStage is exclusive
*/
public PreviewPipelineBuilder(StageLibraryTask stageLib, Configuration configuration, String name, String rev,
PipelineConfiguration pipelineConf, String endStageInstanceName) {
this.stageLib = new PreviewStageLibraryTask(stageLib);
this.configuration = configuration;
this.name = name;
this.rev = rev;
this.pipelineConf = pipelineConf;
this.endStageInstanceName = endStageInstanceName;
}
public PreviewPipeline build(UserContext userContext, PipelineRunner runner) throws PipelineRuntimeException, StageException {
if(endStageInstanceName != null && endStageInstanceName.trim().length() > 0) {
List<StageConfiguration> stages = new ArrayList<>();
Set<String> allowedOutputLanes = new HashSet<>();
for(StageConfiguration stageConfiguration: pipelineConf.getStages()) {
if (stageConfiguration.getInstanceName().equals(endStageInstanceName)) {
allowedOutputLanes.addAll(stageConfiguration.getInputLanes());
break;
}
stages.add(stageConfiguration);
}
ListIterator li = stages.listIterator(stages.size());
while(li.hasPrevious()) {
StageConfiguration stageConfiguration = (StageConfiguration) li.previous();
boolean contains = false;
List<String> outputLanes = stageConfiguration.getOutputLanes();
for(String outputLane :outputLanes) {
if(allowedOutputLanes.contains(outputLane)){
contains = true;
break;
}
}
if(contains) {
allowedOutputLanes.addAll(stageConfiguration.getInputLanes());
} else {
li.remove();
}
}
pipelineConf.setStages(stages);
}
PipelineConfigurationValidator validator = new PipelineConfigurationValidator(stageLib, name, pipelineConf);
pipelineConf = validator.validate();
if (!validator.getIssues().hasIssues() || validator.canPreview()) {
List<String> openLanes = validator.getOpenLanes();
if (!openLanes.isEmpty()) {
pipelineConf.getStages().add(createPlugStage(openLanes));
}
} else {
throw new PipelineRuntimeException(ContainerError.CONTAINER_0154, ValidationUtil.getFirstIssueAsString(name,
validator.getIssues()));
}
Pipeline.Builder builder = new Pipeline.Builder(
stageLib,
configuration,
name + ":preview",
name,
rev,
userContext,
pipelineConf
);
Pipeline pipeline = builder.build(runner);
if (pipeline != null) {
return new PreviewPipeline(name, rev, pipeline, validator.getIssues());
} else {
Issues issues = new Issues(builder.getIssues());
throw new PipelineRuntimeException(issues);
}
}
}