// Path: src/main/java/com/github/eostermueller/heapspank/leakyspank/LeakySpankContext.java
// public class LeakResult {
// 	private long timestamp;
// 	LeakResult() {
// 		this.timestamp = System.currentTimeMillis();
// 	}
// 	public JMapHistoLine line = null;
// 	public int countRunsPresent = 0;
// 	public int countRunsWithLeakierRank = 0;
// 	public int countRunsWithBytesIncrease = 0;
// 	public int countRunsWithInstanceCountIncrease = 0;
// 		
// 	/**
// 	 * The percentage of 'runs' that the bytes increase from the previous run.
// 	 * @return a double between 0 and 1.  Multiply the result by to get a portion of 100%.
// 	 */
// 	public double getPercentageOfRunsWithUpwardByteTrend() {
// 		double rc = 0;
// 			
// 		double totalRunCount = LeakySpankContext.this.getCurrentRunCount() -1;
// 		if (this.countRunsWithBytesIncrease == 0 || totalRunCount == 0) // avoid divide by 0 problems.
// 			rc = 0;
// 		else
// 			rc = this.countRunsWithBytesIncrease / totalRunCount;
// 			
// 		return rc;
// 	}
// 	/**
// 	 * Higher score means more likely a leak
// 	 * @return
// 	 */
// 	int getLeakScore() {
// 		return this.countRunsPresent+this.countRunsWithLeakierRank+this.countRunsWithBytesIncrease+this.countRunsWithInstanceCountIncrease;
// 	}
// 	public String humanReadable() {
// 		StringBuilder sb = new StringBuilder();
// 		 sb.append("Class=" + line.className + "\n");
// 		 sb.append("\ncountRunsPresent=" + this.countRunsPresent + "\n");
// 		 sb.append("countRunsWithRankIncrease=" + this.countRunsWithLeakierRank + "\n");
// 		 sb.append("countRunsWithBytesIncrease=" + this.countRunsWithBytesIncrease + "\n");
// 		 sb.append("countRunsWithInstanceCountIncrease=" + this.countRunsWithInstanceCountIncrease + "\n");
// 		 return sb.toString();
// 	}
// 	/**
// 	 * update values in 'this' with values from the given LeakResult
// 	 * @param oneToAdd
// 	 */
// 	public void update(LeakResult oneToAdd) {
// 		/**
// 		 * Add given values to tally values.
// 		 */
// 		this.countRunsPresent+= oneToAdd.countRunsPresent;
// 		this.countRunsWithBytesIncrease += oneToAdd.countRunsWithBytesIncrease;
// 		this.countRunsWithInstanceCountIncrease += oneToAdd.countRunsWithInstanceCountIncrease;
// 		this.countRunsWithLeakierRank += oneToAdd.countRunsWithLeakierRank;
// 			
// 		/**
// 		 * display current values of these, instead of outdated values.
// 		 */
// 		this.line.bytes = oneToAdd.line.bytes;
// 		this.line.num = oneToAdd.line.num;
// 		this.line.instances = oneToAdd.line.instances;
// 	}
// 		
// }


import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Hashtable;
import java.util.List;
import com.github.eostermueller.heapspank.leakyspank.LeakySpankContext.LeakResult;
package com.github.eostermueller.heapspank.leakyspank;



/**
 *  Pojo representing parsed output of one execution of JAVA_HOME/bin/jmap -histo <myPid>
 */
public class Model 
{
	/**
	 * There are a lot of extraneous classes in the jmap -histo output that get in the way of quick troubleshooting.
	 * This list allows us to exclude certain java packages from the output.
	 */
//	public static String[] DEFAULT_STARTSWITH_EXCLUDE_FILTER = {"[B","[C","[I","[Z","[D","[F","[J","[L","[S","java"};
//	public static String[] DEFAULT_STARTSWITH_EXCLUDE_FILTER = {};
	private Hashtable<String,JMapHistoLine> htAllClasses = new Hashtable<String,JMapHistoLine>(); //<JMapHistoLine>
	private List<JMapHistoLine> alAllClasses = new ArrayList<JMapHistoLine>(); //<JMapHistoLine>
	private ClassNameFilter classNameExclusionFilter;
	
	public JMapHistoLine[] getAll() {
		return this.alAllClasses.toArray( new JMapHistoLine[0]);
	}
	
