/* * Copyright 2017 ThoughtWorks, Inc. * * 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 com.thoughtworks.go.server.presentation.models; import com.thoughtworks.go.config.PipelineConfig; import com.thoughtworks.go.domain.BaseCollection; import com.thoughtworks.go.domain.CommentRenderer; import com.thoughtworks.go.domain.PipelinePauseInfo; import com.thoughtworks.go.domain.StageIdentifier; import com.thoughtworks.go.presentation.pipelinehistory.PipelineInstanceModel; import com.thoughtworks.go.presentation.pipelinehistory.PipelineInstanceModels; import com.thoughtworks.go.presentation.pipelinehistory.StageInstanceModel; import com.thoughtworks.go.presentation.pipelinehistory.StageInstanceModels; import com.thoughtworks.go.server.presentation.PipelineHistoryGroupingUtil; import com.thoughtworks.go.server.util.Pagination; import com.thoughtworks.go.util.TimeConverter; import com.thoughtworks.go.util.json.JsonAware; import java.util.*; import static com.thoughtworks.go.config.CaseInsensitiveString.str; import static com.thoughtworks.go.util.UrlUtil.encodeInUtf8; import static java.lang.String.valueOf; public class PipelineHistoryJsonPresentationModel implements JsonAware { private final PipelinePauseInfo pipelinePauseInfo; private final PipelineConfig pipelineConfig; private final Pagination pagination; private TimeConverter timeConverter = new TimeConverter(); private boolean canForce; private final boolean hasForceBuildCause; private PipelineHistoryGroups pipelineHistoryGroups; private final boolean hasBuildCauseInBuffer; private final boolean canPause; public PipelineHistoryJsonPresentationModel(PipelinePauseInfo pipelinePauseInfo, PipelineInstanceModels pipelineHistory, PipelineConfig pipelineConfig, Pagination pagination, boolean canForce, boolean hasForcedBuildCause, boolean hasBuildCauseInBuffer, boolean canPause) { this(pipelinePauseInfo, new PipelineHistoryGroupingUtil().createGroups(pipelineHistory), pipelineConfig, pagination, canForce, hasForcedBuildCause, hasBuildCauseInBuffer, canPause); } PipelineHistoryJsonPresentationModel(PipelinePauseInfo pipelinePauseInfo, PipelineHistoryGroups pipelineHistoryGroups, PipelineConfig pipelineConfig, Pagination pagination, boolean canForce, boolean hasForceBuildCause, boolean hasBuildCauseInBuffer, boolean canPause) { this.pipelinePauseInfo = pipelinePauseInfo; this.pipelineHistoryGroups = pipelineHistoryGroups; this.pipelineConfig = pipelineConfig; this.pagination = pagination; this.canForce = canForce; this.hasForceBuildCause = hasForceBuildCause; this.hasBuildCauseInBuffer = hasBuildCauseInBuffer; this.canPause = canPause; createGroupForCurrentConfigIfItHasChanged(new HashMap<>()); } private void createGroupForCurrentConfigIfItHasChanged(Map<String, StageIdentifier> latest) { if (pipelineHistoryGroups.isEmpty()) { if (hasBuildCauseInBuffer || pipelineConfig.isFirstStageManualApproval()) { createGroupForCurrentConfig(latest); } return; } if (hasPipelineConfigChanged()) { createGroupForCurrentConfig(latest); } } private boolean hasPipelineConfigChanged() { return !pipelineHistoryGroups.first().match(pipelineConfig); } private void createGroupForCurrentConfig(Map<String, StageIdentifier> latest) { PipelineInstanceGroupModel group = new PipelineInstanceGroupModel( new StageConfigurationModels(pipelineConfig, latest)); pipelineHistoryGroups.add(0, group); } public Map toJson() { Map<String, Object> json = new LinkedHashMap<>(); String pipelineName = str(pipelineConfig.name()); json.put("pipelineName", pipelineName); json.put("paused", valueOf(pipelinePauseInfo.isPaused())); json.put("pauseCause", pipelinePauseInfo.getPauseCause()); json.put("pauseBy", pipelinePauseInfo.getPauseBy()); json.put("canForce", valueOf(canForce)); json.put("nextLabel", ""); json.put("groups", groupAsJson()); json.put("forcedBuild", valueOf(hasForceBuildCause)); json.put("showForceBuildButton", valueOf(showForceBuildButton())); json.put("canPause", valueOf(canPause)); json.putAll(pagination.toJsonMap()); return json; } private boolean showForceBuildButton() { return hasBuildCauseInBuffer || pipelineConfig.isFirstStageManualApproval(); } private List groupAsJson() { List jsonList = new ArrayList(); for (PipelineInstanceGroupModel group : pipelineHistoryGroups) { Map<String, Object> jsonMap = new LinkedHashMap<>(); Map configJson = configAsJson(group.getStages()); jsonMap.put("config", configJson); jsonMap.put("history", historyAsJson(group.getPipelineInstances())); jsonList.add(jsonMap); } return jsonList; } private Map configAsJson(Iterable<StageConfigurationModel> stages) { List jsonList = new ArrayList(); for (StageConfigurationModel stageInfo : stages) { Map<String, Object> jsonMap = new LinkedHashMap<>(); jsonMap.put("name", stageInfo.getName()); jsonMap.put("isAutoApproved", valueOf(stageInfo.isAutoApproved())); jsonList.add(jsonMap); } Map<String, Object> jsonMap = new LinkedHashMap<>(); jsonMap.put("stages", jsonList); return jsonMap; } private List historyAsJson(BaseCollection<PipelineInstanceModel> pipelineHistory) { List json = new ArrayList(); for (PipelineInstanceModel item : pipelineHistory) { Map<String, Object> jsonMap = new LinkedHashMap<>(); jsonMap.put("pipelineId", item.getId()); jsonMap.put("label", item.getLabel()); jsonMap.put("counterOrLabel", item.getPipelineIdentifier().instanceIdentifier()); jsonMap.put("scheduled_date", timeConverter.getHumanReadableStringWithTimeZone(item.getScheduledDate())); jsonMap.put("scheduled_timestamp", item.getScheduledDate() != null ? item.getScheduledDate().getTime() : null); jsonMap.put("buildCauseBy", item.getApprovedByForDisplay()); jsonMap.put("modification_date", getModificationDate(item)); jsonMap.put("materialRevisions", materialRevisionsJson(item)); jsonMap.put("stages", stageHistoryAsJson(item, item.getStageHistory())); jsonMap.put("revision", item.getRevisionOfLatestModification()); jsonMap.put("comment", item.getComment()); json.add(jsonMap); } return json; } private List materialRevisionsJson(PipelineInstanceModel item) { CommentRenderer commentRenderer = pipelineConfig.getCommentRenderer(); MaterialRevisionsJsonBuilder jsonVisitor = new MaterialRevisionsJsonBuilder(commentRenderer); jsonVisitor.setIncludeModifiedFiles(false); item.getBuildCause().getMaterialRevisions().accept(jsonVisitor); return jsonVisitor.json(); } // TODO #1234 - should not get latest modified date private TimeConverter.ConvertedTime getModificationDate(PipelineInstanceModel item) { Date mostRecentModificationDate = item.getBuildCause().getMaterialRevisions().getDateOfLatestModification(); return timeConverter.getConvertedTime(mostRecentModificationDate); } private List stageHistoryAsJson(PipelineInstanceModel pipelineInstanceModel, StageInstanceModels stageHistory) { List json = new ArrayList(); for (StageInstanceModel stageHistoryItem : stageHistory) { Map<String, Object> jsonMap = new LinkedHashMap<>(); jsonMap.put("stageName", stageHistoryItem.getName()); jsonMap.put("stageId", stageHistoryItem.getId()); jsonMap.put("stageStatus", stageHistoryItem.getState().toString()); StageIdentifier stageIdentifier = new StageIdentifier(pipelineInstanceModel.getPipelineIdentifier(), stageHistoryItem.getName(), stageHistoryItem.getCounter()); jsonMap.put("stageLocator", encodeInUtf8(stageIdentifier.stageLocator())); jsonMap.put("getCanRun", Boolean.toString(stageHistoryItem.getCanRun())); jsonMap.put("getCanCancel", Boolean.toString(stageHistoryItem.getCanCancel())); jsonMap.put("scheduled", Boolean.toString(stageHistoryItem.isScheduled())); jsonMap.put("stageCounter", stageHistoryItem.getCounter()); handleApproval(stageHistoryItem, jsonMap); json.add(jsonMap); } return json; } private void handleApproval(StageInstanceModel stageHistoryItem, Map jsonMap) { if (stageHistoryItem.needsApproval() && !pipelinePauseInfo.isPaused()) { jsonMap.put("needsApproval", String.valueOf(true)); } else if (stageHistoryItem.getApprovedBy() != null) { jsonMap.put("approvedBy", stageHistoryItem.getApprovedBy()); } } }