com.thoughtworks.go.server.service.dd.reporting.ReportingDependencyFanInNode.java Source code

Java tutorial

Introduction

Here is the source code for com.thoughtworks.go.server.service.dd.reporting.ReportingDependencyFanInNode.java

Source

/*
 * Copyright 2019 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.service.dd.reporting;

import com.thoughtworks.go.config.CaseInsensitiveString;
import com.thoughtworks.go.config.materials.dependency.DependencyMaterialConfig;
import com.thoughtworks.go.domain.PipelineTimelineEntry;
import com.thoughtworks.go.domain.StageIdentifier;
import com.thoughtworks.go.domain.materials.MaterialConfig;
import com.thoughtworks.go.domain.materials.dependency.DependencyMaterialRevision;
import com.thoughtworks.go.server.domain.PipelineTimeline;
import com.thoughtworks.go.util.Pair;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.IterableUtils;

import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;

public class ReportingDependencyFanInNode extends ReportingFanInNode {
    private static List<Class<? extends MaterialConfig>> DEPENDENCY_NODE_TYPES = new ArrayList<>();
    public Set<ReportingFanInNode> children = new HashSet<>();
    StageIdentifier currentRevision;
    private int totalInstanceCount = Integer.MAX_VALUE;
    private int currentCount;
    private Map<StageIdentifier, Set<ReportingFaninScmMaterial>> stageIdentifierScmMaterial = new LinkedHashMap<>();

    ReportingDependencyFanInNode(MaterialConfig material) {
        super(material);
        for (Class<? extends MaterialConfig> clazz : DEPENDENCY_NODE_TYPES) {
            if (clazz.isAssignableFrom(material.getClass())) {
                return;
            }
        }
        throw new RuntimeException("Not a valid root node material type");
    }

    public void populateRevisions(ReportingFanInGraphContext context) {
        initialize(context);
        context.out.println("Total Instances: " + totalInstanceCount);
        context.out.println();
        fillNextRevisions(context);
    }

    private void setCurrentRevision() {
        currentRevision = stageIdentifierScmMaterial.keySet().toArray(new StageIdentifier[0])[0];
    }

    public void initialize(ReportingFanInGraphContext context) {
        totalInstanceCount = context.pipelineTimeline
                .instanceCount(((DependencyMaterialConfig) materialConfig).getPipelineName());
    }

    private void fillNextRevisions(ReportingFanInGraphContext context) {
        if (!hasMoreInstances()) {
            return;
        }

        final Pair<StageIdentifier, List<ReportingFaninScmMaterial>> sIdScmPair = getRevisionNthFor(1, context);

        validateIfRevisionMatchesTheCurrentConfig(context, sIdScmPair);

        if (!validateAllScmRevisionsAreSameWithinAFingerprint(sIdScmPair)) {
            context.out.println("Latest Revision Is Inconsistent ");
        }

        context.out.println();
    }

    private void printCurrentAndOldSCMs(ReportingFanInGraphContext context, Set<MaterialConfig> currentScmMaterials,
            List<ReportingFaninScmMaterial> scmMaterials,
            Pair<StageIdentifier, List<ReportingFaninScmMaterial>> stageIdentifierScmPair) {
        context.out.println();
        context.out.println("----");
        context.out.println("SCM Materials in config:");
        context.out.println(currentScmMaterials);
        final Set<MaterialConfig> scmMaterialsInRev = new HashSet<>();
        for (ReportingFaninScmMaterial scmMaterial : scmMaterials) {
            final MaterialConfig scm = context.fingerprintScmMaterialMap.get(scmMaterial.fingerprint);
            scmMaterialsInRev.add(scm);
        }
        context.out.println("----");
        context.out.println("SCM Materials in Latest Revision:");
        context.out.println(scmMaterialsInRev);
        context.out.println("----");
        context.out.println("Latest Revision of Material:");
        context.out.println(stageIdentifierScmPair.first());
        context.out.println("----");
    }

    private void validateIfRevisionMatchesTheCurrentConfig(ReportingFanInGraphContext context,
            Pair<StageIdentifier, List<ReportingFaninScmMaterial>> stageIdentifierScmPair) {
        if (stageIdentifierScmPair == null) {
            return;
        }

        final Set<MaterialConfig> currentScmMaterials = context.pipelineScmDepMap.get(materialConfig);
        final List<ReportingFaninScmMaterial> scmMaterials = stageIdentifierScmPair.last();

        printCurrentAndOldSCMs(context, currentScmMaterials, scmMaterials, stageIdentifierScmPair);

        final List<ReportingFaninScmMaterial> setOfRevisions = new ArrayList<>();
        for (final ReportingFaninScmMaterial scmMaterial : scmMaterials) {
            ReportingFaninScmMaterial mat = IterableUtils.find(setOfRevisions, mat1 -> {
                if (mat1 == null) {
                    return false;
                }
                return scmMaterial.fingerprint.equals(mat1.fingerprint)
                        && scmMaterial.revision.equals(mat1.revision);
            });
            if (mat == null) {
                setOfRevisions.add(scmMaterial);
            }
        }

        context.out.println("SCM Revisions of Latest Revision of Material:");
        context.out.println(setOfRevisions);
    }

    private Pair<StageIdentifier, List<ReportingFaninScmMaterial>> getRevisionNthFor(int n,
            ReportingFanInGraphContext context) {
        List<ReportingFaninScmMaterial> scmMaterials = new ArrayList<>();
        PipelineTimeline pipelineTimeline = context.pipelineTimeline;
        Queue<PipelineTimelineEntry.Revision> revisionQueue = new ConcurrentLinkedQueue<>();
        DependencyMaterialConfig dependencyMaterial = (DependencyMaterialConfig) materialConfig;
        PipelineTimelineEntry entry = pipelineTimeline.instanceFor(dependencyMaterial.getPipelineName(),
                totalInstanceCount - n);

        StageIdentifier dependentStageIdentifier = dependentStageIdentifier(context, entry,
                CaseInsensitiveString.str(dependencyMaterial.getStageName()));
        if (!StageIdentifier.NULL.equals(dependentStageIdentifier)) {
            addToRevisionQueue(entry, revisionQueue, scmMaterials, context);
        } else {
            return null;
        }
        while (!revisionQueue.isEmpty()) {
            PipelineTimelineEntry.Revision revision = revisionQueue.poll();
            DependencyMaterialRevision dmr = DependencyMaterialRevision.create(revision.revision, null);
            PipelineTimelineEntry pte = pipelineTimeline
                    .getEntryFor(new CaseInsensitiveString(dmr.getPipelineName()), dmr.getPipelineCounter());
            addToRevisionQueue(pte, revisionQueue, scmMaterials, context);
        }

        return new Pair<>(dependentStageIdentifier, scmMaterials);
    }

    private boolean validateAllScmRevisionsAreSameWithinAFingerprint(
            Pair<StageIdentifier, List<ReportingFaninScmMaterial>> pIdScmPair) {
        if (pIdScmPair == null) {
            return false;
        }
        List<ReportingFaninScmMaterial> scmMaterialList = pIdScmPair.last();
        for (final ReportingFaninScmMaterial scmMaterial : scmMaterialList) {
            Collection<ReportingFaninScmMaterial> scmMaterialOfSameFingerprint = CollectionUtils
                    .select(scmMaterialList, scmMaterial::equals);

            for (ReportingFaninScmMaterial faninScmMaterial : scmMaterialOfSameFingerprint) {
                if (!faninScmMaterial.revision.equals(scmMaterial.revision)) {
                    return false;
                }
            }
        }
        return true;
    }

    private StageIdentifier dependentStageIdentifier(ReportingFanInGraphContext context,
            PipelineTimelineEntry entry, final String stageName) {
        return context.pipelineDao.latestPassedStageIdentifier(entry.getId(), stageName);
    }

    private void addToRevisionQueue(PipelineTimelineEntry entry,
            Queue<PipelineTimelineEntry.Revision> revisionQueue, List<ReportingFaninScmMaterial> scmMaterials,
            ReportingFanInGraphContext context) {
        printPipelineTimelineEntry(entry, context);

        for (Map.Entry<String, List<PipelineTimelineEntry.Revision>> revisionList : entry.revisions().entrySet()) {
            String fingerprint = revisionList.getKey();
            PipelineTimelineEntry.Revision revision = revisionList.getValue().get(0);
            if (isScmMaterial(fingerprint, context)) {
                scmMaterials.add(new ReportingFaninScmMaterial(fingerprint, revision));
                continue;
            }

            if (isDependencyMaterial(fingerprint, context)) {
                revisionQueue.add(revision);
            }
        }
    }

    private void printPipelineTimelineEntry(PipelineTimelineEntry entry, ReportingFanInGraphContext context) {
        context.out.println(
                "Pipeline-Timeline-Entry: Id: " + entry.getId() + ", Pipeline-Name: " + entry.getPipelineName()
                        + ", Counter: " + entry.getCounter() + ", Natural-Order: " + entry.naturalOrder());
        Iterator it = entry.revisions().entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<String, List<PipelineTimelineEntry.Revision>> pairs = (Map.Entry) it.next();
            context.out.println("Flyweight: " + pairs.getKey() + " - " + pairs.getValue());
        }
        context.out.println("***");
    }

    private boolean isDependencyMaterial(String fingerprint, ReportingFanInGraphContext context) {
        return context.fingerprintDepMaterialMap.containsKey(fingerprint);
    }

    private boolean isScmMaterial(String fingerprint, ReportingFanInGraphContext context) {
        return context.fingerprintScmMaterialMap.containsKey(fingerprint);
    }

    private boolean hasMoreInstances() {
        return currentCount < totalInstanceCount;
    }

    enum RevisionAlteration {
        NOT_APPLICABLE, SAME_AS_CURRENT_REVISION, ALTERED_TO_CORRECT_REVISION, ALL_OPTIONS_EXHAUSTED, NEED_MORE_REVISIONS
    }

    static {
        DEPENDENCY_NODE_TYPES.add(DependencyMaterialConfig.class);
    }
}