content: /*******************************************************************************
   * Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
   * All rights reserved. This program and the accompanying materials
   * are made available under the terms of the Eclipse Public License v1.0
   * which accompanies this distribution, and is available at
   * http://www.eclipse.org/legal/epl-v10.html
   *
   * Contributors:
   *    Marc R. Hoffmann - initial API and implementation
   *    
   *******************************************************************************/
  package org.jacoco.core.analysis;
  
  import java.util.*;
  
  import org.jacoco.core.internal.analysis.BundleCoverageImpl;
  import org.jacoco.core.internal.analysis.SourceFileCoverageImpl;
  import org.jacoco.core.internal.diff.ClassInfo;
  import org.jacoco.core.internal.diff.CodeDiff;
  
  /**
   * Builder for hierarchical {@link ICoverageNode} structures from single
   * {@link IClassCoverage} nodes. The nodes are feed into the builder through its
   * {@link ICoverageVisitor} interface. Afterwards the aggregated data can be
   * obtained with {@link #getClasses()}, {@link #getSourceFiles()} or
   * {@link #getBundle(String)} in the following hierarchy:
   * 
   * <pre>
   * {@link IBundleCoverage}
   * +-- {@link IPackageCoverage}*
   *     +-- {@link IClassCoverage}*
   *     +-- {@link ISourceFileCoverage}*
   * </pre>
   */
  public class CoverageBuilder implements ICoverageVisitor {
  
  	private final Map<String, IClassCoverage> classes;
  
  	private final Map<String, ISourceFileCoverage> sourcefiles;
  
  	public static List<ClassInfo> classInfos;
  
  	/**
  	 * Create a new builder.
  	 * 
  	 */
  	public CoverageBuilder() {
  		this.classes = new HashMap<String, IClassCoverage>();
  		this.sourcefiles = new HashMap<String, ISourceFileCoverage>();
  		classInfos = null;
  	}
  
  	/**
  	 * compare new  branch withe master branch
  	 * @param gitPath local gitPath
  	 * @param branchName new test branch name
  	 */
  	public CoverageBuilder(String gitPath, String branchName) {
  		this.classes = new HashMap<String, IClassCoverage>();
  		this.sourcefiles = new HashMap<String, ISourceFileCoverage>();
  		classInfos = CodeDiff.diffBranchToBranch(gitPath, branchName,CodeDiff.MASTER);
  	}
  
  	/**
  	 * compare new  newBranchName withe oldBranchName
  	 * @param gitPath local gitPath
  	 * @param newBranchName newBranchName
  	 * @param oldBranchName oldBranchName
  	 */
  	public CoverageBuilder(String gitPath, String newBranchName, String oldBranchName) {
  		this.classes = new HashMap<String, IClassCoverage>();
  		this.sourcefiles = new HashMap<String, ISourceFileCoverage>();
  		classInfos = CodeDiff.diffBranchToBranch(gitPath, newBranchName, oldBranchName);
  	}
  
  	/**
  	 * compare new Tag withe old Tag
  	 * @param gitPath local gitPath
  	 * @param branchName develop branchName
  	 * @param newTag new Tag
  	 * @param oldTag old Tag
  	 */
  	public CoverageBuilder(String gitPath, String branchName, String newTag, String oldTag) {
  		this.classes = new HashMap<String, IClassCoverage>();
  		this.sourcefiles = new HashMap<String, ISourceFileCoverage>();
  		classInfos = CodeDiff.diffTagToTag(gitPath,branchName, newTag, oldTag);
  	}
  
  	/**
  	 * Returns all class nodes currently contained in this builder.
  	 * 
  	 * @return all class nodes
  	 */
  	public Collection<IClassCoverage> getClasses() {
  		return Collections.unmodifiableCollection(classes.values());
  	}
  
  	/**
  	 * Returns all source file nodes currently contained in this builder.
  	 * 
  	 * @return all source file nodes
  	 */
  	public Collection<ISourceFileCoverage> getSourceFiles() {
  		return Collections.unmodifiableCollection(sourcefiles.values());
  	}
  
  	/**
  	 * Creates a bundle from all nodes currently contained in this bundle.
  	 * 
  	 * @param name
  	 *            Name of the bundle
  	 * @return bundle containing all classes and source files
  	 */
  	public IBundleCoverage getBundle(final String name) {
  		return new BundleCoverageImpl(name, classes.values(),
  				sourcefiles.values());
  	}
  
  	/**
  	 * Returns all classes for which execution data does not match.
  	 * 
  	 * @see IClassCoverage#isNoMatch()
  	 * @return collection of classes with non-matching execution data
  	 */
  	public Collection<IClassCoverage> getNoMatchClasses() {
  		final Collection<IClassCoverage> result = new ArrayList<IClassCoverage>();
  		for (final IClassCoverage c : classes.values()) {
  			if (c.isNoMatch()) {
  				result.add(c);
  			}
  		}
  		return result;
  	}
  
  	// === ICoverageVisitor ===
  
  	public void visitCoverage(final IClassCoverage coverage) {
  		final String name = coverage.getName();
  		final IClassCoverage dup = classes.put(name, coverage);
  		if (dup != null) {
  			if (dup.getId() != coverage.getId()) {
  				throw new IllegalStateException(
  						"Can't add different class with same name: " + name);
  			}
  		} else {
  			final String source = coverage.getSourceFileName();
  			if (source != null) {
  				final SourceFileCoverageImpl sourceFile = getSourceFile(source,
  						coverage.getPackageName());
  				sourceFile.increment(coverage);
  			}
  		}
  	}
  
  	private SourceFileCoverageImpl getSourceFile(final String filename,
  			final String packagename) {
  		final String key = packagename + '/' + filename;
  		SourceFileCoverageImpl sourcefile = (SourceFileCoverageImpl) sourcefiles
  				.get(key);
  		if (sourcefile == null) {
  			sourcefile = new SourceFileCoverageImpl(filename, packagename);
  			sourcefiles.put(key, sourcefile);
  		}
  		return sourcefile;
  	}
  
  }
  