	public Model() {
	}
	public Model(String jMapHistoStdout) {
		this(jMapHistoStdout,null);
	}
// Path: src/main/java/com/github/eostermueller/heapspank/leakyspank/LeakySpankContext.java
// public class LeakResult {
// 	private long timestamp;
// 	LeakResult() {
// 		this.timestamp = System.currentTimeMillis();
// 	}
// 	public JMapHistoLine line = null;
// 	public int countRunsPresent = 0;
// 	public int countRunsWithLeakierRank = 0;
// 	public int countRunsWithBytesIncrease = 0;
// 	public int countRunsWithInstanceCountIncrease = 0;
// 		
// 	/**
// 	 * The percentage of 'runs' that the bytes increase from the previous run.
// 	 * @return a double between 0 and 1.  Multiply the result by to get a portion of 100%.
// 	 */
// 	public double getPercentageOfRunsWithUpwardByteTrend() {
// 		double rc = 0;
// 			
// 		double totalRunCount = LeakySpankContext.this.getCurrentRunCount() -1;
// 		if (this.countRunsWithBytesIncrease == 0 || totalRunCount == 0) // avoid divide by 0 problems.
// 			rc = 0;
// 		else
// 			rc = this.countRunsWithBytesIncrease / totalRunCount;
// 			
// 		return rc;
// 	}
// 	/**
// 	 * Higher score means more likely a leak
// 	 * @return
// 	 */
// 	int getLeakScore() {
// 		return this.countRunsPresent+this.countRunsWithLeakierRank+this.countRunsWithBytesIncrease+this.countRunsWithInstanceCountIncrease;
// 	}
// 	public String humanReadable() {
// 		StringBuilder sb = new StringBuilder();
// 		 sb.append("Class=" + line.className + "\n");
// 		 sb.append("\ncountRunsPresent=" + this.countRunsPresent + "\n");
// 		 sb.append("countRunsWithRankIncrease=" + this.countRunsWithLeakierRank + "\n");
// 		 sb.append("countRunsWithBytesIncrease=" + this.countRunsWithBytesIncrease + "\n");
// 		 sb.append("countRunsWithInstanceCountIncrease=" + this.countRunsWithInstanceCountIncrease + "\n");
// 		 return sb.toString();
// 	}
// 	/**
// 	 * update values in 'this' with values from the given LeakResult
// 	 * @param oneToAdd
// 	 */
// 	public void update(LeakResult oneToAdd) {
// 		/**
// 		 * Add given values to tally values.
// 		 */
// 		this.countRunsPresent+= oneToAdd.countRunsPresent;
// 		this.countRunsWithBytesIncrease += oneToAdd.countRunsWithBytesIncrease;
// 		this.countRunsWithInstanceCountIncrease += oneToAdd.countRunsWithInstanceCountIncrease;
// 		this.countRunsWithLeakierRank += oneToAdd.countRunsWithLeakierRank;
// 			
// 		/**
// 		 * display current values of these, instead of outdated values.
// 		 */
// 		this.line.bytes = oneToAdd.line.bytes;
// 		this.line.num = oneToAdd.line.num;
// 		this.line.instances = oneToAdd.line.instances;
// 	}
// 		
// }


// Path: src/main/java/com/github/eostermueller/heapspank/leakyspank/Model.java
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Hashtable;
import java.util.List;
import com.github.eostermueller.heapspank.leakyspank.LeakySpankContext.LeakResult;

package com.github.eostermueller.heapspank.leakyspank;



/**
 *  Pojo representing parsed output of one execution of JAVA_HOME/bin/jmap -histo <myPid>
 */
public class Model 
{
	/**
	 * There are a lot of extraneous classes in the jmap -histo output that get in the way of quick troubleshooting.
	 * This list allows us to exclude certain java packages from the output.
	 */
//	public static String[] DEFAULT_STARTSWITH_EXCLUDE_FILTER = {"[B","[C","[I","[Z","[D","[F","[J","[L","[S","java"};
//	public static String[] DEFAULT_STARTSWITH_EXCLUDE_FILTER = {};
	private Hashtable<String,JMapHistoLine> htAllClasses = new Hashtable<String,JMapHistoLine>(); //<JMapHistoLine>
	private List<JMapHistoLine> alAllClasses = new ArrayList<JMapHistoLine>(); //<JMapHistoLine>
	private ClassNameFilter classNameExclusionFilter;
	
	public JMapHistoLine[] getAll() {
		return this.alAllClasses.toArray( new JMapHistoLine[0]);
	}
	
	public Model() {
	}
	public Model(String jMapHistoStdout) {
		this(jMapHistoStdout,null);
	}
	public void add(LeakResult[] toAdd) {