/* * Copyright 2012 Kantega AS * * 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 org.kantega.revoc.report; import org.kantega.revoc.registry.BranchPoint; import org.kantega.revoc.registry.CoverageData; import org.kantega.revoc.registry.Registry; import java.util.*; /** * */ public class CoverageFolder { public CoverageData fold(CoverageData coverageData) { Map<String, List<Integer>> sources = new LinkedHashMap<String, List<Integer>>(); Map<String, Integer> topLevels = new TreeMap<String, Integer>(); for(int i = 0; i < coverageData.getClassNames().length; i++) { String sourceName = coverageData.getSourceFiles()[i]; String className = coverageData.getClassNames()[i]; String sourcePath = className.substring(0, className.lastIndexOf("/")+1) + sourceName; String sourceKey = coverageData.getClassLoaders()[i] +"-" + sourcePath; if(!sources.containsKey(sourceKey)) { sources.put(sourceKey, new ArrayList<Integer>()); } if(className.equals(sourcePath.substring(0, sourcePath.length() - ".java".length()))) { topLevels.put(sourceKey, i); } List<Integer> classes = sources.get(sourceKey); classes.add(i); } final long[][] linesVisited = new long[topLevels.size()][]; final long[][] lineTimes = new long[topLevels.size()][]; final String[] classNames = new String[topLevels.size()]; final int[] classLoaders = new int[topLevels.size()]; final String[] sourceFiles = new String[topLevels.size()]; final BranchPoint[][] branchPoints = new BranchPoint[topLevels.size()][]; int c = 0; for(String sourceKey : sources.keySet()) { if(topLevels.get(sourceKey) == null) { continue; } int maxLines = 0; int numBranchPoints = 0; for(Integer i : sources.get(sourceKey)) { maxLines = Math.max(maxLines, coverageData.getLinesVisited(i).length); numBranchPoints += coverageData.getBranchPoints(i).length; } branchPoints[c] = new BranchPoint[numBranchPoints]; int b = 0; classNames[c] = coverageData.getClassNames()[topLevels.get(sourceKey)]; classLoaders[c] = coverageData.getClassLoaders()[topLevels.get(sourceKey)]; linesVisited[c] = new long[maxLines]; Arrays.fill(linesVisited[c], -1); lineTimes[c] = new long[maxLines]; Arrays.fill(lineTimes[c], -1); for(Integer i : sources.get(sourceKey)) { for(int l = 0; l < coverageData.getLinesVisited(i).length; l++) { long visits = coverageData.getLinesVisited(i)[l]; if(visits >=0) { linesVisited[c][l] = visits; } } for(int l = 0; l < coverageData.getLinesVisitTimes(i).length; l++) { long time = coverageData.getLinesVisitTimes(i)[l]; if(time >=0) { lineTimes[c][l] = time; } } for(BranchPoint branchPoint : coverageData.getBranchPoints(i)) { branchPoints[c][b++] = branchPoint; } } c++; } return new CoverageData() { public long[] getLinesVisited(int classId) { return linesVisited[classId]; } public long[] getLinesVisitTimes(int classId) { return lineTimes[classId]; } public String[] getClassNames() { return classNames; } @Override public int[] getClassLoaders() { return classLoaders; } @Override public ClassLoader getClassLoader(int classId) { return Registry.getClassLoader(classId); } public String[] getSourceFiles() { return sourceFiles; } public BranchPoint[] getBranchPoints(int classId) { return branchPoints[classId]; } public BranchPoint[] getBranchPointsForLine(int classId, int lineNumber) { List<BranchPoint> points = new ArrayList<BranchPoint>(); for (BranchPoint b : branchPoints[classId]) { if (b.getLinenumber() == lineNumber) { points.add(b); } } return points.toArray(new BranchPoint[points.size()]); } public String[][] getMethodNames() { throw new IllegalStateException("Folding not implemented for method names"); } public String[][] getMethodDescriptions() { throw new IllegalStateException("Folding not implemented for method descriptions"); } }; } public CoverageData filter(CoverageData coverageData, BitSet forClasses) { final long[][] linesVisited = new long[forClasses.cardinality()][]; final long[][] linesVisitedTime = new long[forClasses.cardinality()][]; final String[][] methodNames = new String[forClasses.cardinality()][]; final String[][] methodDescr = new String[forClasses.cardinality()][]; final String[] sourceFiles = new String[forClasses.cardinality()]; final String[] classNames = new String[forClasses.cardinality()]; final int[] classLoadersIds = new int[forClasses.cardinality()]; int c = 0; for (int i = forClasses.nextSetBit(0); i >= 0; i = forClasses.nextSetBit(i+1)) { linesVisited[c] = coverageData.getLinesVisited(i); linesVisitedTime[c] = coverageData.getLinesVisitTimes(i); methodNames[c] = coverageData.getMethodNames()[i]; methodDescr[c] = coverageData.getMethodDescriptions()[i]; sourceFiles[c] = coverageData.getSourceFiles()[i]; classNames[c] = coverageData.getClassNames()[i]; classLoadersIds[c] = coverageData.getClassLoaders()[i]; c++; } return new CoverageData() { @Override public long[] getLinesVisited(int classId) { return linesVisited[classId]; } @Override public long[] getLinesVisitTimes(int classId) { return linesVisitedTime[classId]; } @Override public String[] getClassNames() { return classNames; } @Override public String[][] getMethodNames() { return methodNames; } @Override public String[][] getMethodDescriptions() { return methodDescr; } @Override public String[] getSourceFiles() { return sourceFiles; } @Override public BranchPoint[] getBranchPoints(int classId) { return new BranchPoint[0]; //To change body of implemented methods use File | Settings | File Templates. } @Override public BranchPoint[] getBranchPointsForLine(int classId, int lineNumber) { return new BranchPoint[0]; //To change body of implemented methods use File | Settings | File Templates. } @Override public int[] getClassLoaders() { return classLoadersIds; } @Override public ClassLoader getClassLoader(int i) { return Registry.getClassLoader(i); } }; } }