http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/5077c457/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/CodeCoverageReporter.java
----------------------------------------------------------------------
diff --git 
a/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/CodeCoverageReporter.java
 
b/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/CodeCoverageReporter.java
new file mode 100755
index 0000000..9a4bb0e
--- /dev/null
+++ 
b/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/CodeCoverageReporter.java
@@ -0,0 +1,549 @@
+/*
+ *
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.apache.flex.tools.codecoverage.reporter;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.flex.tools.codecoverage.reporter.reports.IReportFactory;
+import org.apache.flex.tools.codecoverage.reporter.reports.IReportWriter;
+import org.apache.flex.tools.codecoverage.reporter.reports.ReportOptions;
+import org.apache.flex.tools.codecoverage.reporter.reports.XMLReportFactory;
+import org.apache.flex.tools.codecoverage.reporter.swf.SWFLineReporter;
+
+/**
+ * Analyzes code coverage data files and produces a report.
+ * 
+ * This class can be run from the command line and accept arguments to control
+ * the format of the report.
+ *
+ */
+public class CodeCoverageReporter
+{
+    /**
+     * Extension for code coverage reports.
+     */
+    private static final String DEFAULT_REPORT_NAME = "ccreport.xml";
+    private static final String DEFAULT_DATA_DIRECTORY = "ccdata";
+    
+    private static final String CCREPORTER_VERSION = "0.9";
+    
+    /**
+     * CodeCovergeReporter will read code code coverage result files and
+     * generate reports.
+     * 
+     */
+    public static void main(String[] args) throws IOException
+    {
+        // This message should not be localized.
+        System.out.println("Apache Flex Code Coverage Reporter");
+        System.out.println("Version " + CCREPORTER_VERSION);
+        System.out.println("");
+
+        if (args.length == 1 && "-help".equals(args[0]))
+        {
+            displayUsage();
+            System.exit(1);
+        }
+
+        CodeCoverageReporter reporter = new CodeCoverageReporter();
+        reporter.processArgs(args);
+        
+        System.out.println("Analyzing " + reporter.files.size() + " files");
+        
+        try
+        {
+            final CoverageData coverageData = new CoverageData();
+
+            // analyzes the files and then report the results.
+            for (File file : reporter.files)
+            {
+                reporter.analyze(file, coverageData);
+            }
+
+            final CoverageSummary coverageSummary = 
reporter.createCoverageSummary(coverageData); 
+            reporter.createReport(coverageSummary);
+
+            // output high level coverage to the console
+            reporter.outputCoverageSummaryToConsole(coverageSummary);
+
+            System.out.println("Report output to " + 
reporter.reportFile.getAbsolutePath());
+        }
+        catch (Error e)
+        {
+            e.printStackTrace();
+
+            System.err.println("");
+            System.err.println("An unrecoverable error occurred.");
+        }
+    }
+    
+    /**
+     * Create a regex string from a given user input string that can have
+     * wild cards but is not a regex pattern. 
+     * Supports simple wild cards: '*', '?'
+     * 
+     * @param userFilter user supplied filter that may only contain the '*' 
and '?'
+     *  wild card characters. All other cards will have no special meaning.
+     */
+    private static String createRegexStringFromUserArg(String userFilter)
+    {
+        // substitute regex for user wild cards.
+        StringBuilder regexString = new StringBuilder("^");
+        String[] results = userFilter.split("[\\?\\*]");
+        int currentIndex = 0;
+
+        for (String filter : results)
+        {
+            currentIndex += filter.length();
+            
+            if (filter.length() > 0)
+            {
+                regexString.append("\\Q");
+                regexString.append(filter);
+                regexString.append("\\E");
+            }
+            
+            if (currentIndex < userFilter.length())
+            {
+                if (userFilter.charAt(currentIndex) == '*')
+                {
+                    regexString.append(".*");
+                }
+                else if (userFilter.charAt(currentIndex) == '?')
+                {
+                    regexString.append(".?");
+                }
+            }
+            
+            currentIndex++; // skip past wild card
+        }
+        
+        regexString.append("$");
+        return regexString.toString();
+    }
+
+    public static Collection<File> listFiles(final File dir)
+    {
+        final String[] fileNames = dir.list();
+
+        if (fileNames == null)
+        {
+            return Collections.emptyList();
+        }
+
+        final Collection<File> fileList = new 
ArrayList<File>(fileNames.length);
+        for (int i = 0; i < fileNames.length; i++)
+        {
+            fileList.add(new File(dir.getPath(), fileNames[i]));
+        }
+        
+        return fileList;
+    }
+
+    private void outputCoverageSummaryToConsole(final CoverageSummary 
coverageSummary)
+    {
+        System.out.println("Results:");
+        
+        final SummaryInfo summaryInfo = 
coverageSummary.getOverallSummaryInfo();
+        int executed = summaryInfo.getExecutedLineCount();
+        int total = summaryInfo.getTotalLineCount();
+        int percent = total == 0 ? 0 : executed * 100 / total;
+        System.out.println("Line Coverage:   " +  percent + "%");
+
+        executed = summaryInfo.getExecutedMethodCount();
+        total = summaryInfo.getTotalMethodCount();
+        percent = total == 0 ? 0 : executed * 100 / total;
+        System.out.println("Method Coverage: " +  percent + "%");
+    }
+
+    private static void displayUsage()
+    {
+        System.out.println("Usage: ccreporter");
+        System.out.println("[-exclude filter]");
+        System.out.println("[-help]");
+        System.out.println("[-hide-unexecuted]");
+        System.out.println("[-hide-files]");
+        System.out.println("[-hide-methods]");
+        System.out.println("[-hide-packages]");
+        System.out.println("[-include filter]");
+        System.out.println("[-output filename]");
+        System.out.println("[-report-factory");
+        System.out.println("[filename | directory name]*");
+    }
+
+    /**
+     * The report file.
+     */
+    private File reportFile;
+    
+    /**
+     * Collection of data files to analyze.
+     */
+    private Collection<File> files;
+    
+    /**
+     * User filters converted to regex.
+     */
+    private Collection<String> includeFilters;
+    private Collection<String> excludeFilters;
+    
+    /**
+     * Raw user filters as input.
+     */
+    private Collection<String> userIncludeFilters;
+    private Collection<String> userExcludeFilters;
+    private boolean showPackages = true;
+    private boolean showFiles = true;
+    private boolean showMethods = true;
+    private boolean showUnexecutedDetails = false;
+    
+    /**
+     * User can specify their own report factory.
+     */
+    private String reportFactory;
+    
+    /**
+     * Create a code coverage reporter.
+     * 
+     */
+    public CodeCoverageReporter()
+    {
+    }
+
+    /**
+     * Parse the command line arguments and set the instance variables of
+     * the reporter.
+     * 
+     * @param args User specified arguments.
+     */
+    public void processArgs(final String[] args)
+    {
+        int index = 0;
+        File reportFile = null;
+        List<String> includeFilters = new ArrayList<String>();
+        List<String> excludeFilters = new ArrayList<String>();
+        List<String> userIncludeFilters = new ArrayList<String>();
+        List<String> userExcludeFilters = new ArrayList<String>();
+        boolean showPackages = true;
+        boolean showFiles = true;
+        boolean showMethods = true;
+        boolean showUnexecutedDetails = true;
+        String reportFactory = null;
+        
+        while ((index < args.length) && (args[index].startsWith("-")))
+        {
+            switch (args[index])
+            {
+                case "-include":
+                {
+                    userIncludeFilters.add(args[++index]);
+                    
includeFilters.add(createRegexStringFromUserArg(args[index]));
+                    index++;                    
+                    break;
+                }
+                case "-exclude":
+                {
+                    userExcludeFilters.add(args[++index]);
+                    
excludeFilters.add(createRegexStringFromUserArg(args[index]));
+                    index++;                    
+                    break;
+                }
+                case "-include-regex":
+                {
+                    includeFilters.add(args[++index]);
+                    index++;                    
+                    break;
+                }
+                case "-exclude-regex":
+                {
+                    excludeFilters.add(args[++index]);
+                    index++;                    
+                    break;
+                }
+                case "-output":
+                {
+                    reportFile = new File(args[++index]);
+                    index++;                    
+                    break;
+                }
+                case "-hide-unexecuted":
+                {
+                    showUnexecutedDetails = false;
+                    index++;                    
+                    break;
+                }
+                case "-hide-methods":
+                {
+                    showMethods = false;
+                    index++;                    
+                    break;
+                }
+                case "-hide-files":
+                {
+                    showFiles = false;
+                    index++;                    
+                    break;
+                }
+                case "-hide-packages":
+                {
+                    showPackages = false;
+                    index++;                    
+                    break;
+                }
+                case "-report-factory":
+                {
+                    reportFactory = args[++index];
+                    index++;                    
+                    break;
+                }
+                default:
+                {
+                    System.err.println("unknown argument " + args[index]);
+                    index++;                    
+                    System.exit(1);
+                }
+            }
+        }
+
+        if (reportFile == null)
+            reportFile = new File(DEFAULT_REPORT_NAME);
+
+        Collection<String>filenames = new ArrayList<String>();
+        Collection<File> files = new ArrayList<File>();
+
+        // Collect filenames/directories from user args.
+        // If no files specified look in the default data directory.
+        if (index >= args.length)
+        {
+            filenames.add(new File(System.getProperty("user.home"), 
DEFAULT_DATA_DIRECTORY).getAbsolutePath());
+        }
+        else
+        {
+            for (int i = index; i < args.length; i++)
+            {
+                filenames.add(args[i]);
+            }
+        }
+
+        // validate files
+        for (String filename : filenames)
+        {
+            File file = new File(filename);
+            
+            if (!file.exists())
+            {
+                System.err.println("File not found: " + 
file.getAbsolutePath());
+                System.exit(1);
+            }
+            else
+            {
+                if (file.isDirectory())
+                {
+                    Collection<File> newFiles = listFiles(file); 
+                    files.addAll(newFiles);
+                    System.out.println("Found " + newFiles.size() + " files in 
" + file.getAbsolutePath());
+                }
+                else
+                {
+                    files.add(file);
+                    System.out.println("Found " + file.getAbsolutePath());
+                }
+            }            
+            
+        }
+
+        this.includeFilters = includeFilters;
+        this.excludeFilters = excludeFilters;
+        this.userIncludeFilters = userIncludeFilters;
+        this.userExcludeFilters = userExcludeFilters;
+        this.showUnexecutedDetails = showUnexecutedDetails;
+        this.showMethods = showMethods;
+        this.showFiles = showFiles;
+        this.showPackages = showPackages;
+        this.files = files;
+        this.reportFile = reportFile;
+        this.reportFactory = reportFactory;
+    }
+
+    /**
+     * Read in a code coverage raw file and output raw code coverage data.
+     * 
+     * @param inFile
+     *            Code coverage execution data.
+     * @throws IOException
+     * @throws FileNotFoundException
+     */
+    public void analyze(final File inFile, final CoverageData coverageData)
+            throws FileNotFoundException, IOException
+    {
+        try (BufferedReader reader = new BufferedReader(new 
FileReader(inFile)))
+        {
+            String inLine;
+            final ArrayList<String> stringPool = new ArrayList<String>();
+            int inLineNumber = 1;
+
+            while ((inLine = reader.readLine()) != null)
+            {
+                // test first char:
+                // @{path} the SWF's path
+                // #{id,string} defines an id string
+                char firstChar = inLine.charAt(0);
+                
+                switch (firstChar)
+                {
+                    case '@':   // @swfURL
+                    {
+                        // read in SWF and analyze
+                        String swfURL = inLine.substring(1); 
+                        SWFLineReporter swfLineReporter = new 
SWFLineReporter(swfURL);
+                        swfLineReporter.readLines(coverageData);
+                        break;
+                    }
+                    case '#':   // instruction: packageFileID,packageFileString
+                    {
+                        // add id to pool
+                        String[] results = inLine.substring(1).split(",");
+
+                        assert results.length == 2 : "line " + inLineNumber
+                                + System.lineSeparator()
+                                + "improperly formatted line"
+                                + System.lineSeparator() + inLine;
+
+                        assert !stringPool.contains(results[1]) : "line "
+                                + inLineNumber + System.lineSeparator()
+                                + "string is already in the string pool: "
+                                + results[1];
+
+                        assert Integer.valueOf(results[0]) == 
stringPool.size() : "line "
+                                + inLineNumber
+                                + System.lineSeparator()
+                                + "string is already in the string pool: "
+                                + results[1];
+
+                        stringPool.add(results[1]);
+                        break;
+                    }
+                    default:
+                    {
+                        // "id,linenum"
+                        // Split line and record linenum as a hit.
+                        if (firstChar >= '0' && firstChar <= '9')
+                        {
+                            String[] results = inLine.split(",");
+                            String file = 
stringPool.get(Integer.valueOf(results[0]));
+                            int hitLineNumber = Integer.valueOf(results[1]);
+                            coverageData.setLineExecuted(file, hitLineNumber);
+                            break;                            
+                        }
+                        else
+                        {
+                            System.err.println("Warning: line " + inLineNumber 
+ ": unrecognized data, " + inLine);
+                        }
+                    }
+                }
+
+                inLineNumber++;
+            }
+        }
+        catch (NumberFormatException e)
+        {
+            System.err.println(inFile.getAbsolutePath() + " may not be a code 
coverage data file");
+            throw new IOException(e);
+        }
+    }
+
+    /**
+     * Create a code coverage report. The report summarizes the code coverage 
by
+     * package, file, and method. The report is output to the file specified
+     * by the user.
+     * 
+     * @param coverageSummary A summary of the coverage data.
+     * @throws IOException 
+     */
+    public void createReport(final CoverageSummary coverageSummary) throws 
IOException
+    {
+        createXMLReport(coverageSummary);
+    }
+
+    /**
+     * Create a summary of the raw code coverage data.
+     * 
+     * @param coverageData
+     * @return
+     */
+    protected CoverageSummary createCoverageSummary(final CoverageData 
coverageData)
+    {
+        final CoverageSummary coverageSummary = new 
CoverageSummary(coverageData, 
+                includeFilters, excludeFilters);
+        
+        coverageSummary.processCoverageData();
+        return coverageSummary;
+    }
+    
+    /**
+     * Output an XML report to the reportFile.
+     * 
+     * @param coverageSummary A summary of the coverage data.
+     * @throws IOException 
+     */
+    protected void createXMLReport(final CoverageSummary coverageSummary) 
throws IOException 
+    {
+        Class<?> classFactory = null;
+        IReportFactory factory = null;
+        
+        if (reportFactory != null)
+        {
+            try
+            {
+                classFactory = Class.forName(reportFactory);
+                factory = (IReportFactory) classFactory.newInstance();
+            }
+            catch (ClassNotFoundException | InstantiationException | 
IllegalAccessException e)
+            {
+                // fallback to default report writer
+                e.printStackTrace();
+                System.err.println("Report factory not found," + 
reportFactory);
+            }
+        }
+
+        if (factory == null)
+            factory = new XMLReportFactory();
+        
+        final ReportOptions reportOptions = new 
ReportOptions(userIncludeFilters, userExcludeFilters,
+                showPackages, showFiles, showMethods, showUnexecutedDetails);
+        final IReportWriter reportWriter = factory.createReport(reportOptions);
+        try (final FileWriter fileWriter = new FileWriter(reportFile);
+                final BufferedWriter bufferedWriter = new 
BufferedWriter(fileWriter))
+        {
+            reportWriter.writeTo(bufferedWriter, coverageSummary);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/5077c457/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/CoverageData.java
----------------------------------------------------------------------
diff --git 
a/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/CoverageData.java
 
b/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/CoverageData.java
new file mode 100755
index 0000000..4df2632
--- /dev/null
+++ 
b/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/CoverageData.java
@@ -0,0 +1,113 @@
+/*
+ *
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.apache.flex.tools.codecoverage.reporter;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeMap;
+
+/**
+ * Class to record the execution data as well the all the debug lines that 
exist
+ * in SWF file.
+ * Each line number is associated with method.
+ */
+public class CoverageData
+{
+    /**
+     * key   = package;file
+     * value = Map<line number, LineInfo>
+     */
+    final Map<String, Map<Integer, LineInfo>> lineMap =
+            new HashMap<String, Map<Integer, LineInfo>>();
+    Iterator<Map<String, Map<Integer, LineInfo>>> lineMapIterator;
+    
+    /**
+     * Add the existence of a line to the coverage data.
+     * 
+     * @param file The file the line number is in.
+     * @param lineNumber The line number of the line
+     * @param methodName The name of the method the line is in.
+     */
+    public void addLine(final String file, final int lineNumber,
+            final String methodName)
+    {
+        doAddLine(file, lineNumber, methodName);
+    }
+    
+    /**
+     * Mark a line number as being executed.
+     * @param file The file.
+     * @param lineNumber The line number that was executed.
+     */
+    public void setLineExecuted(final String file, final int lineNumber)
+    {
+        LineInfo lineInfo = doAddLine(file, lineNumber, null);
+        lineInfo.setExecuted(true);
+    }
+    
+    /**
+     * Get a list of entries in the coverage data.
+     * 
+     * @return list of entries in the coverage data.
+     */
+    public Set<Entry<String, Map<Integer, LineInfo>>> entrySet()
+    {
+        return lineMap.entrySet();
+    }
+
+    /**
+     * Add a line to the coverage data.
+     * This line is recorded as unexecuted.
+     * 
+     * @param file The file the line is found in.
+     * @param lineNumber The line number.
+     * @param methodName The method name.
+     * @return new LineInfo object
+     */
+    private LineInfo doAddLine(final String file, final int lineNumber,
+            final String methodName)
+    {
+        Map<Integer, LineInfo> lineInfoMap = lineMap.get(file);
+        
+        if (lineInfoMap == null)
+        {
+            lineInfoMap = new TreeMap<Integer, LineInfo>();
+            lineMap.put(file, lineInfoMap);
+        }
+
+        LineInfo lineInfo = lineInfoMap.get(lineNumber);
+        
+        if (lineInfo == null)
+        {
+            lineInfo = new LineInfo(methodName, lineNumber);
+            lineInfoMap.put(lineNumber, lineInfo);
+        }
+        else if (methodName != null && lineInfo.getMethodName() == null)
+        {
+            lineInfo.setMethodName(methodName);
+        }
+        
+        return lineInfo;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/5077c457/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/CoverageSummary.java
----------------------------------------------------------------------
diff --git 
a/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/CoverageSummary.java
 
b/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/CoverageSummary.java
new file mode 100755
index 0000000..ddf01a6
--- /dev/null
+++ 
b/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/CoverageSummary.java
@@ -0,0 +1,423 @@
+/*
+ *
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.apache.flex.tools.codecoverage.reporter;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Summary of code coverage at the package, file, and method level.
+ *
+ */
+public class CoverageSummary
+{
+    /**
+     *  Used to return the results of splitting the debugfile string. 
+     */
+    private static class FilePathComponents
+    {
+        public String packageName;
+        public String filename;
+    }
+    
+    private static final TreeSet<String> emptyTreeSet = new TreeSet<String>();
+
+    /**
+     * The coverage data being summarized.
+     */
+    private final CoverageData coverageData;
+    
+    /**
+     * Compiled regex patterns to include only specific files. 
+     */
+    private final Collection<Pattern> includeFilterPatterns = new 
ArrayList<Pattern>();
+    
+    /**
+     * Compiled regex patterns to exclude only specific files. 
+     */
+    private final Collection<Pattern> excludeFilterPatterns = new 
ArrayList<Pattern>();
+    
+    /**
+     * Coverage summary rolled up to the package level.
+     * 
+     * Key: package name
+     * Value: PackageSummaryInfo
+     */
+    private final Map<String, PackageSummaryInfo> packageSummaryMap = 
+            new TreeMap<String, PackageSummaryInfo>();
+
+    /**
+     * Coverage summary rolled up to the file level.
+     * 
+     * key: package;file
+     * value: SummaryInfo.
+     */
+    private final Map<String, SummaryInfo> fileSummaryMap = 
+            new TreeMap<String, SummaryInfo>();
+    
+    /**
+     * Coverage summary for methods.
+     * 
+     * Key: method name
+     * Value: SummaryInfo
+     */
+    private final Map<String, SummaryInfo> methodSummaryMap = 
+            new TreeMap<String, SummaryInfo>();
+    
+    /**
+     * Summary information for all packages being reported.
+     */
+    private final SummaryInfo overall = new SummaryInfo();
+    
+    /**
+     * Association of methods in a file.
+     * 
+     * Key: package;filename
+     * Value: Ordered set of method names.
+     */
+    private final Map<String, TreeSet<String>> methodsInFile =
+            new HashMap<String, TreeSet<String>>();
+
+    /**
+     * Create a coverage summmary object. The coverage summary object
+     * can process the coverage data and provide coverage data by 
+     * package, file, and method.
+     * 
+     * @param coverageData the coverage data to generate the summary from.
+     * @param includeFilters Regex filter patterns. Controls which files
+     * are included in the coverage summary.
+     * @param excludeFilters Regex filter patterns. Controls which files
+     * are excluded in the coverage summary.
+     * 
+     */
+    public CoverageSummary(final CoverageData coverageData, 
+            final Collection<String> includeFilters,
+            final Collection<String> excludeFilters)
+    {
+        this.coverageData = coverageData;
+        
+        initializePatterns(includeFilters, excludeFilters);
+    }
+    
+    /**
+     * Get the coverage data the summary is generated from.
+     * @return the coverage data.
+     */
+    public CoverageData getCoverageData()
+    {
+        return coverageData;
+    }
+
+    /**
+     * Get the aggregate summary info of all the included packages.
+     * 
+     * @return aggregate summary info.
+     */
+    public SummaryInfo getOverallSummaryInfo()
+    {
+        return overall;
+    }
+    
+    /**
+     * Entry set of all included packages.
+     * 
+     * @return Set of packages included in summary data.
+     */
+    public Set<Map.Entry<String, PackageSummaryInfo>> 
getPackageSummaryEntrySet()
+    {
+        return packageSummaryMap.entrySet();
+    }
+    
+    /**
+     * Entry set of all files included in the summary data.
+     * 
+     * @return Entry set
+     */
+    public Set<Map.Entry<String, SummaryInfo>> getFileSummaryEntrySet()
+    {
+        return fileSummaryMap.entrySet();
+    }
+
+    /**
+     * Get the coverage summmary info for a specific file.
+     * 
+     * @param packageFileKey key formed by calling createPackageFileKey().
+     * @return SummaryInfo for the specified file or null the file is
+     * not included in the summary data.
+     */
+    public SummaryInfo getFileSummaryInfo(final String packageFileKey)
+    {
+        return fileSummaryMap.get(packageFileKey);
+    }
+
+    /**
+     * Get the summary info for a specific method.
+     * 
+     * @param methodName The name of the method to get the summary info for.
+     * @return SummyInfo for the specified method or null if the method is
+     * not included in the summary data.
+     */
+    public SummaryInfo getMethodSummaryInfo(String methodName)
+    {
+        return methodSummaryMap.get(methodName);
+    }
+    
+    /**
+     * A set of methods declared in the specified file.
+     * 
+     * @param filename The name of the AS or MXML file.
+     * @return Set of method names.
+     */
+    public Set<String> getMethodsInFile(String filename)
+    {
+        TreeSet<String> results = methodsInFile.get(filename);
+        return results != null ? results : emptyTreeSet;
+    }
+    
+    /**
+     * Roll up the coverage data at a method, file, and package level.
+     * If include filters and/or exclude filters are specified then
+     * they are applied that this time.
+     */
+    public void processCoverageData()
+    {
+        // for all packages;files
+        for (Map.Entry<String, Map<Integer, LineInfo>> fileEntry : 
coverageData.entrySet())
+        {
+            final String packageFile = fileEntry.getKey();
+            final FilePathComponents fileComponents = 
splitPackageFile(packageFile);
+            final SummaryInfo summaryInfo = new SummaryInfo();
+            summaryInfo.setName(fileComponents.filename);
+            
+            // for all line numbers; 
+            // 1. summary at the file level
+            // 2. record execution status for each method.
+            for (final Map.Entry<Integer, LineInfo> lineEntry : 
fileEntry.getValue().entrySet())
+            {
+                final LineInfo lineInfo = lineEntry.getValue();
+                final String methodName = lineInfo.getMethodName();
+                
+                if (!shouldIncludeFile(fileComponents))
+                    continue;
+                
+                summaryInfo.setLineExecutionStatus(lineInfo.getLineNumber(),
+                        methodName, lineInfo.isExecuted());
+
+                addMethodSummaryInfo(fileComponents.packageName,
+                        fileComponents.filename, methodName, lineInfo);
+            }
+
+            addFileSummaryInfo(fileComponents.packageName,
+                    fileComponents.filename, summaryInfo);
+        }
+    }
+    
+    /**
+     * Determine if a file should be included in the summary.
+     * If no include filters or exclude filters are specified then
+     * all files are included.
+     * 
+     * @param pathComponents The package and file name to test.
+     * @return true if the package should be included, false otherwise.
+     */
+    private boolean shouldIncludeFile(final FilePathComponents pathComponents)
+    {
+        String className = pathComponents.packageName + "." + 
pathComponents.filename;
+        final int index = className.lastIndexOf('.');
+        
+        assert index != -1 : "no suffix found on filename";
+        
+        className = className.substring(0, index);
+        
+        // a class name is included if it is included by the pattern
+        // and not exclude by the exclude filters.
+        if (!(includeFilterPatterns.size() == 0) && 
+            !matches(includeFilterPatterns, className))
+        {
+            return false;
+        }
+        
+        if (!(excludeFilterPatterns.size() == 0) &&
+            matches(excludeFilterPatterns, className))
+        {
+            return false;
+        }
+        
+        return true;
+    }
+
+    /**
+     * Utility to test is a string matches one of a set of patterns.
+     * 
+     * @param patterns Collection of patterns
+     * @param value The value to match
+     * @return true if the pattern matches, false otherwise.
+     */
+    private boolean matches(final Collection<Pattern> patterns, final String 
value)
+    {
+        for (Pattern pattern : patterns)
+        {
+            Matcher matcher = pattern.matcher(value);
+            if (matcher.matches())
+                return true;
+        }
+
+        return false;
+    }
+    
+    /**
+     * Create a combination package/file key.
+     * 
+     * @param packageName The package name part of the key.
+     * @param filename THe filename part of the key.
+     * @return Key for the package/file.
+     */
+    public String createPackageFileKey(final String packageName, final String 
filename)
+    {
+        return packageName + ";" + filename;
+    }
+
+    /**
+     * Split a sourcePath;package/file string. These string come from the 
+     * AS debug_file opcodes and are in the code coverage data files.
+     * 
+     * @param packageFile The string to split into components.
+     * @return FilePathComponents
+     */
+    private FilePathComponents splitPackageFile(final String packageFile)
+    {
+        final String[] splitResults = packageFile.split(";");
+        String packageName = splitResults.length > 1 ? 
+                splitResults[splitResults.length - 2] : "";
+        final String filename = splitResults[splitResults.length - 1];
+        
+        // convert '\' and '/' path separators to '.' package separators.
+        if (packageName.length() > 0)
+            packageName = packageName.replaceAll("[\\\\/]", ".");
+        
+        final FilePathComponents results = new FilePathComponents();
+        results.packageName = packageName;
+        results.filename = filename;
+        
+        return results;
+    }
+
+    /**
+     * Aggregate summary information for a file.
+     * 
+     * This method takes summary information for a file
+     * and aggregates them at the file, package, and overall coverage.
+     * 
+     * @param packageName Package name the summary info is for.
+     * @param filename The file name the summary info is for.
+     * @param summaryInfo The summary info to aggregate.
+     */
+    private void addFileSummaryInfo(final String packageName, final String 
filename, 
+            final SummaryInfo summaryInfo)
+    {
+        if (summaryInfo.getTotalLineCount() == 0)
+            return;
+        
+        // summarize at the package level
+        fileSummaryMap.put(createPackageFileKey(packageName, filename), 
summaryInfo);
+        PackageSummaryInfo packageSummaryInfo = 
packageSummaryMap.get(packageName);
+        if (packageSummaryInfo == null)
+        {
+            packageSummaryInfo = new PackageSummaryInfo();
+            packageSummaryInfo.getSummaryInfo().setName(packageName);
+            packageSummaryMap.put(packageName, packageSummaryInfo);
+        }
+
+        packageSummaryInfo.addFile(packageName, filename);
+        packageSummaryInfo.add(summaryInfo);
+        
+        // summary of all of the packages
+        overall.add(summaryInfo);
+    }
+    
+    /**
+     * Add line coverage information about a method.
+     * 
+     * This method aggregates the line coverage information for a method.
+     * 
+     * @param packageName The name of the package the line info is from.
+     * @param filename The name of the file the line info is from.
+     * @param methodName The name of the method the line info is from.
+     * @param lineInfo The line info.
+     */
+    private void addMethodSummaryInfo(final String packageName, final String 
filename, 
+            final String methodName, final LineInfo lineInfo)
+    {
+        // ignore cinit and script init methods.
+        if (methodName == null || methodName.isEmpty())
+            return;
+        
+        // method summary info
+        SummaryInfo methodSummaryInfo = methodSummaryMap.get(methodName);
+        if (methodSummaryInfo == null)
+        {
+            methodSummaryInfo = new SummaryInfo();
+            methodSummaryInfo.setName(methodName);
+            methodSummaryMap.put(methodName, methodSummaryInfo);
+
+            final String key = createPackageFileKey(packageName, filename);
+            TreeSet<String> treeSet = methodsInFile.get(key);
+            if (treeSet == null)
+            {
+                treeSet = new TreeSet<String>();
+                treeSet.add(methodName);
+                methodsInFile.put(key, treeSet);                
+            }
+            
+            treeSet.add(methodName);
+        }
+        
+        methodSummaryInfo.setLineExecutionStatus(lineInfo.getLineNumber(),
+                methodName, lineInfo.isExecuted());
+    }
+
+    /**
+     * Initialize the patterns for the include and exclude filters.
+     * 
+     * @param includeFilters regex strings of classes to include.
+     * @param excludeFilters regex strings of classes to exclude.
+     */
+    private void initializePatterns(final Collection<String> includeFilters, 
+            final Collection<String>excludeFilters)
+    {
+        for (final String includeFilter : includeFilters)
+        {
+            includeFilterPatterns.add(Pattern.compile(includeFilter));
+        }
+
+        for (final String excludeFilter : excludeFilters)
+        {
+            excludeFilterPatterns.add(Pattern.compile(excludeFilter));
+        }
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/5077c457/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/LineInfo.java
----------------------------------------------------------------------
diff --git 
a/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/LineInfo.java
 
b/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/LineInfo.java
new file mode 100755
index 0000000..1c22e93
--- /dev/null
+++ 
b/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/LineInfo.java
@@ -0,0 +1,107 @@
+/*
+ *
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.apache.flex.tools.codecoverage.reporter;
+
+/**
+ * Simple value class that contains information about a line number in a source
+ * file.
+ * 
+ * Tracks:
+ * 1. the line number of this line
+ * 2. if the line was executed or not
+ * 3. the name of the method the line is in.
+ */
+public class LineInfo 
+{
+    private int lineNumber;
+    private boolean executed;
+    private String methodName;
+
+    /**
+     * Create an instance of LineInfo.
+     * 
+     * @param methodName The name of the method.
+     * @param lineNumber The source line number. 
+     */
+    public LineInfo(final String methodName, final int lineNumber)
+    {
+        this.methodName = methodName;
+        this.lineNumber = lineNumber;
+    }
+
+    /**
+     * The source line number of this line.
+     * @return the line number
+     */
+    public int getLineNumber()
+    {
+        return lineNumber;
+    }
+    
+    /**
+     * Set the source line number of this line.
+     * 
+     * @param lineNumber
+     */
+    public void setLineNumber(final int lineNumber)
+    {
+        this.lineNumber = lineNumber;
+    }
+    
+    /**
+     * Has the line been executed?
+     * 
+     * @return true if the line has been executed, false otherwise.
+     */
+    public boolean isExecuted()
+    {
+        return executed;
+    }
+    
+    /**
+     * Set the line number as being executed.
+     * 
+     * @param executed true if the line has been hit, false otherwise.
+     */
+    public void setExecuted(final boolean executed)
+    {
+        this.executed = executed;
+    }
+    
+    /**
+     * The method name containing this line.
+     * 
+     * @return The method name or an empty string if no method name is set.
+     */
+    public String getMethodName()
+    {
+        return methodName != null ? methodName : "";
+    }
+    
+    /**
+     * Set the method name this line is contained in.
+     * 
+     * @param methodName
+     */
+    public void setMethodName(final String methodName)
+    {
+        this.methodName = methodName;
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/5077c457/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/PackageSummaryInfo.java
----------------------------------------------------------------------
diff --git 
a/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/PackageSummaryInfo.java
 
b/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/PackageSummaryInfo.java
new file mode 100755
index 0000000..6e1fcdc
--- /dev/null
+++ 
b/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/PackageSummaryInfo.java
@@ -0,0 +1,77 @@
+/*
+ *
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.apache.flex.tools.codecoverage.reporter;
+
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ *  Summary of a package's coverage information.
+ *  Contains coverage summary of all of the files in the package.
+ */
+public class PackageSummaryInfo
+{
+    private Set<String> filesInPackage = new TreeSet<String>();
+    private SummaryInfo summaryInfo = new SummaryInfo();
+    
+    /**
+     * Set of files in a package.
+     * 
+     * @return The set files in the package. Each item in the
+     * set is a combined package name/filename in the following
+     * format: "packageName;filename".
+     */
+    public Set<String> getFilesInPackage()
+    {
+        return filesInPackage;
+    }
+
+    /**
+     * Add a file to this package summary info.
+     * 
+     * @param packageName The package name to add the summary info to.
+     * @param filename The name of file to add to the package.
+     */
+    public void addFile(final String packageName, final String filename)
+    {
+        filesInPackage.add(packageName + ";" + filename);
+    }
+    
+    /**
+     * The rolled up summary info for a package.
+     * 
+     * @return SummaryInfo
+     */
+    public SummaryInfo getSummaryInfo()
+    {
+        return summaryInfo;
+    }
+    
+    /**
+     * Aggregate summary info to this package.
+     * 
+     * @param info The summary info.
+     */
+    public void add(final SummaryInfo info)
+    {
+        summaryInfo.add(info);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/5077c457/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/SummaryInfo.java
----------------------------------------------------------------------
diff --git 
a/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/SummaryInfo.java
 
b/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/SummaryInfo.java
new file mode 100755
index 0000000..08e490a
--- /dev/null
+++ 
b/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/SummaryInfo.java
@@ -0,0 +1,187 @@
+/*
+ *
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.apache.flex.tools.codecoverage.reporter;
+
+import java.util.Collections;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * Simple value class to record summary information on the lines executed vs 
the
+ * total number of lines.
+ * 
+ * This information can be used for reporting at the package, file, and method
+ * level.
+ * 
+ * 1. total executed lines 
+ * 2. total number of lines 
+ * 3. total executed methods
+ * 4. total number of methods
+ * 
+ */
+public class SummaryInfo
+{
+    // name of object the summary info is for.
+    private String name;
+
+    /**
+     * The set of executed lines in sorted order.
+     */
+    private final Set<Integer> executedLineSet = new TreeSet<Integer>();
+
+    /**
+     * The set of unexecuted lines in sorted order.
+     */
+    private final Set<Integer> unexecutedLineSet = new TreeSet<Integer>();
+
+    /**
+     * The set of executed lines in sorted order.
+     */
+    private final Set<String> executedMethodSet = new TreeSet<String>();
+    private final Set<String> unexecutedMethodSet = new TreeSet<String>();
+
+    /**
+     * Name of the object the summary information applies to.
+     * @return name of the object.
+     */
+    public String getName()
+    {
+        return name != null ? name : "";
+    }
+
+    /**
+     * Set the name of the object the summary information applies to.
+     * @param name Name of the object.
+     */
+    public void setName(final String name)
+    {
+        this.name = name;
+    }
+
+    /**
+     * @return Number of executed lines.
+     */
+    public int getExecutedLineCount()
+    {
+        return executedLineSet.size();
+    }
+
+    /**
+     * 
+     * @return total number of lines.
+     */
+    public int getTotalLineCount()
+    {
+        return executedLineSet.size() + unexecutedLineSet.size();
+    }
+
+    /**
+     * 
+     * @return Number of methods executed.
+     */
+    public int getExecutedMethodCount()
+    {
+        return executedMethodSet.size();
+    }
+
+    /**
+     * 
+     * @return Total number of methods.
+     */
+    public int getTotalMethodCount()
+    {
+        return executedMethodSet.size() + unexecutedMethodSet.size();
+    }
+
+    /**
+     * The set of unexecuted lines.
+     * 
+     * @return Set of executed lines, sorted in ascending order.
+     */
+    public Set<Integer> getUnexecutedLines()
+    {
+        return Collections.unmodifiableSet(unexecutedLineSet);
+    }
+    
+    /**
+     * The set of unexecuted methods.
+     * 
+     * @return Set of executed methods, sorted in ascending order.
+     */
+    public Set<String> getUnexecutedMethods()
+    {
+        return Collections.unmodifiableSet(unexecutedMethodSet);
+    }
+    
+    /**
+     * Set the execution status of a given line and method.
+     * 
+     * @param lineNumber The line number of the line.
+     * @param methodName The name of the method containing the line.
+     * @param executed true if the line is executed, false otherwise.
+     */
+    public void setLineExecutionStatus(final int lineNumber, String methodName,
+            final Boolean executed)
+    {
+        if (executedLineSet.contains(lineNumber))
+            return;
+
+        // fixup method name that were not executed.
+        if (methodName == null)
+            methodName = "";
+
+        if (executed)
+        {
+            unexecutedLineSet.remove(lineNumber);
+            executedLineSet.add(lineNumber);
+
+            // ignore empty method names.
+            // these are cinit and script init methods.
+            if (!methodName.isEmpty())
+            {
+                unexecutedMethodSet.remove(methodName);
+                executedMethodSet.add(methodName);
+            }
+        }
+        else
+        {
+            unexecutedLineSet.add(lineNumber);
+
+            // ignore empty method names.
+            // these are cinit and script init methods.
+            if (!methodName.isEmpty())
+                unexecutedMethodSet.add(methodName);
+        }
+    }
+
+    /**
+     * Add the passed summary info to the current set of summary info.
+     * 
+     * @param summaryInfo
+     *            summary information to add in, may not be null.
+     */
+    public void add(final SummaryInfo summaryInfo)
+    {
+        unexecutedLineSet.addAll(summaryInfo.unexecutedLineSet);
+        unexecutedMethodSet.addAll(summaryInfo.unexecutedMethodSet);
+        executedLineSet.addAll(summaryInfo.executedLineSet);
+        executedMethodSet.addAll(summaryInfo.executedMethodSet);
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/5077c457/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/SummaryType.java
----------------------------------------------------------------------
diff --git 
a/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/SummaryType.java
 
b/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/SummaryType.java
new file mode 100755
index 0000000..cd6be2f
--- /dev/null
+++ 
b/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/SummaryType.java
@@ -0,0 +1,29 @@
+/*
+ *
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.apache.flex.tools.codecoverage.reporter;
+
+/**
+ * The type of summary info, either line or method.
+ */
+public enum SummaryType
+{
+    LINE,
+    METHOD
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/5077c457/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/reports/IReportFactory.java
----------------------------------------------------------------------
diff --git 
a/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/reports/IReportFactory.java
 
b/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/reports/IReportFactory.java
new file mode 100755
index 0000000..7603726
--- /dev/null
+++ 
b/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/reports/IReportFactory.java
@@ -0,0 +1,37 @@
+/*
+ *
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.apache.flex.tools.codecoverage.reporter.reports;
+
+/**
+ * Interface for code coverage report factories.
+ * 
+ * The default report factory can overridden by specifying the fully qualified
+ * class name of a report factory with the -report-factory command line option.
+ * 
+ */
+public interface IReportFactory
+{
+    /**
+     * Create a report writer that will output the code coverage report.
+     * 
+     * @param reportOptions Options to control the contents of the report. 
+     */
+    IReportWriter createReport(ReportOptions reportOptions);
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/5077c457/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/reports/IReportWriter.java
----------------------------------------------------------------------
diff --git 
a/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/reports/IReportWriter.java
 
b/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/reports/IReportWriter.java
new file mode 100755
index 0000000..353cd0f
--- /dev/null
+++ 
b/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/reports/IReportWriter.java
@@ -0,0 +1,40 @@
+/*
+ *
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.apache.flex.tools.codecoverage.reporter.reports;
+
+import java.io.BufferedWriter;
+
+import org.apache.flex.tools.codecoverage.reporter.CoverageSummary;
+
+/**
+ * Interface to a report writer.
+ *
+ * Allow for different reports to be created.
+ */
+public interface IReportWriter
+{
+    /**
+     * Write a report to the specified writer.
+     * 
+     * @param writer The writer.
+     * @param coverageSummary A summary of the coverage data.
+     */
+    void writeTo(BufferedWriter writer, CoverageSummary coverageSummary);
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/5077c457/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/reports/ReportOptions.java
----------------------------------------------------------------------
diff --git 
a/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/reports/ReportOptions.java
 
b/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/reports/ReportOptions.java
new file mode 100644
index 0000000..ac129ff
--- /dev/null
+++ 
b/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/reports/ReportOptions.java
@@ -0,0 +1,204 @@
+/*
+ *
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.apache.flex.tools.codecoverage.reporter.reports;
+
+import java.util.Collection;
+
+/**
+ *  Code Coverage Report options. 
+ *
+ */
+public class ReportOptions 
+{
+    private Collection<String> includeFilters;
+    private Collection<String> excludeFilters;
+    private boolean showPackages = true;
+    private boolean showFiles = true;
+    private boolean showMethods = true;
+    private boolean showUnexecutedDetails = false;
+    
+    /**
+     * Constructor.
+     * 
+     * @param includeFilters User specified include filters. 
+     * Equivalent to the -includes command line argument. 
+     * @param excludeFilters User specified exclude filters.
+     * Equivalent to the -excludes command line argument. 
+     * @param showPackages Determines if packages are listed in the report.
+     * Equivalent to the -showPackages command line argument.
+     * @param showFiles Determines if files are listed in the report. Files
+     * will not be show if packages are not shown.
+     * Equivalent to the -showFiles command line argument.
+     * @param showMethods Determines if method are listed in the report.
+     * Equivalent to the -showMethods command line argument.
+     * @param showUnexecutedDetails Determines if unexecuted lines and methods 
are
+     * listed in the report.
+     * Equivalent to the -showUnexecutedDetails command line argument. 
+     */
+    public ReportOptions(Collection<String> includeFilters,
+            Collection<String> excludeFilters, boolean showPackages,
+            boolean showFiles, boolean showMethods,
+            boolean showUnexecutedDetails)
+    {
+        super();
+        this.includeFilters = includeFilters;
+        this.excludeFilters = excludeFilters;
+        this.showPackages = showPackages;
+        this.showFiles = showFiles;
+        this.showMethods = showMethods;
+        this.showUnexecutedDetails = showUnexecutedDetails;
+    }
+
+    /**
+     * User specified include filters. 
+     * Equivalent to the -includes command line argument.
+     *  
+     * @return Collection of user filters.
+     */
+    public Collection<String> getIncludeFilters()
+    {
+        return includeFilters;
+    }
+    
+    /**
+     * Equivalent to the -includes command line argument.
+     *  
+     * @param includeFilters Collection of filters to include classes in the 
+     * report. 
+     */
+    public void setIncludeFilters(Collection<String> includeFilters)
+    {
+        this.includeFilters = includeFilters;
+    }
+
+    /**
+     * User specified exclude filters.
+     * Equivalent to the -excludes command line argument. 
+     * 
+     * @return Collection of filters to exclude classes from the report.
+     */
+    public Collection<String> getExcludeFilters()
+    {
+        return excludeFilters;
+    }
+
+    /**
+     * Equivalent to the -excludes command line argument. 
+     *
+     * @param excludeFilters Collection of filters to exclude classes from
+     * the report.
+     */
+    public void setExcludeFilters(Collection<String> excludeFilters)
+    {
+        this.excludeFilters = excludeFilters;
+    }
+    
+    /**
+     * Determines if packages are listed in the report.
+     * Equivalent to the -showPackages command line argument.
+     * 
+     * @return true if packages are listed in the report, false otherwise.
+     */
+    public boolean isShowPackages()
+    {
+        return showPackages;
+    }
+
+    /**
+     * Determines if packages are listed in the report.
+     * Equivalent to the -showPackages command line argument.
+     * 
+     * @param showPackages Set to true to show packages in the report.
+     */
+    public void setShowPackages(boolean showPackages)
+    {
+        this.showPackages = showPackages;
+    }
+
+    /**
+     * Determines if files are listed in the report.
+     * Equivalent to the -showFiles command line argument.
+     * 
+     * @return true if files are listed in the report, false otherwise.
+     */
+    public boolean isShowFiles()
+    {
+        return showFiles;
+    }
+    
+    /**
+     * Determines if files are listed in the report.
+     * Equivalent to the -showFiles command line argument.
+     * 
+     * @param showFiles Set to true to show files in the report.
+     */
+    public void setShowFiles(boolean showFiles)
+    {
+        this.showFiles = showFiles;
+    }
+    
+    /**
+     * Determines if methods are listed in the report.
+     * Equivalent to the -showMethods command line argument.
+     * 
+     * @return true if methods are listed in the report, false otherwise.
+     */
+    public boolean isShowMethods()
+    {
+        return showMethods;
+    }
+
+    /**
+     * Determines if methods are listed in the report.
+     * Equivalent to the -showMethods command line argument.
+     * 
+     * @param showFiles Set to true to show methods in the report.
+     */
+    public void setShowMethods(boolean showMethods)
+    {
+        this.showMethods = showMethods;
+    }
+    
+    /**
+     * Determines if unexecuted lines and unexecuted methods are listed in the
+     * report.
+     * Equivalent to the -showUnexecutedDetails command line argument.
+     * 
+     * @return true if unexecuted lines and unexecuted are listed in the 
+     * report, false otherwise.
+     */
+    public boolean isShowUnexecutedDetails()
+    {
+        return showUnexecutedDetails;
+    }
+
+    /**
+     * Determines if unexecuted lines and unexecuted methods are listed in the
+     * report.
+     * Equivalent to the -showUnexecutedDetails command line argument.
+     * 
+     * @param showUnexecutedDetails Set to true to show methods in the report.
+     */
+    public void setShowUnexecutedDetails(boolean showUnexecutedDetails)
+    {
+        this.showUnexecutedDetails = showUnexecutedDetails;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/5077c457/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/reports/XMLReportFactory.java
----------------------------------------------------------------------
diff --git 
a/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/reports/XMLReportFactory.java
 
b/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/reports/XMLReportFactory.java
new file mode 100755
index 0000000..d5e405f
--- /dev/null
+++ 
b/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/reports/XMLReportFactory.java
@@ -0,0 +1,36 @@
+/*
+ *
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.apache.flex.tools.codecoverage.reporter.reports;
+
+/**
+ * Factory for an XML report of code coverage.
+ * This is the default factory.
+ * 
+ */
+public class XMLReportFactory implements IReportFactory
+{
+
+    @Override
+    public IReportWriter createReport(ReportOptions reportOptions)
+    {
+        return new XMLReportWriter(reportOptions);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/5077c457/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/reports/XMLReportWriter.java
----------------------------------------------------------------------
diff --git 
a/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/reports/XMLReportWriter.java
 
b/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/reports/XMLReportWriter.java
new file mode 100755
index 0000000..aeeec72
--- /dev/null
+++ 
b/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/reports/XMLReportWriter.java
@@ -0,0 +1,371 @@
+/*
+ *
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.apache.flex.tools.codecoverage.reporter.reports;
+
+import java.io.BufferedWriter;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.flex.tools.codecoverage.reporter.CoverageSummary;
+import org.apache.flex.tools.codecoverage.reporter.PackageSummaryInfo;
+import org.apache.flex.tools.codecoverage.reporter.SummaryInfo;
+import org.apache.flex.tools.codecoverage.reporter.SummaryType;
+
+/**
+ * XML formatted code coverage report.
+ *
+ */
+public class XMLReportWriter implements IReportWriter
+{
+    private static final String REPORT_VERSION = "1.0";
+    
+    private Collection<String> includeFilters;
+    private Collection<String> excludeFilters;
+    private boolean showPackages;
+    private boolean showFiles;
+    private boolean showMethods;
+    private boolean showUnexecutedDetails;
+    
+    /**
+     * Constructor.
+     * 
+     * @param reportOptions Options to control the contents of the report. 
+     */
+    public XMLReportWriter(final ReportOptions reportOptions)
+    {
+        this.includeFilters = reportOptions.getIncludeFilters();
+        this.excludeFilters = reportOptions.getExcludeFilters();
+        this.showPackages = reportOptions.isShowPackages();
+        this.showFiles = reportOptions.isShowFiles();
+        this.showMethods = reportOptions.isShowMethods();
+        this.showUnexecutedDetails = reportOptions.isShowUnexecutedDetails();
+    }
+
+    @Override
+    public void writeTo(final BufferedWriter writer, final CoverageSummary 
coverageSummary)
+    {
+        final XMLOutputFactory xmlOutputFactory = 
XMLOutputFactory.newInstance();
+        assert xmlOutputFactory != null : "Expect XMLOutputFactory 
implementation.";
+
+        try
+        {
+            final XMLStreamWriter xmlWriter = xmlOutputFactory.
+                    createXMLStreamWriter(writer);
+            xmlWriter.writeStartDocument("utf-8", "1.0");
+            
+            // write top-level report
+            outputTopLevelStart(xmlWriter, 
coverageSummary.getOverallSummaryInfo());
+            
+            if (showPackages)
+            {
+                // start package element
+                xmlWriter.writeStartElement("packages");
+                
+                for (Map.Entry<String, PackageSummaryInfo> packageEntry :
+                     coverageSummary.getPackageSummaryEntrySet())
+                {
+                    PackageSummaryInfo packageSummary = 
packageEntry.getValue();
+                    outputPackageCoverageStart(xmlWriter, 
packageSummary.getSummaryInfo());
+
+                    if (showFiles)
+                    {
+                        outputFiles(xmlWriter, packageSummary, 
coverageSummary);
+                    }
+
+                    xmlWriter.writeEndElement(); // package
+                }
+                
+                xmlWriter.writeEndElement(); // packages
+            }
+
+            xmlWriter.writeEndElement(); // code-coverage (top-level)
+            xmlWriter.writeEndDocument();
+            xmlWriter.close();
+        }
+        catch (XMLStreamException e)
+        {
+            e.printStackTrace();
+        }
+
+    }
+    
+    /**
+     * Output the files xml and its children.
+     * 
+     * @param xmlWriter
+     * @param packageSummary
+     * @param coverageSummary
+     * @throws XMLStreamException
+     */
+    private void outputFiles(final XMLStreamWriter xmlWriter,
+            final PackageSummaryInfo packageSummary, 
+            final CoverageSummary coverageSummary) throws XMLStreamException
+    {
+        // start file element
+        xmlWriter.writeStartElement("files");
+
+        for (final String packageFileKey : packageSummary.getFilesInPackage()) 
+        {
+            final SummaryInfo fileSummary = 
coverageSummary.getFileSummaryInfo(packageFileKey);
+            outputFileCoverageStart(xmlWriter, fileSummary);
+            
+            final Set<String> methodNames = 
coverageSummary.getMethodsInFile(packageFileKey);
+            if (showMethods && !methodNames.isEmpty())
+            {
+                // start method element
+                xmlWriter.writeStartElement("methods");
+
+                for (final String methodName : methodNames)
+                {
+                    SummaryInfo methodSummary = coverageSummary.
+                            getMethodSummaryInfo(methodName);
+                    outputMethodNameCoverage(xmlWriter, methodSummary);
+                }
+                
+                xmlWriter.writeEndElement(); // methods
+            }
+            
+            xmlWriter.writeEndElement(); // file
+        }
+
+        xmlWriter.writeEndElement(); // files
+    }
+
+    /**
+     * Output the coverage information for a method.
+     * 
+     * @param xmlWriter
+     * @param summaryInfo
+     * @throws XMLStreamException
+     */
+    private void outputMethodNameCoverage(final XMLStreamWriter xmlWriter,
+            final SummaryInfo summaryInfo) throws XMLStreamException
+    {
+        xmlWriter.writeStartElement("method");
+        xmlWriter.writeAttribute("name", summaryInfo.getName());
+
+        outputLineCoverage(xmlWriter, summaryInfo, false);
+        outputMethodCoverage(xmlWriter, summaryInfo, false);  
+        xmlWriter.writeEndElement();
+    }
+
+    /**
+     * Output the start element for file coverage information.
+     * 
+     * @param xmlWriter
+     * @param summaryInfo
+     * @throws XMLStreamException
+     */
+    private void outputFileCoverageStart(final XMLStreamWriter xmlWriter,
+            final SummaryInfo summaryInfo) throws XMLStreamException
+    {
+        xmlWriter.writeStartElement("file");
+        xmlWriter.writeAttribute("name", summaryInfo.getName());
+
+        outputLineCoverage(xmlWriter, summaryInfo, showUnexecutedDetails);
+        outputMethodCoverage(xmlWriter, summaryInfo, showUnexecutedDetails);  
+    }
+
+    /**
+     * Output code coverage for a package.
+     * @param xmlWriter
+     * @param summaryInfo
+     * @throws XMLStreamException
+     */
+    private void outputPackageCoverageStart(final XMLStreamWriter xmlWriter,
+            final SummaryInfo summaryInfo) throws XMLStreamException
+    {
+        xmlWriter.writeStartElement("package");
+        xmlWriter.writeAttribute("name", summaryInfo.getName());
+
+        outputLineCoverage(xmlWriter, summaryInfo, false);
+        outputMethodCoverage(xmlWriter, summaryInfo, false);
+    }
+
+    /**
+     * Output top level summary information
+     * 
+     * @param summaryInfo overall coverage info.
+     * @throws XMLStreamException 
+     */
+    private void outputTopLevelStart(final XMLStreamWriter xmlWriter,
+            final SummaryInfo summaryInfo) throws XMLStreamException
+    {
+        xmlWriter.writeStartElement("code-coverage");
+        xmlWriter.writeAttribute("version", REPORT_VERSION);
+        
+        outputLineCoverage(xmlWriter, summaryInfo, false);
+        outputMethodCoverage(xmlWriter, summaryInfo, false);
+        outputFilter(xmlWriter, "include-filter");
+        outputFilter(xmlWriter, "exclude-filter");
+    }
+
+    /**
+     * Output filters as part of the report.
+     * 
+     * @param xmlWriter
+     * @param filterName The name of the filter to output.
+     * @throws XMLStreamException 
+     */
+    private void outputFilter(final XMLStreamWriter xmlWriter,
+            final String filterName) throws XMLStreamException
+    {
+        Collection<String> filters = null;
+        String startElementName = null;
+        
+        if ("include-filter".equals(filterName))
+        {
+            startElementName = "include-filters";
+            filters = includeFilters;
+        }
+        else if ("exclude-filter".equals(filterName))
+        {
+            startElementName = "exclude-filters";
+            filters = excludeFilters;            
+        }
+        else 
+        {
+            throw new IllegalArgumentException("unexpected filter name:" + 
filterName);
+        }
+
+        if (filters.isEmpty())
+            return;
+        
+        xmlWriter.writeStartElement(startElementName);
+        
+        for (final String filter : filters)
+        {
+            xmlWriter.writeStartElement(filterName);
+            xmlWriter.writeCharacters(filter);
+            xmlWriter.writeEndElement();
+        }
+        
+        xmlWriter.writeEndElement();
+    }
+
+    /**
+     * Common method to output line coverage information.
+     * 
+     * @param xmlWriter
+     * @param overall
+     * @throws XMLStreamException 
+     */
+    private void outputLineCoverage(final XMLStreamWriter xmlWriter,
+            final SummaryInfo overall, boolean showDetails) throws 
XMLStreamException
+    {
+        outputSummaryInfo(xmlWriter, "line-coverage", overall, 
SummaryType.LINE, showDetails);
+    }
+
+    /**
+     * Common method to output method coverage information.
+     * 
+     * @param xmlWriter
+     * @param overall
+     * @throws XMLStreamException 
+     */
+    private void outputMethodCoverage(final XMLStreamWriter xmlWriter,
+            final SummaryInfo overall, final boolean showDetails) 
+            throws XMLStreamException
+    {
+        outputSummaryInfo(xmlWriter, "method-coverage", overall, 
+                SummaryType.METHOD, showDetails);
+    }
+
+    /**
+     * Common method to output summary information.
+     * 
+     * @param xmlWriter The writer.
+     * @param elementName The name of the element.
+     * @param summaryInfo The summary info to output.
+     * @param summaryType Choose either LINE or METHOD.
+     * @param showDetails Show the lines/methods that were not executed.
+     * @throws XMLStreamException 
+     */
+    private void outputSummaryInfo(final XMLStreamWriter xmlWriter,
+            final String elementName,
+            final SummaryInfo summaryInfo, 
+            final SummaryType summaryType,
+            final boolean showDetails) throws XMLStreamException
+    {
+        xmlWriter.writeStartElement(elementName);
+
+        final int executed;
+        final int total;
+        final int percent;
+        Set<?> items = null;
+        
+        if (summaryType == SummaryType.LINE)
+        {
+            executed = summaryInfo.getExecutedLineCount();
+            total = summaryInfo.getTotalLineCount();
+            percent = total == 0 ? 0 : executed * 100 / total;
+            if (showDetails)
+                items = summaryInfo.getUnexecutedLines();
+        }
+        else
+        {
+            executed = summaryInfo.getExecutedMethodCount();
+            total = summaryInfo.getTotalMethodCount();
+            percent = total == 0 ? 0 : executed * 100 / total; 
+            if (showDetails)
+                items = summaryInfo.getUnexecutedMethods();
+        }
+        
+        xmlWriter.writeAttribute("executed", Integer.toString(executed));
+        xmlWriter.writeAttribute("total", Integer.toString(total));
+        xmlWriter.writeAttribute("percent", Integer.toString(percent));
+        
+        if (showDetails)
+            outputUnexecutedSet(xmlWriter, items);
+        
+        xmlWriter.writeEndElement();
+    }
+
+    /**
+     * Output unexecuted lines or methods.
+     * 
+     * @param xmlWriter
+     * @param items
+     * @throws XMLStreamException
+     */
+    private void outputUnexecutedSet(final XMLStreamWriter xmlWriter,
+            final Set<?> items) throws XMLStreamException
+    {
+        if (items == null || items.isEmpty())
+            return;
+        
+        xmlWriter.writeStartElement("unexecuted-set");
+        
+        for (Object item : items)
+        {
+            xmlWriter.writeStartElement("unexecuted");
+            xmlWriter.writeCharacters(item.toString());
+            xmlWriter.writeEndElement();
+        }
+        
+        xmlWriter.writeEndElement();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/5077c457/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/swf/DebugLineVisitor.java
----------------------------------------------------------------------
diff --git 
a/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/swf/DebugLineVisitor.java
 
b/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/swf/DebugLineVisitor.java
new file mode 100755
index 0000000..648e19b
--- /dev/null
+++ 
b/CodeCoverage/JavaServer/java/src/org/apache/flex/tools/codecoverage/reporter/swf/DebugLineVisitor.java
@@ -0,0 +1,239 @@
+/*
+ *
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.apache.flex.tools.codecoverage.reporter.swf;
+
+import org.apache.flex.abc.ABCConstants;
+import org.apache.flex.abc.Pool;
+import org.apache.flex.abc.instructionlist.InstructionList;
+import org.apache.flex.abc.semantics.ExceptionInfo;
+import org.apache.flex.abc.semantics.Instruction;
+import org.apache.flex.abc.semantics.Label;
+import org.apache.flex.abc.semantics.MethodBodyInfo;
+import org.apache.flex.abc.semantics.MethodInfo;
+import org.apache.flex.abc.semantics.Name;
+import org.apache.flex.abc.visitors.IMethodBodyVisitor;
+import org.apache.flex.abc.visitors.IMethodVisitor;
+import org.apache.flex.abc.visitors.ITraitsVisitor;
+import org.apache.flex.abc.visitors.NilABCVisitor;
+import org.apache.flex.abc.visitors.NilVisitors;
+import org.apache.flex.tools.codecoverage.reporter.CoverageData;
+
+/**
+ * Gather all the debug lines and method in a SWF file. 
+ * Look for debug_file and debug_line op codes and record them so we know all
+ * of possible lines in the SWF that can be executed.
+ *
+ */
+public class DebugLineVisitor extends NilABCVisitor
+{
+
+    private final Pool<String> stringPool = new 
Pool<String>(Pool.DefaultType.HasDefaultZero);
+    private final CoverageData coverageData;
+
+    /**
+     * Constructor
+     * 
+     * @param coverageData The coverage data where debug lines will be added
+     * as unexecuted lines. If a line is already in the coverage data and is
+     * marked as executed, then it will remain an executed line.
+     */
+    public DebugLineVisitor(final CoverageData coverageData)
+    {
+        this.coverageData = coverageData;
+    }
+
+    @Override
+    public IMethodVisitor visitMethod(MethodInfo minfo)
+    {
+        return new MethodVisitor();
+    }
+
+    @Override
+    public void visitPooledString(String s)
+    {
+        stringPool.add(s);
+    }
+
+    /**
+     * Visit all the methods in the ABC.
+     */
+    private class MethodVisitor implements IMethodVisitor
+    {
+        @Override
+        public void visitEnd()
+        {
+        }
+
+        @Override
+        public void visit()
+        {
+        }
+
+        @Override
+        public IMethodBodyVisitor visitBody(MethodBodyInfo mbInfo)
+        {
+            return new MethodBodyVisitor(mbInfo);
+        }
+    }
+    
+    /**
+     * Visit all the method bodies in the ABC.
+     */
+    private class MethodBodyVisitor implements IMethodBodyVisitor
+    {
+        private final MethodBodyInfo mbInfo;
+        private String currentFilename;
+        
+        public MethodBodyVisitor(MethodBodyInfo mbInfo)
+        {
+            this.mbInfo = mbInfo;
+        }
+
+        @Override
+        public void visitEnd()
+        {
+        }
+
+        @Override
+        public void labelCurrent(Label l)
+        {
+        }
+
+        @Override
+        public void labelNext(Label l)
+        {
+        }
+
+        @Override
+        public void visit()
+        {
+        }
+
+        @Override
+        public int visitException(Label from, Label to, Label target, 
+                Name exception_type, Name catch_var)
+        {
+            return  mbInfo.addExceptionInfo(new ExceptionInfo(from, to, target,
+                        exception_type, catch_var));
+        }
+
+        @Override
+        public void visitInstructionList(InstructionList new_list)
+        {
+            for (Instruction inst : new_list.getInstructions())
+            {
+                int opcode = inst.getOpcode();
+                assert opcode != ABCConstants.OP_debugfile && 
+                        opcode != ABCConstants.OP_debugline :
+                        "unexpected debug opcode";
+            }
+        }
+
+        @Override
+        public void visitInstruction(int opcode)
+        {
+            assert opcode != ABCConstants.OP_debugfile && 
+                    opcode != ABCConstants.OP_debugline :
+                    "unexpected debug opcode";
+        }
+
+        @Override
+        public void visitInstruction(int opcode, int immediate_operand)
+        {
+            if (opcode == ABCConstants.OP_debugfile)
+            {
+                recordDebugFile(immediate_operand);
+            }
+            else if (opcode == ABCConstants.OP_debugline)
+            {
+                recordDebugLine(immediate_operand);
+            }
+        }
+
+        @Override
+        public void visitInstruction(int opcode, Object[] operands)
+        {
+            assert opcode != ABCConstants.OP_debugfile && 
+                    opcode != ABCConstants.OP_debugline :
+                    "unexpected debug opcode";
+        }
+
+        @Override
+        public void visitInstruction(int opcode, Object single_operand)
+        {
+            assert opcode != ABCConstants.OP_debugline :
+                    "unexpected debug opcode";
+
+            if (opcode == ABCConstants.OP_debugfile)
+                recordDebugFile((String)single_operand);
+        }
+
+        @Override
+        public void visitInstruction(Instruction instruction)
+        {
+            int opcode = instruction.getOpcode();
+            assert opcode != ABCConstants.OP_debugfile && 
+                    opcode != ABCConstants.OP_debugline :
+                    "unexpected debug opcode";
+        }
+
+        @Override
+        public ITraitsVisitor visitTraits()
+        {
+            return NilVisitors.NIL_TRAITS_VISITOR;
+        }
+
+        /**
+         * Record a debugfile string
+         * 
+         * @param filenameIndex Index of filename in the string pool.
+         */
+        private void recordDebugFile(final int filenameIndex)
+        {
+            recordDebugFile(stringPool.getValues().get(filenameIndex));
+        }
+
+        /**
+         * Set the filename in the context for debug lines that
+         * come after it.
+         * 
+         * @param filename The debugfile filename.
+         */
+        private void recordDebugFile(final String filename)
+        {
+            currentFilename = filename;
+        }
+        
+        /**
+         * Record a debug line into the coverage data.
+         * 
+         * @param lineNumber The line number of the debug line in 
+         * the file that is set by the last debugfile opcode.
+         */
+        private void recordDebugLine(final int lineNumber)
+        {
+            assert currentFilename != null : 
+                "currentFilename must have been set by a debugFile 
instruction";
+
+            String methodName =  mbInfo.getMethodInfo().getMethodName(); 
+            coverageData.addLine(currentFilename, lineNumber, methodName);
+        }
+    }
+}

Reply via email to