[med-svn] [picard-tools] 01/01: Imported Upstream version 2.1.1+dfsg

Andreas Tille tille at debian.org
Sun Mar 13 06:48:05 UTC 2016


This is an automated email from the git hooks/post-receive script.

tille pushed a commit to branch upstream
in repository picard-tools.

commit 115543bd046ef93efa75c1d16e9f6af3baa8c94b
Author: Andreas Tille <tille at debian.org>
Date:   Sun Mar 13 07:44:27 2016 +0100

    Imported Upstream version 2.1.1+dfsg
---
 build.sbt                                          |   4 +-
 build.xml                                          | 155 +++++++++++---------
 src/java/picard/Test.java                          |   6 +-
 src/java/picard/analysis/CollectGcBiasMetrics.java |   4 +-
 .../picard/analysis/CollectMultipleMetrics.java    |  44 +++---
 src/java/picard/analysis/CollectRrbsMetrics.java   |   4 +-
 .../picard/analysis/GcBiasMetricsCollector.java    |   6 +-
 src/java/picard/analysis/MeanQualityByCycle.java   |   2 +-
 .../CollectSequencingArtifactMetrics.java          |  16 +-
 .../analysis/directed/TargetMetricsCollector.java  |   4 +-
 src/java/picard/cmdline/CommandLineParser.java     | 147 ++++++++++++-------
 .../CrosscheckReadGroupFingerprints.java           |   2 +-
 src/java/picard/fingerprint/HaplotypeMap.java      |   4 +-
 ...lotypeProbabilitiesFromGenotypeLikelihoods.java |   2 +-
 .../picard/illumina/ClusterDataToSamConverter.java |   6 +-
 .../picard/illumina/ExtractIlluminaBarcodes.java   |  10 +-
 .../picard/illumina/IlluminaBasecallsToFastq.java  |   6 +-
 .../picard/illumina/IlluminaBasecallsToSam.java    |  10 +-
 src/java/picard/illumina/MarkIlluminaAdapters.java |   2 +-
 src/java/picard/illumina/parser/BarcodeParser.java |   2 +-
 .../illumina/parser/FourChannelIntensityData.java  |   8 +-
 .../parser/IlluminaDataProviderFactory.java        |   4 +-
 .../picard/illumina/parser/IlluminaFileUtil.java   |   4 +-
 .../illumina/parser/MultiTileBclFileUtil.java      |   2 +-
 .../picard/illumina/parser/PerTileFileUtil.java    |   2 +-
 src/java/picard/illumina/parser/ReadStructure.java |   4 +-
 src/java/picard/illumina/parser/TileIndex.java     |   2 +-
 .../illumina/parser/fakers/BarcodeFileFaker.java   |   8 +-
 .../illumina/parser/fakers/PosFileFaker.java       |   8 +-
 .../readers/BclQualityEvaluationStrategy.java      |   2 +-
 .../illumina/parser/readers/FilterFileReader.java  |   2 +-
 .../parser/readers/MMapBackedIteratorFactory.java  |   4 +-
 .../quality/CollectHiSeqXPfFailMetrics.java        |   2 +-
 src/java/picard/sam/FastqToSam.java                |   2 +-
 src/java/picard/sam/FilterSamReads.java            |  52 +++++--
 src/java/picard/sam/MergeBamAlignment.java         |   6 +-
 src/java/picard/sam/RevertSam.java                 |   2 +-
 src/java/picard/sam/SamAlignmentMerger.java        |  10 +-
 src/java/picard/sam/SamToFastq.java                |   4 +-
 src/java/picard/sam/SplitSamByLibrary.java         |   2 +-
 .../markduplicates/EstimateLibraryComplexity.java  |   4 +-
 ...ctOpticalDuplicateFinderCommandLineProgram.java |   6 +-
 .../MemoryBasedReadEndsForMarkDuplicatesMap.java   |   2 +-
 src/java/picard/sam/util/PhysicalLocation.java     |   2 +-
 src/java/picard/util/AdapterMarker.java            |   2 +-
 src/java/picard/util/BaitDesigner.java             |   2 +-
 src/java/picard/util/BasicInputParser.java         |   8 +-
 src/java/picard/util/DbSnpBitSetUtil.java          |  71 ++++++---
 src/java/picard/util/IlluminaUtil.java             |  10 +-
 src/java/picard/util/IntervalListTools.java        |   2 +-
 src/java/picard/util/MathUtil.java                 |   2 +-
 .../picard/vcf/CollectVariantCallingMetrics.java   |  13 +-
 src/java/picard/vcf/GenotypeConcordance.java       |   4 +-
 .../picard/vcf/filter/AlleleBalanceFilter.java     |   2 +-
 src/java/picard/vcf/filter/FilterVcf.java          | 131 ++++++++++++-----
 src/java/picard/vcf/processor/VcfFileSegment.java  |   2 +-
 .../vcf/processor/VcfFileSegmentGenerator.java     |   4 +-
 .../CollectAlignmentSummaryMetricsTest.java        |   6 +-
 .../java/picard/cmdline/CommandLineParserTest.java | 162 +++++++++++++++++++++
 .../illumina/CheckIlluminaDirectoryTest.java       |   2 +-
 src/tests/java/picard/sam/FilterSamReadsTest.java  |  77 ++++++++++
 .../java/picard/util/BedToIntervalListTest.java    |   2 +-
 .../java/picard/util/IntervalListToBedTest.java    |   2 +-
 src/tests/java/picard/vcf/SortVcfsTest.java        |   1 -
 .../vcf/UpdateVcfSequenceDictionaryTest.java       |   5 -
 .../picard/vcf/{ => filter}/TestFilterVcf.java     |  41 ++++++
 .../vcf/processor/VcfFileSegmentGeneratorTest.java |   2 +-
 .../picard/sam/FilterSamReads/filterOddStarts.js   |   2 +
 .../filterReadsWithout5primeSoftClip.js            |  10 ++
 .../sam/summary_alignment_stats_test_chimeras.sam  |  22 +--
 70 files changed, 821 insertions(+), 346 deletions(-)

diff --git a/build.sbt b/build.sbt
index a2a67bf..e66a6e7 100644
--- a/build.sbt
+++ b/build.sbt
@@ -4,7 +4,7 @@ import sbt.Package.ManifestAttributes
 
 name := "picard"
 
-version := "2.1.0"
+version := "2.1.1"
 
 organization := "com.github.broadinstitute"
 
@@ -15,7 +15,7 @@ javaSource in Test := baseDirectory.value / "src/tests"
 unmanagedResourceDirectories in Test := Seq(baseDirectory.value / "src/scripts", baseDirectory.value / "testdata", baseDirectory.value / "src/tests/scripts")
 
 libraryDependencies ++= Seq(
-  "com.github.samtools" % "htsjdk" % "2.1.0",
+  "com.github.samtools" % "htsjdk" % "2.1.1",
   ("com.google.cloud.genomics" % "gatk-tools-java" % "1.1" % "picardopt").
     exclude("org.mortbay.jetty", "servlet-api"),
   "org.testng" % "testng" % "6.8.8" % Test
diff --git a/build.xml b/build.xml
index 9568f5c..b985cd9 100755
--- a/build.xml
+++ b/build.xml
@@ -53,7 +53,7 @@
         <arg value="--pretty=format:%H_%at"/>
     </exec>
     <property name="repository.revision" value=""/>
-    <property name="picard-version" value="2.1.0"/>
+    <property name="picard-version" value="2.1.1"/>
     <property name="command-line-html-dir" value="${dist}/html"/>
     <property name="testng.verbosity" value="2"/>
     <property name="test.debug.port" value="5005"/>
@@ -93,8 +93,8 @@
                 <include name="**/*.jar"/>
             </fileset>
             <fileset dir="${lib}">
-        	    <include name="**/*.jar"/>
-        	  </fileset>
+                <include name="**/*.jar"/>
+            </fileset>
         </path>
         <path id="metrics.classpath">
             <pathelement path="${classpath}"/>
@@ -199,20 +199,20 @@
     <target name="test" depends="compile, set_excluded_test_groups" description="Run unit tests">
         <taskdef resource="testngtasks" classpathref="classpath"/>
         <jacoco:coverage destfile="jacoco.data" xmlns:jacoco="antlib:org.jacoco.ant">
-        <testng suitename="picard-tests" classpathref="classpath" outputdir="${test.output}"
-                failureproperty="tests.failed" excludedgroups="${excludedTestGroups}" workingDir="${basedir}"
-                verbose="${testng.verbosity}">
-            <classpath>
-                <pathelement path="${classes}"/>
-                <pathelement path="${classes.test}"/>
-                <pathelement path="${scripts}"/>
-            </classpath>
-            <classfileset dir="${classes.test}">
-                <include name="**/Test*.class"/>
-                <include name="**/*Test.class"/>
-            </classfileset>
-            <jvmarg value="-Xmx2G"/>
-        </testng>
+            <testng suitename="picard-tests" classpathref="classpath" outputdir="${test.output}"
+                    failureproperty="tests.failed" excludedgroups="${excludedTestGroups}" workingDir="${basedir}"
+                    verbose="${testng.verbosity}">
+                <classpath>
+                    <pathelement path="${classes}"/>
+                    <pathelement path="${classes.test}"/>
+                    <pathelement path="${scripts}"/>
+                </classpath>
+                <classfileset dir="${classes.test}">
+                    <include name="**/Test*.class"/>
+                    <include name="**/*Test.class"/>
+                </classfileset>
+                <jvmarg value="-Xmx2G"/>
+            </testng>
         </jacoco:coverage>
 
         <junitreport todir="${dist}/test">
@@ -227,18 +227,18 @@
 
     <target name="test-coverage-report" depends="test" description="Runs tests and creates an HTML code coverage report">
         <jacoco:report xmlns:jacoco="antlib:org.jacoco.ant">
-        <executiondata>
-           <file file="jacoco.data"/>
-        </executiondata>
-        <structure name="Picard">
-          <classfiles>
-            <fileset dir="classes"/>
-          </classfiles>
-          <sourcefiles encoding="UTF-8">
-            <fileset dir="src"/>
-          </sourcefiles>
-        </structure>
-        <html destdir="report"/>
+            <executiondata>
+                <file file="jacoco.data"/>
+            </executiondata>
+            <structure name="Picard">
+                <classfiles>
+                    <fileset dir="classes"/>
+                </classfiles>
+                <sourcefiles encoding="UTF-8">
+                    <fileset dir="src"/>
+                </sourcefiles>
+            </structure>
+            <html destdir="report"/>
         </jacoco:report>
     </target>
 
@@ -269,40 +269,40 @@
 
     <target name="process-external-jars" depends="clean-jar-opt, maybe-add-gatk-tools-java">
     </target>
-	
-	  <target name="clean-jar-opt">
-      <delete dir="${jar_opt}"/>
-	  	<mkdir dir="${jar_opt}"/>
+
+    <target name="clean-jar-opt">
+        <delete dir="${jar_opt}"/>
+        <mkdir dir="${jar_opt}"/>
     </target>
-	
-	  <target name="maybe-add-gatk-tools-java" if="addGATKToolsJava">
-    	<mkdir dir="${jar_opt}"/>
-      <unzip dest="${jar_opt}">
-    	  <fileset dir="${lib}/gatk-tools-java">
-    	    <include name="*.jar"/>
-    	  </fileset>
-    	</unzip>
+
+    <target name="maybe-add-gatk-tools-java" if="addGATKToolsJava">
+        <mkdir dir="${jar_opt}"/>
+        <unzip dest="${jar_opt}">
+            <fileset dir="${lib}/gatk-tools-java">
+                <include name="*.jar"/>
+            </fileset>
+        </unzip>
     </target>
-	
+
     <target name="picard-jar" depends="compile, process-external-jars"
-        description="Builds the main executable picard.jar">
-       <mkdir dir="${dist}"/>
-       <mkdir dir="${dist.tmp}"/>
-       <unjar dest="${dist.tmp}">
-           <fileset dir="${lib}">
-               <exclude name="**/jacocoant.jar"/> <!-- must exclude this jar from packing into picard - this is only used for testing -->
-           </fileset>
-           <fileset dir="${htsjdk_lib_dir}">
-               <include name="*.jar"/>
-           </fileset>
-       </unjar>
+            description="Builds the main executable picard.jar">
+        <mkdir dir="${dist}"/>
+        <mkdir dir="${dist.tmp}"/>
+        <unjar dest="${dist.tmp}">
+            <fileset dir="${lib}">
+                <exclude name="**/jacocoant.jar"/> <!-- must exclude this jar from packing into picard - this is only used for testing -->
+            </fileset>
+            <fileset dir="${htsjdk_lib_dir}">
+                <include name="*.jar"/>
+            </fileset>
+        </unjar>
 
         <jar destfile="${dist}/picard.jar" compress="no">
             <fileset dir="${classes}" includes="picard/**/*.*, META-INF/**/*"/>
             <fileset dir="${src.scripts}" includes="**/*.R"/>
             <fileset dir="${htsjdk-classes}" includes ="${htsjdk}/*/**/*.*"/>
             <fileset dir="${dist.tmp}" includes="**/*"/>
-	          <fileset dir="${jar_opt}" includes="**/*"/>
+            <fileset dir="${jar_opt}" includes="**/*"/>
 
             <manifest>
                 <attribute name="Implementation-Version" value="${picard-version}(${repository.revision})"/>
@@ -317,7 +317,7 @@
     </target>
 
     <target name="picard-lib-jar" depends="compile"
-        description="Builds the library: picard-lib.jar">
+            description="Builds the library: picard-lib.jar">
         <mkdir dir="${dist}"/>
         <jar destfile="${dist}/picard-lib.jar" compress="no">
             <fileset dir="${classes}" includes="picard/**/*.*"/>
@@ -409,33 +409,49 @@
     </target>
 
     <target name="add-ga4gh-support">
-    	<property name="addGATKToolsJava" value="1"/>	
+        <property name="addGATKToolsJava" value="1"/>
     </target>
 
-	  <target name="package-commands-ga4gh" depends="add-ga4gh-support, compile, picard-jar" />
-	
+    <target name="package-commands-ga4gh" depends="add-ga4gh-support, compile, picard-jar" />
+
     <target name="package-commands" depends="compile, picard-jar">
         <delete dir="${command-line-html-dir}"/>
         <!-- If you don't want to generate on-line doc for a command, use package-command instead of document-command -->
         <document-command title="AddCommentsToBam"                  main-class="picard.sam.AddCommentsToBam"/>
         <document-command title="AddOrReplaceReadGroups"            main-class="picard.sam.AddOrReplaceReadGroups"/>
+        <document-command title="BaitDesigner"                      main-class="picard.util.BaitDesigner"/>
         <document-command title="BamToBfq"                          main-class="picard.fastq.BamToBfq"/>
         <document-command title="BamIndexStats"                     main-class="picard.sam.BamIndexStats"/>
         <document-command title="BedToIntervalList"                 main-class="picard.util.BedToIntervalList"/>
         <document-command title="BuildBamIndex"                     main-class="picard.sam.BuildBamIndex"/>
         <document-command title="CalculateHsMetrics"                main-class="picard.analysis.directed.CalculateHsMetrics"/>
+        <document-command title="CollectHsMetrics"                  main-class="picard.analysis.directed.CollectHsMetrics"/>
+        <document-command title="CalculateReadGroupChecksum"        main-class="picard.sam.CalculateReadGroupChecksum"/>
         <document-command title="CleanSam"                          main-class="picard.sam.CleanSam"/>
         <document-command title="CollectAlignmentSummaryMetrics"    main-class="picard.analysis.CollectAlignmentSummaryMetrics"/>
         <document-command title="CollectBaseDistributionByCycle"    main-class="picard.analysis.CollectBaseDistributionByCycle"/>
         <document-command title="CollectGcBiasMetrics"              main-class="picard.analysis.CollectGcBiasMetrics"/>
+        <document-command title="CollectHiSeqXPfFailMetrics"        main-class="picard.illumina.quality.CollectHiSeqXPfFailMetrics"/>
         <document-command title="CollectHsMetrics"                  main-class="picard.analysis.directed.CollectHsMetrics"/>
+        <document-command title="CollectIlluminaBasecallingMetrics" main-class="picard.illumina.CollectIlluminaBasecallingMetrics"/>
+        <document-command title="CollectIlluminaLaneMetrics"        main-class="picard.illumina.CollectIlluminaLaneMetrics"/>
         <document-command title="CollectInsertSizeMetrics"          main-class="picard.analysis.CollectInsertSizeMetrics"/>
+        <document-command title="CollectJumpingLibraryMetrics"      main-class="picard.analysis.CollectJumpingLibraryMetrics"/>
         <document-command title="CollectMultipleMetrics"            main-class="picard.analysis.CollectMultipleMetrics"/>
+        <document-command title="CollectOxoGMetrics"                main-class="picard.analysis.CollectOxoGMetrics"/>
+        <document-command title="CollectQualityYieldMetrics"        main-class="picard.analysis.CollectQualityYieldMetrics"/>
+        <document-command title="CollectRawWgsMetrics"              main-class="picard.analysis.CollectRawWgsMetrics"/>
         <document-command title="CollectTargetedPcrMetrics"         main-class="picard.analysis.directed.CollectTargetedPcrMetrics"/>
         <document-command title="CollectRnaSeqMetrics"              main-class="picard.analysis.CollectRnaSeqMetrics"/>
+        <document-command title="CollectRrbsMetrics"                main-class="picard.analysis.CollectRrbsMetrics"/>
+        <document-command title="CollectSequencingArtifactMetrics"  main-class="picard.analysis.artifacts.CollectSequencingArtifactMetrics"/>
         <document-command title="CollectVariantCallingMetrics"      main-class="picard.vcf.CollectVariantCallingMetrics"/>
         <document-command title="CollectWgsMetrics"                 main-class="picard.analysis.CollectWgsMetrics"/>
+        <document-command title="CollectWgsMetricsFromQuerySorted"  main-class="picard.analysis.CollectWgsMetricsFromQuerySorted"/>
+        <document-command title="CollectWgsMetricsFromSampledSites" main-class="picard.analysis.CollectWgsMetricsFromSampledSites"/>
+        <document-command title="CompareMetrics"                    main-class="picard.analysis.CompareMetrics"/>
         <document-command title="CompareSAMs"                       main-class="picard.sam.CompareSAMs"/>
+        <document-command title="ConvertSequencingArtifactToOxoG"   main-class="picard.analysis.artifacts.ConvertSequencingArtifactToOxoG"/>
         <document-command title="CreateSequenceDictionary"          main-class="picard.sam.CreateSequenceDictionary"/>
         <document-command title="DownsampleSam"                     main-class="picard.sam.DownsampleSam"/>
         <document-command title="ExtractIlluminaBarcodes"           main-class="picard.illumina.ExtractIlluminaBarcodes"/>
@@ -451,7 +467,9 @@
         <document-command title="IlluminaBasecallsToFastq"          main-class="picard.illumina.IlluminaBasecallsToFastq"/>
         <document-command title="IlluminaBasecallsToSam"            main-class="picard.illumina.IlluminaBasecallsToSam"/>
         <document-command title="CheckIlluminaDirectory"            main-class="picard.illumina.CheckIlluminaDirectory"/>
+        <document-command title="CheckTerminatorBlock"              main-class="picard.sam.CheckTerminatorBlock"/>
         <document-command title="IntervalListTools"                 main-class="picard.util.IntervalListTools"/>
+        <document-command title="LiftOverIntervalList"              main-class="picard.util.LiftOverIntervalList"/>
         <document-command title="LiftoverVcf"                       main-class="picard.vcf.LiftoverVcf"/>
         <document-command title="MakeSitesOnlyVcf"                  main-class="picard.vcf.MakeSitesOnlyVcf"/>
         <document-command title="MarkDuplicates"                    main-class="picard.sam.markduplicates.MarkDuplicates"/>
@@ -461,17 +479,20 @@
         <document-command title="MergeSamFiles"                     main-class="picard.sam.MergeSamFiles"/>
         <document-command title="MergeVcfs"                         main-class="picard.vcf.MergeVcfs"/>
         <document-command title="NormalizeFasta"                    main-class="picard.reference.NormalizeFasta"/>
+        <document-command title="PositionBasedDownsampleSam"        main-class="picard.sam.PositionBasedDownsampleSam"/>
         <document-command title="ExtractSequences"                  main-class="picard.reference.ExtractSequences"/>
         <document-command title="QualityScoreDistribution"          main-class="picard.analysis.QualityScoreDistribution"/>
+        <document-command title="RenameSampleInVcf"                 main-class="picard.vcf.RenameSampleInVcf"/>
         <document-command title="ReorderSam"                        main-class="picard.sam.ReorderSam"/>
         <document-command title="ReplaceSamHeader"                  main-class="picard.sam.ReplaceSamHeader"/>
         <document-command title="RevertSam"                         main-class="picard.sam.RevertSam"/>
-        <document-command title="RevertOriginalBaseQualitiesAndAddMateCigar"
-                                                                   main-class="picard.sam.RevertOriginalBaseQualitiesAndAddMateCigar"/>
+        <document-command title="RevertOriginalBaseQualitiesAndAddMateCigar"    main-class="picard.sam.RevertOriginalBaseQualitiesAndAddMateCigar"/>
         <document-command title="SamFormatConverter"                main-class="picard.sam.SamFormatConverter"/>
         <document-command title="SamToFastq"                        main-class="picard.sam.SamToFastq"/>
+        <document-command title="ScatterIntervalsByNs"              main-class="picard.util.ScatterIntervalsByNs"/>
         <document-command title="SortSam"                           main-class="picard.sam.SortSam"/>
         <document-command title="SortVcf"                           main-class="picard.vcf.SortVcf"/>
+        <document-command title="SplitSamByLibrary"                 main-class="picard.sam.SplitSamByLibrary"/>
         <document-command title="UpdateVcfSequenceDictionary"       main-class="picard.vcf.UpdateVcfSequenceDictionary"/>
         <document-command title="VcfFormatConverter"                main-class="picard.vcf.VcfFormatConverter"/>
         <document-command title="MarkIlluminaAdapters"              main-class="picard.illumina.MarkIlluminaAdapters"/>
@@ -508,9 +529,10 @@
             <java classname="picard.cmdline.CreateHtmlDocForStandardOptions"
                   output="${command-line-html-dir}/program_usage/standard-options.html"
                   failonerror="true">
-                <classpath>
-                    <pathelement location="${dist}/picard.jar"/>
-                </classpath>
+                  <classpath>
+                      <path refid="classpath"/>
+                      <pathelement location="${classes}"/>
+                  </classpath>
             </java>
         </sequential>
     </target>
@@ -529,9 +551,10 @@
             <java classname="picard.cmdline.CreateHtmlDocForProgram"
                   output="${command-line-html-dir}/program_usage/@{title}.html"
                   failonerror="true">
-                <classpath>
-                    <pathelement location="${dist}/picard.jar"/>
-                </classpath>
+                  <classpath>
+                      <path refid="classpath"/>
+                      <pathelement location="${classes}"/>
+                  </classpath>
                 <arg value="@{main-class}"/>
             </java>
 
diff --git a/src/java/picard/Test.java b/src/java/picard/Test.java
index c0ac40e..ab82c64 100644
--- a/src/java/picard/Test.java
+++ b/src/java/picard/Test.java
@@ -9,7 +9,7 @@ import java.util.StringTokenizer;
  *
  */
 public class Test {
-    private final String text = "C0A69ACXX111213:6:1101:10000:144257\t83\t5\t128984606\t60\t76M\t=\t128984542\t-140\tAGTGTTAGAACTTCCTCCCCAAAGCATATACTTCAGTGGCAAGCTGTCCTGGATGAAGGTATGACCAACCAGATCA\t at FFFEECC>EFHBJIGIFGIEIJJJIHED<IEHIGIIJIIIGJIGJIIIIIJGGCJIIGIHHHBHGHFFDFFFC@@\tXT:A:U\tNM:i:0\tSM:i:37\tAM:i:37\tX0:i:1\tX1:i:0\tXM:i:0\tXO:i:0\tXG:i:0\tMD:Z:76";
+    private static final String TEXT = "C0A69ACXX111213:6:1101:10000:144257\t83\t5\t128984606\t60\t76M\t=\t128984542\t-140\tAGTGTTAGAACTTCCTCCCCAAAGCATATACTTCAGTGGCAAGCTGTCCTGGATGAAGGTATGACCAACCAGATCA\t at FFFEECC>EFHBJIGIFGIEIJJJIHED<IEHIGIIJIIIGJIGJIIIIIJGGCJIIGIHHHBHGHFFDFFFC@@\tXT:A:U\tNM:i:0\tSM:i:37\tAM:i:37\tX0:i:1\tX1:i:0\tXM:i:0\tXO:i:0\tXG:i:0\tMD:Z:76";
 
     public static void main(String[] args) {
         new Test().run();
@@ -22,7 +22,7 @@ public class Test {
 
         watch.start();
         for (int i=0; i<ITERATIONS; ++i) {
-            if (StringUtil.split(text, fields, '\t') > 100) {
+            if (StringUtil.split(TEXT, fields, '\t') > 100) {
                 System.out.println("Mama Mia that's a lot of tokens!!");
             }
         }
@@ -32,7 +32,7 @@ public class Test {
         
         watch.start();
         for (int i=0; i<ITERATIONS; ++i) {
-            if (split(text, fields, "\t") > 100) {
+            if (split(TEXT, fields, "\t") > 100) {
                 System.out.println("Mama Mia that's a lot of tokens!!");
             }
         }
diff --git a/src/java/picard/analysis/CollectGcBiasMetrics.java b/src/java/picard/analysis/CollectGcBiasMetrics.java
index a122731..46008bb 100644
--- a/src/java/picard/analysis/CollectGcBiasMetrics.java
+++ b/src/java/picard/analysis/CollectGcBiasMetrics.java
@@ -63,7 +63,7 @@ public class CollectGcBiasMetrics extends SinglePassSamProgram {
             " nucleotides in a sample.  Regions of high and low G + C content have been shown to interfere with mapping/aligning," +
             " ultimately leading to fragmented genome assemblies and poor coverage in a phenomenon known as \"GC bias\".  " +
             "Detailed information on the effects of GC bias on the collection and analysis of sequencing data can be found at " +
-            "DOI: 10.1371/journal.pone.0062856/.<br /><br />." +
+            "DOI: 10.1371/journal.pone.0062856/.<br /><br />" +
             "" +
             "The GC bias statistics are always output in a detailed long-form version, but a summary can also be produced. Both the " +
             "detailed metrics and the summary metrics are output as tables (\".txt\" files) and an accompanying chart that plots the " +
@@ -85,7 +85,7 @@ public class CollectGcBiasMetrics extends SinglePassSamProgram {
             "AT_DROPOUT, and GC_DROPOUT.  While WINDOW_SIZE refers to the numbers of bases used for the distribution (see above), the " +
             "ALIGNED_READS and TOTAL_CLUSTERS are the total number of aligned reads and the total number of reads (after filtering) " +
             "produced in a run. In addition, the tool produces both AT_DROPOUT and GC_DROPOUT metrics, which indicate the percentage of " +
-            "misaligned reads that correlate with low (%-GC is < 50%) or high (%-GC is > 50%) GC content respectively.  <br /><br />" +
+            "misaligned reads that correlate with low (%-GC is < 50%) or high (%-GC is > 50%) GC content respectively.  <br /><br />" +
             "" +
             "The percentage of \"coverage\" or depth in a GC bin is calculated by dividing the number of reads of a particular GC content " +
             "by the mean number of reads of all GC bins.  A number of 1 represents mean coverage, a number less than 1 represents lower " +
diff --git a/src/java/picard/analysis/CollectMultipleMetrics.java b/src/java/picard/analysis/CollectMultipleMetrics.java
index c0694f4..ab7fd11 100644
--- a/src/java/picard/analysis/CollectMultipleMetrics.java
+++ b/src/java/picard/analysis/CollectMultipleMetrics.java
@@ -86,7 +86,7 @@ public class CollectMultipleMetrics extends CommandLineProgram {
             "</pre>" +
             "<hr />";
     public static interface ProgramInterface {
-        SinglePassSamProgram makeInstance(final String outbase, final File input, final File reference,
+        SinglePassSamProgram makeInstance(final String outbase, final String outext, final File input, final File reference,
             final Set<MetricAccumulationLevel> metricAccumulationLevel, final File dbSnp, final File intervals);
         public boolean needsReferenceSequence();
         public boolean supportsMetricAccumulationLevel();
@@ -103,9 +103,9 @@ public class CollectMultipleMetrics extends CommandLineProgram {
                 return true;
             }
             @Override
-            public SinglePassSamProgram makeInstance(final String outbase, final File input, final File reference, final Set<MetricAccumulationLevel> metricAccumulationLevel, final File dbSnp, final File intervals) {
+            public SinglePassSamProgram makeInstance(final String outbase, final String outext, final File input, final File reference, final Set<MetricAccumulationLevel> metricAccumulationLevel, final File dbSnp, final File intervals) {
                 final CollectAlignmentSummaryMetrics program = new CollectAlignmentSummaryMetrics();
-                program.OUTPUT = new File(outbase + ".alignment_summary_metrics");
+                program.OUTPUT = new File(outbase + ".alignment_summary_metrics" + outext);
 
                 // Generally programs should not be accessing these directly but it might make things smoother
                 // to just set them anyway. These are set here to make sure that in case of a the derived class
@@ -127,9 +127,9 @@ public class CollectMultipleMetrics extends CommandLineProgram {
                 return true;
             }
             @Override
-            public SinglePassSamProgram makeInstance(final String outbase, final File input, final File reference, final Set<MetricAccumulationLevel> metricAccumulationLevel, final File dbSnp, final File intervals) {
+            public SinglePassSamProgram makeInstance(final String outbase, final String outext, final File input, final File reference, final Set<MetricAccumulationLevel> metricAccumulationLevel, final File dbSnp, final File intervals) {
                 final CollectInsertSizeMetrics program = new CollectInsertSizeMetrics();
-                program.OUTPUT = new File(outbase + ".insert_size_metrics");
+                program.OUTPUT = new File(outbase + ".insert_size_metrics" + outext);
                 program.Histogram_FILE = new File(outbase + ".insert_size_histogram.pdf");
                 // Generally programs should not be accessing these directly but it might make things smoother
                 // to just set them anyway. These are set here to make sure that in case of a the derived class
@@ -151,9 +151,9 @@ public class CollectMultipleMetrics extends CommandLineProgram {
                 return false;
             }
             @Override
-            public SinglePassSamProgram makeInstance(final String outbase, final File input, final File reference, final Set<MetricAccumulationLevel> metricAccumulationLevel, final File dbSnp, final File intervals) {
+            public SinglePassSamProgram makeInstance(final String outbase, final String outext, final File input, final File reference, final Set<MetricAccumulationLevel> metricAccumulationLevel, final File dbSnp, final File intervals) {
                 final QualityScoreDistribution program = new QualityScoreDistribution();
-                program.OUTPUT = new File(outbase + ".quality_distribution_metrics");
+                program.OUTPUT = new File(outbase + ".quality_distribution_metrics" + outext);
                 program.CHART_OUTPUT = new File(outbase + ".quality_distribution.pdf");
                 // Generally programs should not be accessing these directly but it might make things smoother
                 // to just set them anyway. These are set here to make sure that in case of a the derived class
@@ -174,9 +174,9 @@ public class CollectMultipleMetrics extends CommandLineProgram {
                 return false;
             }
             @Override
-            public SinglePassSamProgram makeInstance(final String outbase, final File input, final File reference, final Set<MetricAccumulationLevel> metricAccumulationLevel, final File dbSnp, final File intervals) {
+            public SinglePassSamProgram makeInstance(final String outbase, final String outext, final File input, final File reference, final Set<MetricAccumulationLevel> metricAccumulationLevel, final File dbSnp, final File intervals) {
                 final MeanQualityByCycle program = new MeanQualityByCycle();
-                program.OUTPUT = new File(outbase + ".quality_by_cycle_metrics");
+                program.OUTPUT = new File(outbase + ".quality_by_cycle_metrics" + outext);
                 program.CHART_OUTPUT = new File(outbase + ".quality_by_cycle.pdf");
                 // Generally programs should not be accessing these directly but it might make things smoother
                 // to just set them anyway. These are set here to make sure that in case of a the derived class
@@ -197,9 +197,9 @@ public class CollectMultipleMetrics extends CommandLineProgram {
                 return false;
             }
             @Override
-            public SinglePassSamProgram makeInstance(final String outbase, final File input, final File reference, final Set<MetricAccumulationLevel> metricAccumulationLevel, final File dbSnp, final File intervals) {
+            public SinglePassSamProgram makeInstance(final String outbase, final String outext, final File input, final File reference, final Set<MetricAccumulationLevel> metricAccumulationLevel, final File dbSnp, final File intervals) {
                 final CollectBaseDistributionByCycle program = new CollectBaseDistributionByCycle();
-                program.OUTPUT = new File(outbase + ".base_distribution_by_cycle_metrics");
+                program.OUTPUT = new File(outbase + ".base_distribution_by_cycle_metrics" + outext);
                 program.CHART_OUTPUT = new File(outbase + ".base_distribution_by_cycle.pdf");
                 // Generally programs should not be accessing these directly but it might make things smoother
                 // to just set them anyway. These are set here to make sure that in case of a the derived class
@@ -220,10 +220,10 @@ public class CollectMultipleMetrics extends CommandLineProgram {
                 return true;
             }
             @Override
-            public SinglePassSamProgram makeInstance(final String outbase, final File input, final File reference, final Set<MetricAccumulationLevel> metricAccumulationLevel, final File dbSnp, final File intervals) {
+            public SinglePassSamProgram makeInstance(final String outbase, final String outext, final File input, final File reference, final Set<MetricAccumulationLevel> metricAccumulationLevel, final File dbSnp, final File intervals) {
                 final CollectGcBiasMetrics program = new CollectGcBiasMetrics();
-                program.OUTPUT = new File(outbase + ".gc_bias.detail_metrics");
-                program.SUMMARY_OUTPUT = new File(outbase + ".gc_bias.summary_metrics");
+                program.OUTPUT = new File(outbase + ".gc_bias.detail_metrics" + outext);
+                program.SUMMARY_OUTPUT = new File(outbase + ".gc_bias.summary_metrics" + outext);
                 program.CHART_OUTPUT = new File(outbase + ".gc_bias.pdf");
 
                 program.INPUT = input;
@@ -250,9 +250,9 @@ public class CollectMultipleMetrics extends CommandLineProgram {
                 return true;
             }
             @Override
-            public SinglePassSamProgram makeInstance(final String outbase, final File input, final File reference, final Set<MetricAccumulationLevel> metricAccumulationLevel, final File dbSnp, final File intervals) {
+            public SinglePassSamProgram makeInstance(final String outbase, final String outext, final File input, final File reference, final Set<MetricAccumulationLevel> metricAccumulationLevel, final File dbSnp, final File intervals) {
                 final CollectRnaSeqMetrics program = new CollectRnaSeqMetrics();
-                program.OUTPUT       = new File(outbase + ".rna_metrics");
+                program.OUTPUT       = new File(outbase + ".rna_metrics" + outext);
                 program.CHART_OUTPUT = new File(outbase + ".rna_coverage.pdf");
                 // Generally programs should not be accessing these directly but it might make things smoother
                 // to just set them anyway. These are set here to make sure that in case of a the derived class
@@ -272,9 +272,10 @@ public class CollectMultipleMetrics extends CommandLineProgram {
             @Override
             public boolean supportsMetricAccumulationLevel() { return false; }
             @Override
-            public SinglePassSamProgram makeInstance(final String outbase, final File input, final File reference, final Set<MetricAccumulationLevel> metricAccumulationLevel, final File dbSnp, final File intervals) {
+            public SinglePassSamProgram makeInstance(final String outbase, final String outext, final File input, final File reference, final Set<MetricAccumulationLevel> metricAccumulationLevel, final File dbSnp, final File intervals) {
                 final CollectSequencingArtifactMetrics program = new CollectSequencingArtifactMetrics();
                 program.OUTPUT = new File(outbase);
+                program.FILE_EXTENSION = outext;
                 program.DB_SNP = dbSnp;
                 program.INTERVALS = intervals;
                 // Generally programs should not be accessing these directly but it might make things smoother
@@ -295,9 +296,9 @@ public class CollectMultipleMetrics extends CommandLineProgram {
                 return false;
             }
             @Override
-            public SinglePassSamProgram makeInstance(final String outbase, final File input, final File reference, final Set<MetricAccumulationLevel> metricAccumulationLevel, final File dbSnp, final File intervals) {
+            public SinglePassSamProgram makeInstance(final String outbase, final String outext, final File input, final File reference, final Set<MetricAccumulationLevel> metricAccumulationLevel, final File dbSnp, final File intervals) {
                 final CollectQualityYieldMetrics program = new CollectQualityYieldMetrics();
-                program.OUTPUT = new File(outbase + ".quality_yield_metrics");
+                program.OUTPUT = new File(outbase + ".quality_yield_metrics" + outext);
                 // Generally programs should not be accessing these directly but it might make things smoother
                 // to just set them anyway. These are set here to make sure that in case of a the derived class
                 // overrides
@@ -387,10 +388,9 @@ public class CollectMultipleMetrics extends CommandLineProgram {
                 log.warn("The " + program.toString() + " program does not support a metric accumulation level, but METRIC_ACCUMULATION_LEVEL" +
                         " was overridden in the command line. " + program.toString() + " will be run against the entire input.");
             }
-            final SinglePassSamProgram instance = program.makeInstance(OUTPUT, INPUT, REFERENCE_SEQUENCE, METRIC_ACCUMULATION_LEVEL, DB_SNP, INTERVALS);
 
-            // Add a file extension if desired
-            if (null != FILE_EXTENSION && !FILE_EXTENSION.isEmpty()) instance.OUTPUT = new File(instance.OUTPUT.getAbsolutePath() + FILE_EXTENSION);
+            final String outext = (null != FILE_EXTENSION) ? FILE_EXTENSION : ""; // Add a file extension if desired
+            final SinglePassSamProgram instance = program.makeInstance(OUTPUT, outext, INPUT, REFERENCE_SEQUENCE, METRIC_ACCUMULATION_LEVEL, DB_SNP, INTERVALS);
 
             // Generally programs should not be accessing these directly but it might make things smoother
             // to just set them anyway
diff --git a/src/java/picard/analysis/CollectRrbsMetrics.java b/src/java/picard/analysis/CollectRrbsMetrics.java
index f99bc0c..db175c5 100644
--- a/src/java/picard/analysis/CollectRrbsMetrics.java
+++ b/src/java/picard/analysis/CollectRrbsMetrics.java
@@ -186,7 +186,7 @@ private static final String R_SCRIPT = "picard/analysis/rrbsQc.R";
     }
 
     private boolean isSequenceFiltered(final String sequenceName) {
-        return (SEQUENCE_NAMES != null) && (SEQUENCE_NAMES.size() > 0) && (!SEQUENCE_NAMES.contains(sequenceName));
+        return (SEQUENCE_NAMES != null) && (!SEQUENCE_NAMES.isEmpty()) && (!SEQUENCE_NAMES.contains(sequenceName));
     }
 
     private void assertIoFiles(final File summaryFile, final File detailsFile, final File plotsFile) {
@@ -216,6 +216,6 @@ private static final String R_SCRIPT = "picard/analysis/rrbsQc.R";
             errorMsgs.add("MINIMUM_READ_LENGTH must be > 0");
         }
 
-        return errorMsgs.size() == 0 ? null : errorMsgs.toArray(new String[errorMsgs.size()]);
+        return errorMsgs.isEmpty() ? null : errorMsgs.toArray(new String[errorMsgs.size()]);
     }
 }
diff --git a/src/java/picard/analysis/GcBiasMetricsCollector.java b/src/java/picard/analysis/GcBiasMetricsCollector.java
index 79659b2..e372da6 100644
--- a/src/java/picard/analysis/GcBiasMetricsCollector.java
+++ b/src/java/picard/analysis/GcBiasMetricsCollector.java
@@ -89,9 +89,9 @@ public class GcBiasMetricsCollector extends MultiLevelCollector<GcBiasMetrics, I
     /////////////////////////////////////////////////////////////////////////////
     public class PerUnitGcBiasMetricsCollector implements PerUnitMetricCollector<GcBiasMetrics, Integer, GcBiasCollectorArgs> {
         Map<String, GcObject> gcData = new HashMap<String, GcObject>();
-        private String sample = null;
-        private String library = null;
-        private String readGroup = null;
+        private final String sample;
+        private final String library;
+        private final String readGroup;
         private static final String allReads = "All_Reads";
 
         /////////////////////////////////////////////////////////////////////////////
diff --git a/src/java/picard/analysis/MeanQualityByCycle.java b/src/java/picard/analysis/MeanQualityByCycle.java
index 13c67c2..15872b9 100644
--- a/src/java/picard/analysis/MeanQualityByCycle.java
+++ b/src/java/picard/analysis/MeanQualityByCycle.java
@@ -97,7 +97,7 @@ public class MeanQualityByCycle extends SinglePassSamProgram {
         System.exit(new MeanQualityByCycle().instanceMain(args));
     }
 
-    private static class HistogramGenerator {
+    private static final class HistogramGenerator {
         final boolean useOriginalQualities;
         int maxLengthSoFar = 0;
         double[] firstReadTotalsByCycle  = new double[maxLengthSoFar];
diff --git a/src/java/picard/analysis/artifacts/CollectSequencingArtifactMetrics.java b/src/java/picard/analysis/artifacts/CollectSequencingArtifactMetrics.java
index 59451e5..58dd32b 100644
--- a/src/java/picard/analysis/artifacts/CollectSequencingArtifactMetrics.java
+++ b/src/java/picard/analysis/artifacts/CollectSequencingArtifactMetrics.java
@@ -120,6 +120,9 @@ public class CollectSequencingArtifactMetrics extends SinglePassSamProgram {
                   "However, the summary metrics output will still take all contexts into consideration.")
     public Set<String> CONTEXTS_TO_PRINT = new HashSet<String>();
 
+    @Option(shortName = "EXT", doc="Append the given file extension to all metric file names (ex. OUTPUT.pre_adapter_summary_metrics.EXT). None if null", optional=true)
+    public String FILE_EXTENSION = null;
+
     private static final String UNKNOWN_LIBRARY = "UnknownLibrary";
     private static final String UNKNOWN_SAMPLE = "UnknownSample";
 
@@ -166,10 +169,11 @@ public class CollectSequencingArtifactMetrics extends SinglePassSamProgram {
 
     @Override
     protected void setup(final SAMFileHeader header, final File samFile) {
-        preAdapterSummaryOut = new File(OUTPUT + SequencingArtifactMetrics.PRE_ADAPTER_SUMMARY_EXT);
-        preAdapterDetailsOut = new File(OUTPUT + SequencingArtifactMetrics.PRE_ADAPTER_DETAILS_EXT);
-        baitBiasSummaryOut = new File(OUTPUT + SequencingArtifactMetrics.BAIT_BIAS_SUMMARY_EXT);
-        baitBiasDetailsOut = new File(OUTPUT + SequencingArtifactMetrics.BAIT_BIAS_DETAILS_EXT);
+        final String outext = (null != FILE_EXTENSION) ? FILE_EXTENSION : ""; // Add a file extension if desired
+        preAdapterSummaryOut = new File(OUTPUT + SequencingArtifactMetrics.PRE_ADAPTER_SUMMARY_EXT + outext);
+        preAdapterDetailsOut = new File(OUTPUT + SequencingArtifactMetrics.PRE_ADAPTER_DETAILS_EXT + outext);
+        baitBiasSummaryOut = new File(OUTPUT + SequencingArtifactMetrics.BAIT_BIAS_SUMMARY_EXT + outext);
+        baitBiasDetailsOut = new File(OUTPUT + SequencingArtifactMetrics.BAIT_BIAS_DETAILS_EXT + outext);
 
         IOUtil.assertFileIsWritable(preAdapterSummaryOut);
         IOUtil.assertFileIsWritable(preAdapterDetailsOut);
@@ -302,12 +306,12 @@ public class CollectSequencingArtifactMetrics extends SinglePassSamProgram {
             baitBiasSummaryMetricsFile.addAllMetrics(counter.getBaitBiasSummaryMetrics());
 
             for (final PreAdapterDetailMetrics preAdapterDetailMetrics : counter.getPreAdapterDetailMetrics()) {
-                if (CONTEXTS_TO_PRINT.size() == 0 || CONTEXTS_TO_PRINT.contains(preAdapterDetailMetrics.CONTEXT)) {
+                if (CONTEXTS_TO_PRINT.isEmpty() || CONTEXTS_TO_PRINT.contains(preAdapterDetailMetrics.CONTEXT)) {
                     preAdapterDetailMetricsFile.addMetric(preAdapterDetailMetrics);
                 }
             }
             for (final BaitBiasDetailMetrics baitBiasDetailMetrics : counter.getBaitBiasDetailMetrics()) {
-                if (CONTEXTS_TO_PRINT.size() == 0 || CONTEXTS_TO_PRINT.contains(baitBiasDetailMetrics.CONTEXT)) {
+                if (CONTEXTS_TO_PRINT.isEmpty() || CONTEXTS_TO_PRINT.contains(baitBiasDetailMetrics.CONTEXT)) {
                     baitBiasDetailMetricsFile.addMetric(baitBiasDetailMetrics);
                 }
             }
diff --git a/src/java/picard/analysis/directed/TargetMetricsCollector.java b/src/java/picard/analysis/directed/TargetMetricsCollector.java
index 9e7d5c6..e318784 100644
--- a/src/java/picard/analysis/directed/TargetMetricsCollector.java
+++ b/src/java/picard/analysis/directed/TargetMetricsCollector.java
@@ -604,8 +604,8 @@ public abstract class TargetMetricsCollector<METRIC_TYPE extends MultilevelMetri
             double totalCoverage = 0;
 
             // The "how many bases at at-least X" calculations.
-            final int targetBasesDepth[] = {0, 1, 2, 10, 20, 30, 40, 50, 100}; // NB: this should be in ascending order
-            final int targetBases[] = new int[targetBasesDepth.length]; // counts for how many target bases are at at least X coverage, where X corresponds to the value at the same offset in targetBasesDepth
+            final int[] targetBasesDepth = {0, 1, 2, 10, 20, 30, 40, 50, 100}; // NB: this should be in ascending order
+            final int[] targetBases = new int[targetBasesDepth.length]; // counts for how many target bases are at at least X coverage, where X corresponds to the value at the same offset in targetBasesDepth
 
             // consider all bases in calculating the mean, median etc.
             for (final Coverage c : this.coverageByTarget.values()) {
diff --git a/src/java/picard/cmdline/CommandLineParser.java b/src/java/picard/cmdline/CommandLineParser.java
index 964cdb8..ee90b44 100644
--- a/src/java/picard/cmdline/CommandLineParser.java
+++ b/src/java/picard/cmdline/CommandLineParser.java
@@ -23,9 +23,11 @@
  */
 package picard.cmdline;
 
+import com.google.common.base.CharMatcher;
 import htsjdk.samtools.util.CloserUtil;
 import htsjdk.samtools.util.CollectionUtil.MultiMap;
 import htsjdk.samtools.util.StringUtil;
+import picard.PicardException;
 
 import java.io.BufferedReader;
 import java.io.File;
@@ -48,8 +50,8 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-
-import picard.PicardException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * Annotation-driven utility for parsing command-line arguments, checking for errors, and producing usage message.
@@ -177,19 +179,19 @@ public class CommandLineParser {
     private int maxPositionalArguments;
 
     // List of all the data members with @Option annotation
-    private final List<OptionDefinition> optionDefinitions = new ArrayList<OptionDefinition>();
+    private final List<OptionDefinition> optionDefinitions = new ArrayList<>();
 
     // Maps long name, and short name, if present, to an option definition that is
     // also in the optionDefinitions list.
-    private final Map<String, OptionDefinition> optionMap = new HashMap<String, OptionDefinition>();
+    private final Map<String, OptionDefinition> optionMap = new HashMap<>();
 
     // Maps child options prefix to CommandLineParser for the child object.
     // Key: option prefix.
-    private final Map<String, CommandLineParser> childOptionsMap = new LinkedHashMap<String, CommandLineParser>();
+    private final Map<String, CommandLineParser> childOptionsMap = new LinkedHashMap<>();
 
     // Holds the command-line arguments for a child option parser.
     // Key: option prefix.  Value: List of arguments for child corresponding to that prefix (with prefix stripped).
-    private final MultiMap<String, ChildOptionArg> childOptionArguments = new MultiMap<String, ChildOptionArg>();
+    private final MultiMap<String, ChildOptionArg> childOptionArguments = new MultiMap<>();
 
     // For printing error messages when parsing command line.
     private PrintStream messageStream;
@@ -230,9 +232,12 @@ public class CommandLineParser {
         } else {
             usagePreamble += defaultUsagePreambleWithPositionalArguments;
         }
+
         if (null != this.programVersion && 0 < this.programVersion.length()) {
             usagePreamble += "Version: " + getVersion() + "\n";
         }
+        //checkForNonASCII(usagePreamble, "preamble");
+
         return usagePreamble;
     }
 
@@ -281,7 +286,7 @@ public class CommandLineParser {
     }
 
     private static List<Field> getAllFields(Class clazz) {
-        final List<Field> ret = new ArrayList<Field>();
+        final List<Field> ret = new ArrayList<>();
         do {
             ret.addAll(Arrays.asList(clazz.getDeclaredFields()));
             clazz = clazz.getSuperclass();
@@ -299,8 +304,11 @@ public class CommandLineParser {
      * @param stream Where to write the usage message.
      */
     public void usage(final PrintStream stream, final boolean printCommon) {
+
         if (prefix.isEmpty()) {
-            stream.print(getStandardUsagePreamble(callerOptions.getClass()) + getUsagePreamble());
+            final String preamble = htmlUnescape(convertFromHtml(getStandardUsagePreamble(callerOptions.getClass()) + getUsagePreamble()));
+            checkForNonASCII(preamble, "Tool description");
+            stream.print(preamble);
             stream.println("\nVersion: " + getVersion());
             stream.println("\n\nOptions:\n");
 
@@ -310,9 +318,7 @@ public class CommandLineParser {
         }
 
         if (!optionDefinitions.isEmpty()) {
-            for (final OptionDefinition optionDefinition : optionDefinitions) {
-                if (printCommon || !optionDefinition.isCommon) printOptionUsage(stream, optionDefinition);
-            }
+            optionDefinitions.stream().filter(optionDefinition -> printCommon || !optionDefinition.isCommon).forEach(optionDefinition -> printOptionUsage(stream, optionDefinition));
         }
 
         if (printCommon) {
@@ -333,17 +339,43 @@ public class CommandLineParser {
         }
 
         // Generate usage for child parsers.
-        final Collection<CommandLineParser> childClps;
-        childClps = getChildParsersForHelp();
-        for (final CommandLineParser childClp : childClps) {
-            childClp.usage(stream, printCommon);
+        getChildParsersForHelp()
+                .stream()
+                .forEach(childClp -> childClp.usage(stream, printCommon));
+    }
+
+    static void checkForNonASCII(String documentationText, String location) {
+        if (!CharMatcher.ASCII.matchesAllOf(documentationText)) {
+            throw new AssertionError("Non-ASCII character used in documentation ("+location+"). Only ASCII characters are allowed.");
+        }
+        //make sure that html-encoded non-ascii characters are found as well
+        if ( Pattern.compile(".*&[a-zA-Z]*?;.*",Pattern.MULTILINE).matcher(documentationText).find()) {
+            throw new AssertionError("Non-ASCII character used in documentation ("+location+"). Only ASCII characters are allowed.");
         }
     }
+    // package local for testing
+    static String convertFromHtml(final String textToConvert) {
+
+        //LinkedHashmap since the order matters
+        final Map<String, String> regexps = new LinkedHashMap<>();
+
+        regexps.put("< *a *href=[\'\"](.*?)[\'\"] *>(.*?)</ *a *>","$2 ($1)");
+        regexps.put("< *a *href=[\'\"](.*?)[\'\"] *>(.*?)< *a */>","$2 ($1)");
+        regexps.put("</ *(br|p|table|h[1-4]|pre|hr|li|ul) *>","\n");
+        regexps.put("< *(br|p|table|h[1-4]|pre|hr|li|ul) */>","\n");
+        regexps.put("< *(p|table|h[1-4]|ul|pre) *>","\n");
+        regexps.put("<li>", " - ");
+        regexps.put("</th>", "\t");
+        regexps.put("<\\w*?>", "");
+
+        return regexps.entrySet().stream().sequential()
+                .reduce(textToConvert, (string, entrySet) -> string.replaceAll(entrySet.getKey(), entrySet.getValue()), (a, b) -> b);
+    }
 
     private Collection<CommandLineParser> getChildParsersForHelp() {
         final Collection<CommandLineParser> childClps;
         if (isCommandLineProgram()) {
-            childClps = new ArrayList<CommandLineParser>();
+            childClps = new ArrayList<>();
             for (final Map.Entry<String, Object> entry :
                     ((CommandLineProgram) callerOptions).getNestedOptionsForHelp().entrySet()) {
                 if (entry.getKey().contains(".")) {
@@ -360,8 +392,7 @@ public class CommandLineParser {
 
     public void htmlUsage(final PrintStream stream, final String programName, final boolean printCommon) {
         // TODO: Should HTML escape usage preamble and option usage, including line breaks
-        stream.println("<a id=\"" + programName + "\"/>");
-        stream.println("<h3>" + programName + "</h3>");
+        stream.println("<h3 id=\"" + programName + "\">" + programName + "</h3>");
         stream.println("<section>");
         stream.println("<p>" + getUsagePreamble() + "</p>");
         boolean hasOptions = false;
@@ -383,7 +414,7 @@ public class CommandLineParser {
         if (printCommon) {
             for (final String[] optionDoc : FRAMEWORK_OPTION_DOC) {
                 stream.println("<tr><td>" + optionDoc[0] + "</td><td>" +
-                        htmlEscape(optionDoc[2]) + "</td></tr>");
+                        optionDoc[2] + "</td></tr>");
             }
         }
         htmlPrintOptionTableRows(stream, printCommon);
@@ -393,11 +424,14 @@ public class CommandLineParser {
     /**
      * Prints options as rows in an HTML table.
      *
-     * @param stream
-     * @param printCommon
+     * @param stream stream into which to write the output
+     * @param printCommon whether or not to print the common information
      */
     private void htmlPrintOptionTableRows(final PrintStream stream, final boolean printCommon) {
         for (final OptionDefinition optionDefinition : optionDefinitions) {
+
+            checkForNonASCII(optionDefinition.doc, optionDefinition.name);
+
             if (!optionDefinition.isCommon || printCommon) {
                 printHtmlOptionUsage(stream, optionDefinition);
             }
@@ -405,14 +439,21 @@ public class CommandLineParser {
         for (final CommandLineParser childParser : getChildParsersForHelp()) {
             childParser.htmlPrintOptionTableRows(stream, false);
         }
-
     }
 
-    private static String htmlEscape(String str) {
+    private static final Map<String, String> htmlToText = new LinkedHashMap<String, String>(){{
+        put("<","<");
+        put(">",">");
+        put("≥",">=");
+        put("≤","<=");
+
+        put("<p>","\n");
+    }};
+
+    static String htmlUnescape(String str) {
         // May need more here
-        str = str.replaceAll("<", "<");
-        str = str.replaceAll("\n", "\n<p>");
-        return str;
+        return htmlToText.entrySet().stream().sequential()
+                .reduce(str, (string, entrySet) -> string.replace(entrySet.getKey(), entrySet.getValue()), (a, b) -> b);
     }
 
     /**
@@ -444,9 +485,8 @@ public class CommandLineParser {
                 return false;
             }
 
-
             final String[] pair = arg.split("=", 2);
-            if (pair.length == 2 && pair[1].length() == 0) {
+            if (pair.length == 2 && pair[1].isEmpty()) {
 
                 if (i < args.length - 1) {
                     pair[1] = args[++i];
@@ -495,7 +535,7 @@ public class CommandLineParser {
                 for (final String mutexOption : optionDefinition.mutuallyExclusive) {
                     final OptionDefinition mutextOptionDef = optionMap.get(mutexOption);
                     if (mutextOptionDef != null && mutextOptionDef.hasBeenSet) {
-                        mutextOptionNames.append(" ").append(prefixDot).append(mutextOptionDef.name);
+                        mutextOptionNames.append(' ').append(prefixDot).append(mutextOptionDef.name);
                     }
                 }
                 if (optionDefinition.hasBeenSet && mutextOptionNames.length() > 0) {
@@ -522,8 +562,8 @@ public class CommandLineParser {
                     }
                     return false;
                 }
-
             }
+
             if (positionalArguments != null) {
                 final Collection c = (Collection) positionalArguments.get(callerOptions);
                 if (c.size() < minPositionalArguments) {
@@ -532,13 +572,13 @@ public class CommandLineParser {
                     return false;
                 }
                 for (final Object posArg : c) {
-                    commandLineString.append(" ").append(posArg.toString());
+                    commandLineString.append(' ').append(posArg.toString());
                 }
             }
             //first, append args that were explicitly set
             for (final OptionDefinition optionDefinition : optionDefinitions) {
                 if (optionDefinition.hasBeenSet) {
-                    commandLineString.append(" ").append(prefixDot).append(optionDefinition.name).append("=").append(
+                    commandLineString.append(' ').append(prefixDot).append(optionDefinition.name).append('=').append(
                             optionDefinition.field.get(callerOptions));
                 }
             }
@@ -546,7 +586,7 @@ public class CommandLineParser {
             //next, append args that weren't explicitly set, but have a default value
             for (final OptionDefinition optionDefinition : optionDefinitions) {
                 if (!optionDefinition.hasBeenSet && !optionDefinition.defaultValue.equals("null")) {
-                    commandLineString.append(" ").append(prefixDot).append(optionDefinition.name).append("=").append(
+                    commandLineString.append(' ').append(prefixDot).append(optionDefinition.name).append('=').append(
                             optionDefinition.defaultValue);
                 }
             }
@@ -556,8 +596,6 @@ public class CommandLineParser {
             // Should never happen because lack of publicness has already been checked.
             throw new RuntimeException(e);
         }
-
-
     }
 
     private boolean parsePositionalArgument(final String stringValue) {
@@ -725,7 +763,7 @@ public class CommandLineParser {
             reader = new BufferedReader(new FileReader(optionsFile));
             String line;
             while ((line = reader.readLine()) != null) {
-                if (line.startsWith("#") || line.trim().length() == 0) {
+                if (line.startsWith("#") || line.trim().isEmpty()) {
                     continue;
                 }
                 final String[] pair = line.split("=", 2);
@@ -754,8 +792,7 @@ public class CommandLineParser {
     private void printHtmlOptionUsage(final PrintStream stream, final OptionDefinition optionDefinition) {
         final String type = getUnderlyingType(optionDefinition.field).getSimpleName();
         final String optionLabel = prefixDot + optionDefinition.name + " (" + type + ")";
-        stream.println("<tr><td>" + optionLabel + "</td><td>" +
-                htmlEscape(makeOptionDescription(optionDefinition)) + "</td></tr>");
+        stream.println("<tr><td>" + optionLabel + "</td><td>" + makeOptionDescription(optionDefinition) + "</td></tr>");
     }
 
     private void printOptionUsage(final PrintStream stream, final OptionDefinition optionDefinition) {
@@ -771,7 +808,7 @@ public class CommandLineParser {
         if (type != null) optionLabel += "=" + type;
 
         stream.print(optionLabel);
-        if (shortName != null && shortName.length() > 0) {
+        if (shortName != null && !shortName.isEmpty()) {
             stream.println();
             optionLabel = prefixDot + shortName;
             if (type != null) optionLabel += "=" + type;
@@ -784,7 +821,9 @@ public class CommandLineParser {
             numSpaces = OPTION_COLUMN_WIDTH;
         }
         printSpaces(stream, numSpaces);
-        final String wrappedDescription = StringUtil.wordWrap(optionDescription, DESCRIPTION_COLUMN_WIDTH);
+        checkForNonASCII(optionDescription, name);
+
+        final String wrappedDescription = StringUtil.wordWrap(convertFromHtml(optionDescription), DESCRIPTION_COLUMN_WIDTH);
         final String[] descriptionLines = wrappedDescription.split("\n");
         for (int i = 0; i < descriptionLines.length; ++i) {
             if (i > 0) {
@@ -797,7 +836,7 @@ public class CommandLineParser {
 
     private String makeOptionDescription(final OptionDefinition optionDefinition) {
         final StringBuilder sb = new StringBuilder();
-        if (optionDefinition.doc.length() > 0) {
+        if (!optionDefinition.doc.isEmpty()) {
             sb.append(optionDefinition.doc);
             sb.append("  ");
         }
@@ -820,7 +859,7 @@ public class CommandLineParser {
             final Boolean isClpEnum = enumConstants.length > 0 && (enumConstants[0] instanceof ClpEnum);
 
             sb.append("Possible values: {");
-            if (isClpEnum) sb.append("\n");
+            if (isClpEnum) sb.append('\n');
 
             for (int i = 0; i < enumConstants.length; ++i) {
                 if (i > 0 && !isClpEnum) {
@@ -864,9 +903,9 @@ public class CommandLineParser {
                             " doesn't match any known option.");
                 }
 
-                sb.append(" ").append(mutextOptionDefinition.name);
-                if (mutextOptionDefinition.shortName.length() > 0) {
-                    sb.append(" (").append(mutextOptionDefinition.shortName).append(")");
+                sb.append(' ').append(mutextOptionDefinition.name);
+                if (!mutextOptionDefinition.shortName.isEmpty()) {
+                    sb.append(" (").append(mutextOptionDefinition.shortName).append(')');
                 }
             }
         }
@@ -876,7 +915,7 @@ public class CommandLineParser {
     private void printSpaces(final PrintStream stream, final int numSpaces) {
         final StringBuilder sb = new StringBuilder();
         for (int i = 0; i < numSpaces; ++i) {
-            sb.append(" ");
+            sb.append(' ');
         }
         stream.print(sb);
     }
@@ -940,7 +979,7 @@ public class CommandLineParser {
             if (!optionDefinition.overridable && optionMap.containsKey(optionDefinition.name)) {
                 throw new CommandLineParserDefinitionException(optionDefinition.name + " has already been used.");
             }
-            if (optionDefinition.shortName.length() > 0) {
+            if (!optionDefinition.shortName.isEmpty()) {
                 if (optionMap.containsKey(optionDefinition.shortName)) {
                     if (!optionDefinition.overridable) {
                         throw new CommandLineParserDefinitionException(optionDefinition.shortName +
@@ -1111,17 +1150,15 @@ public class CommandLineParser {
         String getHelpDoc();
     }
 
-    
     protected static class OptionDefinitionByPrintOrderComparator implements Comparator<OptionDefinition> {
 
-		@Override
-		public int compare(OptionDefinition o1, OptionDefinition o2) {
-			return o1.printOrder - o2.printOrder;
-		}
-    	
+        @Override
+        public int compare(OptionDefinition o1, OptionDefinition o2) {
+            return o1.printOrder - o2.printOrder;
+        }
     }
     
-    protected static class OptionDefinition {
+    protected static final class OptionDefinition {
         final Field field;
         final String name;
         final String shortName;
@@ -1172,7 +1209,7 @@ public class CommandLineParser {
     /**
      * Holds a command-line argument that is destined for a child parser.  Prefix has been stripped from name.
      */
-    private static class ChildOptionArg {
+    private static final class ChildOptionArg {
         final String name;
         final String value;
         final boolean fromFile;
diff --git a/src/java/picard/fingerprint/CrosscheckReadGroupFingerprints.java b/src/java/picard/fingerprint/CrosscheckReadGroupFingerprints.java
index e724224..a54ffa1 100644
--- a/src/java/picard/fingerprint/CrosscheckReadGroupFingerprints.java
+++ b/src/java/picard/fingerprint/CrosscheckReadGroupFingerprints.java
@@ -291,7 +291,7 @@ public class CrosscheckReadGroupFingerprints extends CommandLineProgram {
     private String getReadGroupDetails(final SAMReadGroupRecord readGroupRecord) {
         final List<String> elements = new ArrayList<>(5);
 
-        final String tmp[] = readGroupRecord.getPlatformUnit().split("\\.");    // Expect to look like: D047KACXX110901.1.ACCAACTG
+        final String[] tmp = readGroupRecord.getPlatformUnit().split("\\.");    // Expect to look like: D047KACXX110901.1.ACCAACTG
         String runBarcode = "?";
         String lane = "?";
         String molBarcode = "?";
diff --git a/src/java/picard/fingerprint/HaplotypeMap.java b/src/java/picard/fingerprint/HaplotypeMap.java
index 19cdf8b..fe3fd57 100644
--- a/src/java/picard/fingerprint/HaplotypeMap.java
+++ b/src/java/picard/fingerprint/HaplotypeMap.java
@@ -85,7 +85,7 @@ public class HaplotypeMap {
             final Map<String, HaplotypeBlock> anchorToHaplotype = new HashMap<String, HaplotypeBlock>();
 
             do {
-                if (line.trim().length() == 0) continue; // skip over blank lines
+                if (line.trim().isEmpty()) continue; // skip over blank lines
                 if (line.startsWith("#")) continue;      // ignore comments/headers
 
                 // Make sure we have the right number of fields
@@ -323,7 +323,7 @@ public class HaplotypeMap {
             final StringBuilder sb = new StringBuilder();
 
             for (final String panel : panels) {
-                if (sb.length() > 0) sb.append(",");
+                if (sb.length() > 0) sb.append(',');
                 sb.append(panel);
             }
 
diff --git a/src/java/picard/fingerprint/HaplotypeProbabilitiesFromGenotypeLikelihoods.java b/src/java/picard/fingerprint/HaplotypeProbabilitiesFromGenotypeLikelihoods.java
index acea750..1d9b4e4 100644
--- a/src/java/picard/fingerprint/HaplotypeProbabilitiesFromGenotypeLikelihoods.java
+++ b/src/java/picard/fingerprint/HaplotypeProbabilitiesFromGenotypeLikelihoods.java
@@ -50,7 +50,7 @@ public class HaplotypeProbabilitiesFromGenotypeLikelihoods extends HaplotypeProb
      * @param logGenotypeLikelihoods correspond to the logLikelihoods of [AA, AB, BB]. Log is assumed to be in base 10.
      */
 
-    public void addToLogLikelihoods(final Snp snp, final List<Allele> alleles, final double logGenotypeLikelihoods[]) {
+    public void addToLogLikelihoods(final Snp snp, final List<Allele> alleles, final double[] logGenotypeLikelihoods) {
         assertSnpPartOfHaplotype(snp);
 
         // only allow biallelic snps
diff --git a/src/java/picard/illumina/ClusterDataToSamConverter.java b/src/java/picard/illumina/ClusterDataToSamConverter.java
index 08f3f7a..5e1ab07 100644
--- a/src/java/picard/illumina/ClusterDataToSamConverter.java
+++ b/src/java/picard/illumina/ClusterDataToSamConverter.java
@@ -156,7 +156,7 @@ public class ClusterDataToSamConverter implements
         // Get and transform the unmatched barcode, if any, to store with the reads
         String unmatchedBarcode = null;
         if (hasSampleBarcode && cluster.getMatchedBarcode() == null) {
-            final byte barcode[][] = new byte[sampleBarcodeIndices.length][];
+            final byte[][] barcode = new byte[sampleBarcodeIndices.length][];
             for (int i = 0; i < sampleBarcodeIndices.length; i++) {
                 barcode[i] = cluster.getRead(sampleBarcodeIndices[i]).getBases();
             }
@@ -167,8 +167,8 @@ public class ClusterDataToSamConverter implements
         final String joinedMolecularIndexQ ;
         if (hasMolecularBarcode) {
             final StringBuilder joinedMolecularIndexQBuilder = new StringBuilder();
-            final byte molecularIndex[][] = new byte[molecularBarcodeIndices.length][];
-            final byte molecularIndexQ[][] = new byte[molecularBarcodeIndices.length][];
+            final byte[][] molecularIndex = new byte[molecularBarcodeIndices.length][];
+            final byte[][] molecularIndexQ = new byte[molecularBarcodeIndices.length][];
             for (int i = 0; i < molecularBarcodeIndices.length; i++) {
                 molecularIndex[i]  = cluster.getRead(molecularBarcodeIndices[i]).getBases();
                 molecularIndexQ[i] = cluster.getRead(molecularBarcodeIndices[i]).getQualities();
diff --git a/src/java/picard/illumina/ExtractIlluminaBarcodes.java b/src/java/picard/illumina/ExtractIlluminaBarcodes.java
index 4027378..94074c3 100644
--- a/src/java/picard/illumina/ExtractIlluminaBarcodes.java
+++ b/src/java/picard/illumina/ExtractIlluminaBarcodes.java
@@ -353,10 +353,10 @@ public class ExtractIlluminaBarcodes extends CommandLineProgram {
                 barcodeToMetrics.put(barcode, metric);
             }
         }
-        if (barcodeToMetrics.keySet().size() == 0) {
+        if (barcodeToMetrics.keySet().isEmpty()) {
             messages.add("No barcodes have been specified.");
         }
-        if (messages.size() == 0) {
+        if (messages.isEmpty()) {
             return null;
         }
         return messages.toArray(new String[messages.size()]);
@@ -386,7 +386,7 @@ public class ExtractIlluminaBarcodes extends CommandLineProgram {
         final int numBarcodes = readStructure.sampleBarcodes.length();
         final Set<String> barcodes = new HashSet<String>();
         for (final TabbedTextFileWithHeaderParser.Row row : barcodesParser) {
-            final String bcStrings[] = new String[numBarcodes];
+            final String[] bcStrings = new String[numBarcodes];
             int barcodeNum = 1;
             for (final ReadDescriptor rd : readStructure.descriptors) {
                 if (rd.type != ReadType.Barcode) continue;
@@ -584,8 +584,8 @@ public class ExtractIlluminaBarcodes extends CommandLineProgram {
                 //(see customCommnandLineValidation), therefore we must use the outputReadStructure to index into the output cluster data
                 final int[] barcodeIndices = outputReadStructure.sampleBarcodes.getIndices();
                 final BufferedWriter writer = IOUtil.openFileForBufferedWriting(barcodeFile);
-                final byte barcodeSubsequences[][] = new byte[barcodeIndices.length][];
-                final byte qualityScores[][] = usingQualityScores ? new byte[barcodeIndices.length][] : null;
+                final byte[][] barcodeSubsequences = new byte[barcodeIndices.length][];
+                final byte[][] qualityScores = usingQualityScores ? new byte[barcodeIndices.length][] : null;
                 while (provider.hasNext()) {
                     // Extract the barcode from the cluster and write it to the file for the tile
                     final ClusterData cluster = provider.next();
diff --git a/src/java/picard/illumina/IlluminaBasecallsToFastq.java b/src/java/picard/illumina/IlluminaBasecallsToFastq.java
index d3c3b4d..d0141e7 100644
--- a/src/java/picard/illumina/IlluminaBasecallsToFastq.java
+++ b/src/java/picard/illumina/IlluminaBasecallsToFastq.java
@@ -257,7 +257,7 @@ public class IlluminaBasecallsToFastq extends CommandLineProgram {
         final Set<String> missingColumns = new HashSet<>(expectedCols);
         missingColumns.removeAll(actualCols);
 
-        if (missingColumns.size() > 0) {
+        if (!missingColumns.isEmpty()) {
             throw new PicardException(String.format(
                     "MULTIPLEX_PARAMS file %s is missing the following columns: %s.",
                     MULTIPLEX_PARAMS.getAbsolutePath(), StringUtil.join(", ", missingColumns
@@ -284,7 +284,7 @@ public class IlluminaBasecallsToFastq extends CommandLineProgram {
         for (final TabbedTextFileWithHeaderParser.Row row : libraryParamsParser) {
             List<String> sampleBarcodeValues = null;
 
-            if (sampleBarcodeColumnLabels.size() > 0) {
+            if (!sampleBarcodeColumnLabels.isEmpty()) {
                 sampleBarcodeValues = new ArrayList<>();
                 for (final String sampleBarcodeLabel : sampleBarcodeColumnLabels) {
                     sampleBarcodeValues.add(row.getField(sampleBarcodeLabel));
@@ -344,7 +344,7 @@ public class IlluminaBasecallsToFastq extends CommandLineProgram {
      * Container for various FastqWriters, one for each template read, one for each sample barcode read,
      * and one for each molecular barcode read.
      */
-    private static class FastqRecordsWriter implements IlluminaBasecallsConverter.ConvertedClusterDataWriter<FastqRecordsForCluster> {
+    private static final class FastqRecordsWriter implements IlluminaBasecallsConverter.ConvertedClusterDataWriter<FastqRecordsForCluster> {
         final FastqWriter[] templateWriters;
         final FastqWriter[] sampleBarcodeWriters;
         final FastqWriter[] molecularBarcodeWriters;
diff --git a/src/java/picard/illumina/IlluminaBasecallsToSam.java b/src/java/picard/illumina/IlluminaBasecallsToSam.java
index c205052..68dd57d 100644
--- a/src/java/picard/illumina/IlluminaBasecallsToSam.java
+++ b/src/java/picard/illumina/IlluminaBasecallsToSam.java
@@ -271,7 +271,7 @@ public class IlluminaBasecallsToSam extends CommandLineProgram {
         final Set<String> missingColumns = new HashSet<String>(expectedCols);
         missingColumns.removeAll(actualCols);
 
-        if (missingColumns.size() > 0) {
+        if (!missingColumns.isEmpty()) {
             throw new PicardException(String.format(
                     "LIBRARY_PARAMS file %s is missing the following columns: %s.",
                     LIBRARY_PARAMS.getAbsolutePath(), StringUtil.join(", ", missingColumns
@@ -293,7 +293,7 @@ public class IlluminaBasecallsToSam extends CommandLineProgram {
         final Set<String> forbiddenHeaders = buildSamHeaderParameters(null).keySet();
         forbiddenHeaders.retainAll(rgTagColumns);
 
-        if (forbiddenHeaders.size() > 0) {
+        if (!forbiddenHeaders.isEmpty()) {
             throw new PicardException("Illegal ReadGroup tags in library params(barcode params) file(" + LIBRARY_PARAMS.getAbsolutePath() + ") Offending headers = " + StringUtil.join(", ", forbiddenHeaders));
         }
 
@@ -336,7 +336,7 @@ public class IlluminaBasecallsToSam extends CommandLineProgram {
         for (final TabbedTextFileWithHeaderParser.Row row : libraryParamsParser) {
             List<String> barcodeValues = null;
 
-            if (barcodeColumnLabels.size() > 0) {
+            if (!barcodeColumnLabels.isEmpty()) {
                 barcodeValues = new ArrayList<String>();
                 for (final String barcodeLabel : barcodeColumnLabels) {
                     barcodeValues.add(row.getField(barcodeLabel));
@@ -447,13 +447,13 @@ public class IlluminaBasecallsToSam extends CommandLineProgram {
         if (READ_GROUP_ID == null) {
             READ_GROUP_ID = RUN_BARCODE.substring(0, 5) + "." + LANE;
         }
-        if (messages.size() == 0) {
+        if (messages.isEmpty()) {
             return null;
         }
         return messages.toArray(new String[messages.size()]);
     }
 
-    private static class SAMFileWriterWrapper
+    private static final class SAMFileWriterWrapper
             implements IlluminaBasecallsConverter.ConvertedClusterDataWriter<SAMRecordsForCluster> {
         public final SAMFileWriter writer;
 
diff --git a/src/java/picard/illumina/MarkIlluminaAdapters.java b/src/java/picard/illumina/MarkIlluminaAdapters.java
index d7e39f7..bc1e904 100644
--- a/src/java/picard/illumina/MarkIlluminaAdapters.java
+++ b/src/java/picard/illumina/MarkIlluminaAdapters.java
@@ -241,7 +241,7 @@ public class MarkIlluminaAdapters extends CommandLineProgram {
         return 0;
     }
 
-    private class CustomAdapterPair implements AdapterPair {
+    private final class CustomAdapterPair implements AdapterPair {
 
         final String fivePrime, threePrime, fivePrimeReadOrder;
         final byte[] fivePrimeBytes, threePrimeBytes, fivePrimeReadOrderBytes;
diff --git a/src/java/picard/illumina/parser/BarcodeParser.java b/src/java/picard/illumina/parser/BarcodeParser.java
index 675a419..9738a5e 100644
--- a/src/java/picard/illumina/parser/BarcodeParser.java
+++ b/src/java/picard/illumina/parser/BarcodeParser.java
@@ -56,7 +56,7 @@ class BarcodeParser extends PerTileParser<BarcodeData> {
     }
 
     private static class BarcodeDataIterator implements CloseableIterator<BarcodeData>{
-        private BarcodeFileReader bfr;
+        private final BarcodeFileReader bfr;
         public BarcodeDataIterator(final File file) {
             bfr = new BarcodeFileReader(file);
         }
diff --git a/src/java/picard/illumina/parser/FourChannelIntensityData.java b/src/java/picard/illumina/parser/FourChannelIntensityData.java
index a097ed6..3f751a2 100644
--- a/src/java/picard/illumina/parser/FourChannelIntensityData.java
+++ b/src/java/picard/illumina/parser/FourChannelIntensityData.java
@@ -40,10 +40,10 @@ public class FourChannelIntensityData {
     /**
      * Major index: channel number; minor index: cycle number (zero based)
      */
-    private short [] a;
-    private short [] c;
-    private short [] g;
-    private short [] t;
+    private final short [] a;
+    private final short [] c;
+    private final short [] g;
+    private final short [] t;
 
     public FourChannelIntensityData(final int numberOfCycles) {
         a = new short[numberOfCycles];
diff --git a/src/java/picard/illumina/parser/IlluminaDataProviderFactory.java b/src/java/picard/illumina/parser/IlluminaDataProviderFactory.java
index ea7f536..cad0242 100644
--- a/src/java/picard/illumina/parser/IlluminaDataProviderFactory.java
+++ b/src/java/picard/illumina/parser/IlluminaDataProviderFactory.java
@@ -168,7 +168,7 @@ public class IlluminaDataProviderFactory {
 
         //find if we have any IlluminaDataType with NO available file formats and, if any exist, throw an exception
         final Set<IlluminaDataType> unmatchedDataTypes = findUnmatchedTypes(dataTypes, formatToDataTypes);
-        if (unmatchedDataTypes.size() > 0) {
+        if (!unmatchedDataTypes.isEmpty()) {
             throw new PicardException("Could not find a format with available files for the following data types: " + StringUtil.join(", ", new ArrayList<IlluminaDataType>(unmatchedDataTypes)));
         }
 
@@ -224,7 +224,7 @@ public class IlluminaDataProviderFactory {
         if (requestedTiles == null) {
             requestedTiles = availableTiles;
         } else {
-            if (requestedTiles.size() == 0) {
+            if (requestedTiles.isEmpty()) {
                 throw new PicardException("Zero length tile list supplied to makeDataProvider, you must specify at least 1 tile OR pass NULL to use all available tiles");
             }
         }
diff --git a/src/java/picard/illumina/parser/IlluminaFileUtil.java b/src/java/picard/illumina/parser/IlluminaFileUtil.java
index df3a91c..51cd573 100644
--- a/src/java/picard/illumina/parser/IlluminaFileUtil.java
+++ b/src/java/picard/illumina/parser/IlluminaFileUtil.java
@@ -194,7 +194,7 @@ public class IlluminaFileUtil {
             throw new PicardException("Format list provided to getTiles was null!");
         }
 
-        if (formats.size() == 0) {
+        if (formats.isEmpty()) {
             throw new PicardException(
                     "0 Formats were specified.  You need to specify at least SupportedIlluminaFormat to use getTiles");
         }
@@ -233,7 +233,7 @@ public class IlluminaFileUtil {
 
 
     private String liToStr(final List<Integer> intList) {
-        if (intList.size() == 0) {
+        if (intList.isEmpty()) {
             return "";
         }
 
diff --git a/src/java/picard/illumina/parser/MultiTileBclFileUtil.java b/src/java/picard/illumina/parser/MultiTileBclFileUtil.java
index ba635a6..e84dd87 100644
--- a/src/java/picard/illumina/parser/MultiTileBclFileUtil.java
+++ b/src/java/picard/illumina/parser/MultiTileBclFileUtil.java
@@ -72,7 +72,7 @@ public class MultiTileBclFileUtil extends ParameterizedFileUtil {
 
     @Override
     public boolean filesAvailable() {
-        return bci.exists() && cycleFileMap.size() > 0;
+        return bci.exists() && !cycleFileMap.isEmpty();
     }
 
     @Override
diff --git a/src/java/picard/illumina/parser/PerTileFileUtil.java b/src/java/picard/illumina/parser/PerTileFileUtil.java
index af31681..fa12df3 100644
--- a/src/java/picard/illumina/parser/PerTileFileUtil.java
+++ b/src/java/picard/illumina/parser/PerTileFileUtil.java
@@ -21,7 +21,7 @@ public class PerTileFileUtil extends ParameterizedFileUtil {
         final FileFaker faker, final int lane, final boolean skipEmptyFiles) {
         super(true, extension, base, faker, lane, skipEmptyFiles);
         this.fileMap = getTiledFiles(base, matchPattern);
-        if (fileMap.size() > 0) {
+        if (!fileMap.isEmpty()) {
             this.tiles = Collections.unmodifiableList(new ArrayList<Integer>(this.fileMap.keySet()));
         } else {
             this.tiles = new ArrayList<Integer>();
diff --git a/src/java/picard/illumina/parser/ReadStructure.java b/src/java/picard/illumina/parser/ReadStructure.java
index 513e44d..143217e 100644
--- a/src/java/picard/illumina/parser/ReadStructure.java
+++ b/src/java/picard/illumina/parser/ReadStructure.java
@@ -111,7 +111,7 @@ public class ReadStructure {
      * @param collection A collection of ReadDescriptors that describes this ReadStructure
      */
     public ReadStructure(final List<ReadDescriptor> collection) {
-        if(collection.size() == 0) { //If this changes, change hashcode
+        if(collection.isEmpty()) { //If this changes, change hashcode
             throw new IllegalArgumentException("ReadStructure does not support 0 length clusters!");
         }
 
@@ -352,7 +352,7 @@ public class ReadStructure {
     /** An iterator over a Substructure's ReadDescriptors */
     private class IndexedIterator implements Iterator<ReadDescriptor> {
         private int index;
-        private int [] indices;
+        private final int [] indices;
         public IndexedIterator(final int [] indices) {
             this.indices = indices;
             this.index = 0;
diff --git a/src/java/picard/illumina/parser/TileIndex.java b/src/java/picard/illumina/parser/TileIndex.java
index 298d9a1..21a224d 100644
--- a/src/java/picard/illumina/parser/TileIndex.java
+++ b/src/java/picard/illumina/parser/TileIndex.java
@@ -134,7 +134,7 @@ public class TileIndex implements Iterable<TileIndex.TileIndexRecord> {
         throw new NoSuchElementException(String.format("Tile %d not found in %s", tileNumber, tileIndexFile));
     }
 
-    public static class TileIndexRecord {
+    public static final class TileIndexRecord {
         /**
          * Number of the tile, e.g. 11101.  These don't necessarily start at 0, and there may be gaps.
          */
diff --git a/src/java/picard/illumina/parser/fakers/BarcodeFileFaker.java b/src/java/picard/illumina/parser/fakers/BarcodeFileFaker.java
index 4b8aacf..be861f0 100644
--- a/src/java/picard/illumina/parser/fakers/BarcodeFileFaker.java
+++ b/src/java/picard/illumina/parser/fakers/BarcodeFileFaker.java
@@ -6,11 +6,11 @@ import java.nio.ByteBuffer;
  * Created by jcarey on 3/13/14.
  */
 public class BarcodeFileFaker extends FileFaker {
-    private final String barcodeString = "1\tn\t \n";
+    private static final String BARCODE_STRING = "1\tn\t \n";
 
     @Override
     protected void fakeFile(final ByteBuffer buffer) {
-        buffer.put(barcodeString.getBytes());
+        buffer.put(BARCODE_STRING.getBytes());
     }
 
     @Override
@@ -20,6 +20,6 @@ public class BarcodeFileFaker extends FileFaker {
 
     @Override
     protected int bufferSize() {
-        return barcodeString.getBytes().length;
+        return BARCODE_STRING.getBytes().length;
     }
-}
+}
diff --git a/src/java/picard/illumina/parser/fakers/PosFileFaker.java b/src/java/picard/illumina/parser/fakers/PosFileFaker.java
index d3c449e..9596425 100644
--- a/src/java/picard/illumina/parser/fakers/PosFileFaker.java
+++ b/src/java/picard/illumina/parser/fakers/PosFileFaker.java
@@ -6,11 +6,11 @@ import java.nio.ByteBuffer;
  * Created by jcarey on 3/13/14.
  */
 public class PosFileFaker extends FileFaker {
-    private final String posFileString = "102.0\t303.3\n";
+    private static final String POS_FILE_STRING = "102.0\t303.3\n";
 
     @Override
     protected void fakeFile(final ByteBuffer buffer) {
-        buffer.put(posFileString.getBytes());
+        buffer.put(POS_FILE_STRING.getBytes());
     }
 
     @Override
@@ -20,6 +20,6 @@ public class PosFileFaker extends FileFaker {
 
     @Override
     protected int bufferSize() {
-        return posFileString.getBytes().length;
+        return POS_FILE_STRING.getBytes().length;
     }
-}
+}
diff --git a/src/java/picard/illumina/parser/readers/BclQualityEvaluationStrategy.java b/src/java/picard/illumina/parser/readers/BclQualityEvaluationStrategy.java
index dfc8608..9b448f1 100644
--- a/src/java/picard/illumina/parser/readers/BclQualityEvaluationStrategy.java
+++ b/src/java/picard/illumina/parser/readers/BclQualityEvaluationStrategy.java
@@ -29,7 +29,7 @@ public class BclQualityEvaluationStrategy {
     public static final int ILLUMINA_ALLEGED_MINIMUM_QUALITY = 2;
     private final int minimumRevisedQuality;
     /** A thread-safe defaulting map that injects an AtomicInteger starting at 0 when a uninitialized key is get-ted. */
-    private Map<Byte, AtomicInteger> qualityCountMap = Collections.synchronizedMap(new CollectionUtil.DefaultingMap<Byte, AtomicInteger>(
+    private final  Map<Byte, AtomicInteger> qualityCountMap = Collections.synchronizedMap(new CollectionUtil.DefaultingMap<Byte, AtomicInteger>(
             new CollectionUtil.DefaultingMap.Factory<AtomicInteger, Byte>() {
                 @Override
                 public AtomicInteger make(final Byte _) {
diff --git a/src/java/picard/illumina/parser/readers/FilterFileReader.java b/src/java/picard/illumina/parser/readers/FilterFileReader.java
index 16b824b..6b8b065 100644
--- a/src/java/picard/illumina/parser/readers/FilterFileReader.java
+++ b/src/java/picard/illumina/parser/readers/FilterFileReader.java
@@ -42,7 +42,7 @@ public class FilterFileReader implements Iterator<Boolean> {
     private static final int HEADER_SIZE  = 12;
 
     /** Expected Version */
-    public final int EXPECTED_VERSION = 3;
+    public static final int EXPECTED_VERSION = 3;
 
     /** Iterator over each cluster in the FilterFile */
     private final BinaryFileIterator<Byte> bbIterator;
diff --git a/src/java/picard/illumina/parser/readers/MMapBackedIteratorFactory.java b/src/java/picard/illumina/parser/readers/MMapBackedIteratorFactory.java
index 0a66128..c76b383 100644
--- a/src/java/picard/illumina/parser/readers/MMapBackedIteratorFactory.java
+++ b/src/java/picard/illumina/parser/readers/MMapBackedIteratorFactory.java
@@ -203,8 +203,8 @@ public class MMapBackedIteratorFactory {
     //TODO: Add test
     //TODO: Make a note that if you want to multithread over this then you have to copy the contents
     private static class ByteBufferMMapIterator extends MMapBackedIterator<ByteBuffer> {
-        private byte [] localBacking;
-        private ByteBuffer localBuffer;
+        private final byte [] localBacking;
+        private final ByteBuffer localBuffer;
         public ByteBufferMMapIterator(final byte[] header, final File file, final int elementBufferSize, final ByteBuffer buf) {
             super(header, file, elementBufferSize, buf);
             this.localBacking = new byte[elementBufferSize];
diff --git a/src/java/picard/illumina/quality/CollectHiSeqXPfFailMetrics.java b/src/java/picard/illumina/quality/CollectHiSeqXPfFailMetrics.java
index 66ae083..cacc0fa 100644
--- a/src/java/picard/illumina/quality/CollectHiSeqXPfFailMetrics.java
+++ b/src/java/picard/illumina/quality/CollectHiSeqXPfFailMetrics.java
@@ -109,7 +109,7 @@ public class CollectHiSeqXPfFailMetrics extends CommandLineProgram {
             errors.add("PROB_EXPLICIT_READS must be a probability, i.e., 0 <= PROB_EXPLICIT_READS <= 1");
         }
 
-        if (errors.size() > 0) {
+        if (!errors.isEmpty()) {
             return errors.toArray(new String[errors.size()]);
         } else {
             return super.customCommandLineValidation();
diff --git a/src/java/picard/sam/FastqToSam.java b/src/java/picard/sam/FastqToSam.java
index 37bf41e..441d292 100644
--- a/src/java/picard/sam/FastqToSam.java
+++ b/src/java/picard/sam/FastqToSam.java
@@ -462,7 +462,7 @@ public class FastqToSam extends CommandLineProgram {
         if(readName.equals("")) throw new PicardException(error(freader,"Pair read name "+pairNum+" cannot be empty: "+readName));
 
         final int idx = readName.lastIndexOf("/");
-        final String result[] = new String[2];
+        final String[] result = new String[2];
 
         if (idx == -1) {
             result[0] = readName;
diff --git a/src/java/picard/sam/FilterSamReads.java b/src/java/picard/sam/FilterSamReads.java
index 234262b..12536be 100644
--- a/src/java/picard/sam/FilterSamReads.java
+++ b/src/java/picard/sam/FilterSamReads.java
@@ -20,6 +20,7 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
+ * 
  */
 
 /**
@@ -35,6 +36,7 @@ import htsjdk.samtools.SamReader;
 import htsjdk.samtools.SamReaderFactory;
 import htsjdk.samtools.filter.AlignedFilter;
 import htsjdk.samtools.filter.FilteringIterator;
+import htsjdk.samtools.filter.JavascriptSamRecordFilter;
 import htsjdk.samtools.filter.ReadNameFilter;
 import htsjdk.samtools.util.IOUtil;
 import htsjdk.samtools.util.Log;
@@ -78,13 +80,13 @@ public class FilterSamReads extends CommandLineProgram {
             "For information on the SAM format, please see: http://samtools.sourceforge.net" +
             "<hr />";
     private static final Log log = Log.getInstance(FilterSamReads.class);
-
-    private static enum Filter {
+    
+    protected /* <- used in test */ enum Filter {
         includeAligned("OUTPUT SAM/BAM will contain aligned reads only. INPUT SAM/BAM must be in queryname SortOrder. (Note that *both* first and second of paired reads must be aligned to be included in the OUTPUT SAM or BAM)"),
         excludeAligned("OUTPUT SAM/BAM will contain un-mapped reads only. INPUT SAM/BAM must be in queryname SortOrder. (Note that *both* first and second of pair must be aligned to be excluded from the OUTPUT SAM or BAM)"),
         includeReadList("OUTPUT SAM/BAM will contain reads that are supplied in the READ_LIST_FILE file"),
-        excludeReadList("OUTPUT bam will contain reads that are *not* supplied in the READ_LIST_FILE file");
-
+        excludeReadList("OUTPUT bam will contain reads that are *not* supplied in the READ_LIST_FILE file"),
+    	includeJavascript("OUTPUT bam will contain reads that hava been accepted by the JAVASCRIPT_FILE script.");
         private final String description;
 
         Filter(final String description) {
@@ -123,7 +125,17 @@ public class FilterSamReads extends CommandLineProgram {
     @Option(doc = "SAM or BAM file to write read excluded results to",
             optional = false, shortName = "O")
     public File OUTPUT;
-
+    
+	@Option(shortName = "JS",
+			doc = "Filters a SAM or BAM file with a javascript expression using the java javascript-engine. "
+	        + " The script puts the following variables in the script context: "
+	        + " 'record' a SamRecord ( https://samtools.github.io/htsjdk/javadoc/htsjdk/htsjdk/samtools/SAMRecord.html ) and "
+	        + " 'header' a SAMFileHeader ( https://samtools.github.io/htsjdk/javadoc/htsjdk/htsjdk/samtools/SAMFileHeader.html )."
+	        + " Last value of the script should be a boolean to tell wether we should accept or reject the record.",
+	        optional = true)
+	public File JAVASCRIPT_FILE = null;
+
+    
     private void filterReads(final FilteringIterator filteringIterator) {
 
         // get OUTPUT header from INPUT and overwrite it if necessary
@@ -181,27 +193,39 @@ public class FilterSamReads extends CommandLineProgram {
             IOUtil.assertFileIsReadable(INPUT);
             IOUtil.assertFileIsWritable(OUTPUT);
             if (WRITE_READS_FILES) writeReadsFile(INPUT);
-
+            final SamReader samReader = SamReaderFactory.makeDefault().referenceSequence(REFERENCE_SEQUENCE).open(INPUT);
+            final FilteringIterator filteringIterator;
+            
             switch (FILTER) {
                 case includeAligned:
-                    filterReads(new FilteringIterator(SamReaderFactory.makeDefault().referenceSequence(REFERENCE_SEQUENCE).open(INPUT).iterator(),
-                            new AlignedFilter(true), true));
+                	filteringIterator = new FilteringIterator(samReader.iterator(),
+                            new AlignedFilter(true), true);
                     break;
                 case excludeAligned:
-                    filterReads(new FilteringIterator(SamReaderFactory.makeDefault().referenceSequence(REFERENCE_SEQUENCE).open(INPUT).iterator(),
-                            new AlignedFilter(false), true));
+                	filteringIterator = new FilteringIterator(samReader.iterator(),
+                            new AlignedFilter(false), true);
                     break;
                 case includeReadList:
-                    filterReads(new FilteringIterator(SamReaderFactory.makeDefault().referenceSequence(REFERENCE_SEQUENCE).open(INPUT).iterator(),
-                            new ReadNameFilter(READ_LIST_FILE, true)));
+                	filteringIterator = new FilteringIterator(samReader.iterator(),
+                            new ReadNameFilter(READ_LIST_FILE, true));
                     break;
                 case excludeReadList:
-                    filterReads(new FilteringIterator(SamReaderFactory.makeDefault().referenceSequence(REFERENCE_SEQUENCE).open(INPUT).iterator(),
-                            new ReadNameFilter(READ_LIST_FILE, false)));
+                	filteringIterator = new FilteringIterator(samReader.iterator(),
+                            new ReadNameFilter(READ_LIST_FILE, false));
+                    break;
+                case includeJavascript:
+                	filteringIterator = new FilteringIterator(samReader.iterator(),
+                			new JavascriptSamRecordFilter(
+                			        JAVASCRIPT_FILE,
+                					samReader.getFileHeader()
+                					));
+                	
                     break;
                 default:
                     throw new UnsupportedOperationException(FILTER.name() + " has not been implemented!");
             }
+            
+            filterReads(filteringIterator);
 
             IOUtil.assertFileIsReadable(OUTPUT);
             if (WRITE_READS_FILES) writeReadsFile(OUTPUT);
diff --git a/src/java/picard/sam/MergeBamAlignment.java b/src/java/picard/sam/MergeBamAlignment.java
index 57e1ece..18a54f8 100644
--- a/src/java/picard/sam/MergeBamAlignment.java
+++ b/src/java/picard/sam/MergeBamAlignment.java
@@ -289,14 +289,14 @@ public class MergeBamAlignment extends CommandLineProgram {
                     "be included."};
         }
 
-        final boolean r1sExist = READ1_ALIGNED_BAM != null && READ1_ALIGNED_BAM.size() > 0;
-        final boolean r2sExist = READ2_ALIGNED_BAM != null && READ2_ALIGNED_BAM.size() > 0;
+        final boolean r1sExist = READ1_ALIGNED_BAM != null && !READ1_ALIGNED_BAM.isEmpty();
+        final boolean r2sExist = READ2_ALIGNED_BAM != null && !READ2_ALIGNED_BAM.isEmpty();
         if ((r1sExist && !r2sExist) || (r2sExist && !r1sExist)) {
             return new String[]{"READ1_ALIGNED_BAM and READ2_ALIGNED_BAM " +
                     "must both be supplied or neither should be included.  For " +
                     "single-end read use ALIGNED_BAM."};
         }
-        if (ALIGNED_BAM == null || ALIGNED_BAM.size() == 0 && !(r1sExist && r2sExist)) {
+        if (ALIGNED_BAM == null || ALIGNED_BAM.isEmpty() && !(r1sExist && r2sExist)) {
             return new String[]{"Either ALIGNED_BAM or the combination of " +
                     "READ1_ALIGNED_BAM and READ2_ALIGNED_BAM must be supplied."};
 
diff --git a/src/java/picard/sam/RevertSam.java b/src/java/picard/sam/RevertSam.java
index 65c1aea..7e7d72e 100644
--- a/src/java/picard/sam/RevertSam.java
+++ b/src/java/picard/sam/RevertSam.java
@@ -313,7 +313,7 @@ public class RevertSam extends CommandLineProgram {
                     // The only valid quality score encoding scheme is standard; if it's not standard, change it.
                     final FastqQualityFormat recordFormat = readGroupToFormat.get(rec.getReadGroup());
                     if (!recordFormat.equals(FastqQualityFormat.Standard)) {
-                        final byte quals[] = rec.getBaseQualities();
+                        final byte[] quals = rec.getBaseQualities();
                         for (int i = 0; i < quals.length; i++) {
                             quals[i] -= SolexaQualityConverter.ILLUMINA_TO_PHRED_SUBTRAHEND;
                         }
diff --git a/src/java/picard/sam/SamAlignmentMerger.java b/src/java/picard/sam/SamAlignmentMerger.java
index f781a61..15a697f 100644
--- a/src/java/picard/sam/SamAlignmentMerger.java
+++ b/src/java/picard/sam/SamAlignmentMerger.java
@@ -107,9 +107,9 @@ public class SamAlignmentMerger extends AbstractAlignmentMerger {
                 alignedReadsOnly, programRecord, attributesToRetain, attributesToRemove, read1BasesTrimmed,
                 read2BasesTrimmed, expectedOrientations, sortOrder, primaryAlignmentSelectionStrategy, addMateCigar, unmapContaminantReads);
 
-        if ((alignedSamFile == null || alignedSamFile.size() == 0) &&
-                (read1AlignedSamFile == null || read1AlignedSamFile.size() == 0 ||
-                        read2AlignedSamFile == null || read2AlignedSamFile.size() == 0)) {
+        if ((alignedSamFile == null || alignedSamFile.isEmpty()) &&
+                (read1AlignedSamFile == null || read1AlignedSamFile.isEmpty() ||
+                        read2AlignedSamFile == null || read2AlignedSamFile.isEmpty())) {
             throw new IllegalArgumentException("Either alignedSamFile or BOTH of read1AlignedSamFile and " +
                     "read2AlignedSamFile must be specified.");
         }
@@ -164,7 +164,7 @@ public class SamAlignmentMerger extends AbstractAlignmentMerger {
         final SAMFileHeader header;
 
         // When the alignment records, including both ends of a pair, are in SAM files
-        if (alignedSamFile != null && alignedSamFile.size() > 0) {
+        if (alignedSamFile != null && !alignedSamFile.isEmpty()) {
             final List<SAMFileHeader> headers = new ArrayList<SAMFileHeader>(alignedSamFile.size());
             final List<SamReader> readers = new ArrayList<SamReader>(alignedSamFile.size());
             for (final File f : this.alignedSamFile) {
@@ -227,7 +227,7 @@ public class SamAlignmentMerger extends AbstractAlignmentMerger {
         };
     }
 
-    private class SuffixTrimingSamRecordIterator implements CloseableIterator<SAMRecord> {
+    private final class SuffixTrimingSamRecordIterator implements CloseableIterator<SAMRecord> {
         private final CloseableIterator<SAMRecord> underlyingIterator;
         private final String suffixToTrim;
 
diff --git a/src/java/picard/sam/SamToFastq.java b/src/java/picard/sam/SamToFastq.java
index 8d06444..8990c33 100755
--- a/src/java/picard/sam/SamToFastq.java
+++ b/src/java/picard/sam/SamToFastq.java
@@ -208,7 +208,7 @@ public class SamToFastq extends CommandLineProgram {
             writerMapping.closeAll();
         }
 
-        if (firstSeenMates.size() > 0) {
+        if (!firstSeenMates.isEmpty()) {
             SAMUtils.processValidationError(new SAMValidationError(SAMValidationError.Type.MATE_NOT_FOUND,
                     "Found " + firstSeenMates.size() + " unpaired mates", null), VALIDATION_STRINGENCY);
         }
@@ -438,7 +438,7 @@ public class SamToFastq extends CommandLineProgram {
      * Allows for lazy construction of the second-of-pair writer, since when we are in the "output per read group mode", we only wish to
      * generate a second-of-pair fastq if we encounter a second-of-pair read.
      */
-    static class FastqWriters {
+    static final class FastqWriters {
         private final FastqWriter firstOfPair, unpaired;
         private final Lazy<FastqWriter> secondOfPair;
 
diff --git a/src/java/picard/sam/SplitSamByLibrary.java b/src/java/picard/sam/SplitSamByLibrary.java
index 6de2f1c..7528216 100755
--- a/src/java/picard/sam/SplitSamByLibrary.java
+++ b/src/java/picard/sam/SplitSamByLibrary.java
@@ -106,7 +106,7 @@ public class SplitSamByLibrary extends CommandLineProgram {
             }
         }
 
-        if (libraryToRg.size() == 0) {
+        if (libraryToRg.isEmpty()) {
             log.error("No individual libraries are " +
                     "specified in the header of " + INPUT.getAbsolutePath());
             return NO_LIBRARIES_SPECIFIED_IN_HEADER;
diff --git a/src/java/picard/sam/markduplicates/EstimateLibraryComplexity.java b/src/java/picard/sam/markduplicates/EstimateLibraryComplexity.java
index d8e9718..5201bdb 100644
--- a/src/java/picard/sam/markduplicates/EstimateLibraryComplexity.java
+++ b/src/java/picard/sam/markduplicates/EstimateLibraryComplexity.java
@@ -173,7 +173,7 @@ public class EstimateLibraryComplexity extends AbstractOpticalDuplicateFinderCom
         if (MIN_IDENTICAL_BASES <= 0) {
             errorMsgs.add("MIN_IDENTICAL_BASES must be greater than 0");
         }
-        return errorMsgs.size() == 0 ? super.customCommandLineValidation() : errorMsgs.toArray(new String[errorMsgs.size()]);
+        return errorMsgs.isEmpty() ? super.customCommandLineValidation() : errorMsgs.toArray(new String[errorMsgs.size()]);
     }
 
     /**
@@ -540,7 +540,7 @@ public class EstimateLibraryComplexity extends AbstractOpticalDuplicateFinderCom
                             }
                         }
 
-                        if (dupes.size() > 0) {
+                        if (!dupes.isEmpty()) {
                             dupes.add(lhs);
                             final int duplicateCount = dupes.size();
                             duplicationHisto.increment(duplicateCount);
diff --git a/src/java/picard/sam/markduplicates/util/AbstractOpticalDuplicateFinderCommandLineProgram.java b/src/java/picard/sam/markduplicates/util/AbstractOpticalDuplicateFinderCommandLineProgram.java
index c574af3..0b66a24 100644
--- a/src/java/picard/sam/markduplicates/util/AbstractOpticalDuplicateFinderCommandLineProgram.java
+++ b/src/java/picard/sam/markduplicates/util/AbstractOpticalDuplicateFinderCommandLineProgram.java
@@ -50,9 +50,9 @@ public abstract class AbstractOpticalDuplicateFinderCommandLineProgram extends C
             optional = true)
     public String READ_NAME_REGEX = OpticalDuplicateFinder.DEFAULT_READ_NAME_REGEX;
 
-    @Option(doc = "The maximum offset between two duplicte clusters in order to consider them optical duplicates. This " +
-            "should usually be set to some fairly small number (e.g. 5-10 pixels) unless using later versions of the " +
-            "Illumina pipeline that multiply pixel values by 10, in which case 50-100 is more normal.")
+    @Option(doc = "The maximum offset between two duplicate clusters in order to consider them optical duplicates. The default " +
+            "is appropriate for unpatterned versions of the Illumina platform. For the patterned flowcell models, 2500 is more" +
+            "appropriate. For other platforms and models, users should experiment to find what works best.")
     public int OPTICAL_DUPLICATE_PIXEL_DISTANCE = OpticalDuplicateFinder.DEFAULT_OPTICAL_DUPLICATE_DISTANCE;
 
     // The tool with which to find optical duplicates
diff --git a/src/java/picard/sam/markduplicates/util/MemoryBasedReadEndsForMarkDuplicatesMap.java b/src/java/picard/sam/markduplicates/util/MemoryBasedReadEndsForMarkDuplicatesMap.java
index 745a2a8..4d20e1e 100644
--- a/src/java/picard/sam/markduplicates/util/MemoryBasedReadEndsForMarkDuplicatesMap.java
+++ b/src/java/picard/sam/markduplicates/util/MemoryBasedReadEndsForMarkDuplicatesMap.java
@@ -39,7 +39,7 @@ class MemoryBasedReadEndsForMarkDuplicatesMap implements ReadEndsForMarkDuplicat
      * Index of this list is sequence index.  Value is map from String {read group id:read name} to ReadEnds.
      * When a ReadEnds is put into this container, it is stored according to the sequenceIndex of the mate
      */
-    private List<Map<String, ReadEndsForMarkDuplicates>> mapPerSequence = new ArrayList<Map<String, ReadEndsForMarkDuplicates>>();
+    private final List<Map<String, ReadEndsForMarkDuplicates>> mapPerSequence = new ArrayList<Map<String, ReadEndsForMarkDuplicates>>();
 
     public ReadEndsForMarkDuplicates remove(int mateSequenceIndex, String key) {
         if (mateSequenceIndex >= mapPerSequence.size()) {
diff --git a/src/java/picard/sam/util/PhysicalLocation.java b/src/java/picard/sam/util/PhysicalLocation.java
index eaf0fc4..fba814e 100644
--- a/src/java/picard/sam/util/PhysicalLocation.java
+++ b/src/java/picard/sam/util/PhysicalLocation.java
@@ -6,7 +6,7 @@ package picard.sam.util;
  * non-zero positive integers, x and y coordinates may be negative.
  */
 public interface PhysicalLocation {
-    public int NO_VALUE = -1;
+    public static int NO_VALUE = -1;
 
     public short getReadGroup();
 
diff --git a/src/java/picard/util/AdapterMarker.java b/src/java/picard/util/AdapterMarker.java
index 683f04a..5ddaba9 100644
--- a/src/java/picard/util/AdapterMarker.java
+++ b/src/java/picard/util/AdapterMarker.java
@@ -277,7 +277,7 @@ public class AdapterMarker {
         }
     }
 
-    private static class TruncatedAdapterPair implements AdapterPair {
+    private static final class TruncatedAdapterPair implements AdapterPair {
         String name;
         final String fivePrime, threePrime, fivePrimeReadOrder;
         final byte[]  fivePrimeBytes, threePrimeBytes, fivePrimeReadOrderBytes;
diff --git a/src/java/picard/util/BaitDesigner.java b/src/java/picard/util/BaitDesigner.java
index aa5737f..c20742f 100644
--- a/src/java/picard/util/BaitDesigner.java
+++ b/src/java/picard/util/BaitDesigner.java
@@ -355,7 +355,7 @@ public class BaitDesigner extends CommandLineProgram {
             errors.add("Right primer " + RIGHT_PRIMER + " is not a valid primer sequence.");
         }
 
-        if (errors.size() > 0) return errors.toArray(new String[errors.size()]);
+        if (!errors.isEmpty()) return errors.toArray(new String[errors.size()]);
         else return null;
     }
 
diff --git a/src/java/picard/util/BasicInputParser.java b/src/java/picard/util/BasicInputParser.java
index 2df0293..91f285d 100644
--- a/src/java/picard/util/BasicInputParser.java
+++ b/src/java/picard/util/BasicInputParser.java
@@ -110,7 +110,7 @@ public class BasicInputParser extends AbstractInputParser
                 nextLine = line;
                 return line.getBytes();
             }
-            if (inputs.size() > 0) {
+            if (!inputs.isEmpty()) {
                 advanceFile();
                 return readNextLine();
             }
@@ -122,7 +122,7 @@ public class BasicInputParser extends AbstractInputParser
     }
 
     protected void advanceFile() {
-        currentFileName = fileNames.size() > 0 ? fileNames.remove(0) : null;
+        currentFileName = !fileNames.isEmpty() ? fileNames.remove(0) : null;
         nextLineNumber = 0;
         nextLine = null;
         reader = new BufferedLineReader(inputs.remove(0));
@@ -166,8 +166,8 @@ public class BasicInputParser extends AbstractInputParser
         return currentLineNumber;
     }
 
-    private static InputStream[] filesToInputStreams(final File files[]) {
-        final InputStream result[] = new InputStream[files.length];
+    private static InputStream[] filesToInputStreams(final File[] files) {
+        final InputStream[] result = new InputStream[files.length];
         for (int i = 0; i < files.length; i++) {
             result[i] = IOUtil.openFileForReading(files[i]);
         }
diff --git a/src/java/picard/util/DbSnpBitSetUtil.java b/src/java/picard/util/DbSnpBitSetUtil.java
index 355e95c..af0559c 100755
--- a/src/java/picard/util/DbSnpBitSetUtil.java
+++ b/src/java/picard/util/DbSnpBitSetUtil.java
@@ -24,13 +24,20 @@
 package picard.util;
 
 import htsjdk.samtools.SAMSequenceDictionary;
-import htsjdk.samtools.util.CloseableIterator;
 import htsjdk.samtools.util.CloserUtil;
+import htsjdk.samtools.util.IntervalList;
 import htsjdk.variant.variantcontext.VariantContext;
 import htsjdk.variant.vcf.VCFFileReader;
+import picard.vcf.ByIntervalListVariantContextIterator;
 
 import java.io.File;
-import java.lang.IllegalArgumentException;import java.lang.String;import java.util.BitSet;import java.util.Collection;import java.util.EnumSet;import java.util.HashMap;import java.util.Map;import java.util.Set;
+import java.util.BitSet;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
 
 /**
  * Utility class to use with DbSnp files to determine is a locus is
@@ -38,7 +45,7 @@ import java.lang.IllegalArgumentException;import java.lang.String;import java.ut
  */
 public class DbSnpBitSetUtil {
 
-    private final Map<String, BitSet> sequenceToBitSet = new HashMap<String,BitSet>();
+    private final Map<String, BitSet> sequenceToBitSet = new HashMap<>();
 
     /** Little tuple class to contain one bitset for SNPs and another for Indels. */
     public static class DbSnpBitSets {
@@ -54,6 +61,13 @@ public class DbSnpBitSetUtil {
         this(dbSnpFile, sequenceDictionary, EnumSet.noneOf(VariantType.class));
     }
 
+    /** Constructor that creates a bit set with bits set to true for the given variant types. */
+    public DbSnpBitSetUtil(final File dbSnpFile,
+                           final SAMSequenceDictionary sequenceDictionary,
+                           final Collection<VariantType> variantsToMatch) {
+        this(dbSnpFile, sequenceDictionary, variantsToMatch, null);
+    }
+
     /**
      * Constructor.
      *
@@ -66,39 +80,56 @@ public class DbSnpBitSetUtil {
      * @param sequenceDictionary Optionally, a sequence dictionary corresponding to the dbSnp file, else null.
      * If present, BitSets will be allocated more efficiently because the maximum size will be known.
      * @param variantsToMatch what types of variants to load.
+     * @param intervals an interval list specifying the regions to load, or null, if we are return all dbSNP sites.
      */
     public DbSnpBitSetUtil(final File dbSnpFile,
                            final SAMSequenceDictionary sequenceDictionary,
-                           final Collection<VariantType> variantsToMatch) {
+                           final Collection<VariantType> variantsToMatch,
+                           final IntervalList intervals) {
 
         if (dbSnpFile == null) throw new IllegalArgumentException("null dbSnpFile");
-        final Map<DbSnpBitSetUtil, Set<VariantType>> tmp = new HashMap<DbSnpBitSetUtil, Set<VariantType>>();
+        final Map<DbSnpBitSetUtil, Set<VariantType>> tmp = new HashMap<>();
         tmp.put(this, EnumSet.copyOf(variantsToMatch));
-        loadVcf(dbSnpFile, sequenceDictionary, tmp);
+        loadVcf(dbSnpFile, sequenceDictionary, tmp, intervals);
     }
 
     /** Factory method to create both a SNP bitmask and an indel bitmask in a single pass of the VCF. */
     public static DbSnpBitSets createSnpAndIndelBitSets(final File dbSnpFile,
                                                         final SAMSequenceDictionary sequenceDictionary) {
+        return createSnpAndIndelBitSets(dbSnpFile, sequenceDictionary, null);
+    }
+
+    /** Factory method to create both a SNP bitmask and an indel bitmask in a single pass of the VCF.
+     * If intervals are given, consider only SNP and indel sites that overlap the intervals. */
+    public static DbSnpBitSets createSnpAndIndelBitSets(final File dbSnpFile,
+                                                        final SAMSequenceDictionary sequenceDictionary,
+                                                        final IntervalList intervals) {
 
         final DbSnpBitSets sets = new DbSnpBitSets();
         sets.snps   = new DbSnpBitSetUtil();
         sets.indels = new DbSnpBitSetUtil();
 
-        final Map<DbSnpBitSetUtil, Set<VariantType>> map = new HashMap<DbSnpBitSetUtil, Set<VariantType>>();
+        final Map<DbSnpBitSetUtil, Set<VariantType>> map = new HashMap<>();
         map.put(sets.snps,   EnumSet.of(VariantType.SNP));
         map.put(sets.indels, EnumSet.of(VariantType.insertion, VariantType.deletion));
-        loadVcf(dbSnpFile, sequenceDictionary, map);
+        loadVcf(dbSnpFile, sequenceDictionary, map, intervals);
         return sets;
     }
 
     /** Private helper method to read through the VCF and create one or more bit sets. */
     private static void loadVcf(final File dbSnpFile,
                                 final SAMSequenceDictionary sequenceDictionary,
-                                final Map<DbSnpBitSetUtil, Set<VariantType>> bitSetsToVariantTypes) {
+                                final Map<DbSnpBitSetUtil, Set<VariantType>> bitSetsToVariantTypes,
+                                final IntervalList intervals) {
 
-        final VCFFileReader variantReader = new VCFFileReader(dbSnpFile);
-        final CloseableIterator<VariantContext> variantIterator = variantReader.iterator();
+        final VCFFileReader variantReader = new VCFFileReader(dbSnpFile, intervals != null);
+        final Iterator<VariantContext> variantIterator;
+        if (intervals != null) {
+            variantIterator = new ByIntervalListVariantContextIterator(variantReader, intervals);
+        }
+        else {
+            variantIterator = variantReader.iterator();
+        }
 
         while (variantIterator.hasNext()) {
             final VariantContext kv = variantIterator.next();
@@ -107,13 +138,13 @@ public class DbSnpBitSetUtil {
                 final DbSnpBitSetUtil bitset            = tuple.getKey();
                 final Set<VariantType> variantsToMatch  = tuple.getValue();
 
-                BitSet bits = bitset.sequenceToBitSet.get(kv.getChr());
+                BitSet bits = bitset.sequenceToBitSet.get(kv.getContig());
                 if (bits == null) {
                     final int nBits;
                     if (sequenceDictionary == null) nBits = kv.getEnd() + 1;
-                    else nBits = sequenceDictionary.getSequence(kv.getChr()).getSequenceLength() + 1;
+                    else nBits = sequenceDictionary.getSequence(kv.getContig()).getSequenceLength() + 1;
                     bits = new BitSet(nBits);
-                    bitset.sequenceToBitSet.put(kv.getChr(), bits);
+                    bitset.sequenceToBitSet.put(kv.getContig(), bits);
                 }
                 if (variantsToMatch.isEmpty() ||
                         (kv.isSNP() && variantsToMatch.contains(VariantType.SNP)) ||
@@ -125,7 +156,6 @@ public class DbSnpBitSetUtil {
             }
         }
 
-        CloserUtil.close(variantIterator);
         CloserUtil.close(variantReader);
     }
 
@@ -134,13 +164,8 @@ public class DbSnpBitSetUtil {
      */
     public boolean isDbSnpSite(final String sequenceName, final int pos) {
         // When we have a dbSnpFile with no sequence dictionary, this line will be necessary
-        if (sequenceToBitSet.get(sequenceName) == null) {
-            return false;
-        }
-        if (pos > sequenceToBitSet.get(sequenceName).length()) {
-            return false;
-        }
-        return sequenceToBitSet.get(sequenceName).get(pos);
+        return sequenceToBitSet.get(sequenceName) != null &&
+                pos <= sequenceToBitSet.get(sequenceName).length() &&
+                sequenceToBitSet.get(sequenceName).get(pos);
     }
-
 }
diff --git a/src/java/picard/util/IlluminaUtil.java b/src/java/picard/util/IlluminaUtil.java
index 82e456f..03732af 100644
--- a/src/java/picard/util/IlluminaUtil.java
+++ b/src/java/picard/util/IlluminaUtil.java
@@ -200,7 +200,7 @@ public class IlluminaUtil {
      * @param barcodes
      * @return A single string representation of all the barcodes
      */
-    public static String barcodeSeqsToString(final String barcodes[]) {
+    public static String barcodeSeqsToString(final String[] barcodes) {
         return stringSeqsToString(barcodes, BARCODE_DELIMITER);
     }
 
@@ -209,11 +209,11 @@ public class IlluminaUtil {
      * @param barcodes
      * @return A single string representation of all the barcodes
      */
-    public static String barcodeSeqsToString(final byte barcodes[][]) {
+    public static String barcodeSeqsToString(final byte[][] barcodes) {
         return byteArrayToString(barcodes, BARCODE_DELIMITER);
     }
 
-    public static String stringSeqsToString(final String barcodes[], String delim) {
+    public static String stringSeqsToString(final String[] barcodes, String delim) {
         final StringBuilder sb = new StringBuilder();
         for (final String bc : barcodes) {
             if (sb.length() > 0) sb.append(delim);
@@ -227,8 +227,8 @@ public class IlluminaUtil {
      * @param barcodes
      * @return A single string representation of all the barcodes
      */
-    public static String byteArrayToString(final byte barcodes[][], String delim) {
-        final String bcs[] = new String[barcodes.length];
+    public static String byteArrayToString(final byte[][] barcodes, String delim) {
+        final String[] bcs = new String[barcodes.length];
         for (int i = 0; i < barcodes.length; i++) {
             bcs[i] = StringUtil.bytesToString(barcodes[i]);
         }
diff --git a/src/java/picard/util/IntervalListTools.java b/src/java/picard/util/IntervalListTools.java
index 7dc06d7..ec03bfd 100644
--- a/src/java/picard/util/IntervalListTools.java
+++ b/src/java/picard/util/IntervalListTools.java
@@ -295,7 +295,7 @@ public class IntervalListTools extends CommandLineProgram {
         if (BREAK_BANDS_AT_MULTIPLES_OF < 0) {
             errorMsgs.add("BREAK_BANDS_AT_MULTIPLES_OF must be greater than or equal to 0.");
         }
-        return errorMsgs.size() == 0 ? null : errorMsgs.toArray(new String[errorMsgs.size()]);
+        return errorMsgs.isEmpty() ? null : errorMsgs.toArray(new String[errorMsgs.size()]);
     }
 
     /**
diff --git a/src/java/picard/util/MathUtil.java b/src/java/picard/util/MathUtil.java
index bd04497..acaf80c 100644
--- a/src/java/picard/util/MathUtil.java
+++ b/src/java/picard/util/MathUtil.java
@@ -370,7 +370,7 @@ final public class MathUtil {
 
         /** Returns the log-representation of the provided decimal array. */
         public double[] getLogValue(final double[] nonLogArray) {
-            final double logArray[] = new double[nonLogArray.length];
+            final double[] logArray = new double[nonLogArray.length];
             for (int i = 0; i < nonLogArray.length; i++) {
                 logArray[i] = getLogValue(nonLogArray[i]);
             }
diff --git a/src/java/picard/vcf/CollectVariantCallingMetrics.java b/src/java/picard/vcf/CollectVariantCallingMetrics.java
index b436bf5..1a709f2 100644
--- a/src/java/picard/vcf/CollectVariantCallingMetrics.java
+++ b/src/java/picard/vcf/CollectVariantCallingMetrics.java
@@ -86,6 +86,9 @@ public class CollectVariantCallingMetrics extends CommandLineProgram {
     @Override
     protected int doWork() {
         IOUtil.assertFileIsReadable(INPUT);
+        IOUtil.assertFileIsReadable(DBSNP);
+        if (TARGET_INTERVALS != null) IOUtil.assertFileIsReadable(TARGET_INTERVALS);
+        if (SEQUENCE_DICTIONARY != null) IOUtil.assertFileIsReadable(SEQUENCE_DICTIONARY);
 
         final boolean requiresIndex = this.TARGET_INTERVALS != null || this.THREAD_COUNT > 1;
         final VCFFileReader variantReader = new VCFFileReader(INPUT, requiresIndex);
@@ -95,8 +98,10 @@ public class CollectVariantCallingMetrics extends CommandLineProgram {
         final SAMSequenceDictionary sequenceDictionary =
                 SAMSequenceDictionaryExtractor.extractDictionary(SEQUENCE_DICTIONARY == null ? INPUT : SEQUENCE_DICTIONARY);
 
+        final IntervalList targetIntervals = (TARGET_INTERVALS == null) ? null : IntervalList.fromFile(TARGET_INTERVALS).uniqued();
+
         log.info("Loading dbSNP file ...");
-        final DbSnpBitSetUtil.DbSnpBitSets dbsnp = DbSnpBitSetUtil.createSnpAndIndelBitSets(DBSNP, sequenceDictionary);
+        final DbSnpBitSetUtil.DbSnpBitSets dbsnp = DbSnpBitSetUtil.createSnpAndIndelBitSets(DBSNP, sequenceDictionary, targetIntervals);
 
         log.info("Starting iteration of variants.");
 
@@ -111,8 +116,8 @@ public class CollectVariantCallingMetrics extends CommandLineProgram {
                         .withInput(INPUT)
                         .multithreadingBy(THREAD_COUNT);
 
-        if (TARGET_INTERVALS != null) {
-            builder.limitingProcessedRegionsTo(IntervalList.fromFile(TARGET_INTERVALS).uniqued());
+        if (targetIntervals != null) {
+            builder.limitingProcessedRegionsTo(targetIntervals);
         }
 
         final CallingMetricAccumulator.Result result = builder.build().process();
@@ -274,7 +279,7 @@ public class CollectVariantCallingMetrics extends CommandLineProgram {
         public static void foldInto(final VariantCallingDetailMetrics target,
                                     final Collection<VariantCallingDetailMetrics> metrics) {
             VariantCallingSummaryMetrics.foldInto(target, metrics);
-            final Set<String> sampleAliases = new HashSet<String>();
+            final Set<String> sampleAliases = new HashSet<>();
             for (final VariantCallingDetailMetrics metric : metrics) {
                 target.numHets += metric.numHets;
                 target.numHomVar += metric.numHomVar;
diff --git a/src/java/picard/vcf/GenotypeConcordance.java b/src/java/picard/vcf/GenotypeConcordance.java
index 4f86ac2..0b25b97 100644
--- a/src/java/picard/vcf/GenotypeConcordance.java
+++ b/src/java/picard/vcf/GenotypeConcordance.java
@@ -176,7 +176,7 @@ public class GenotypeConcordance extends CommandLineProgram {
         // Note - If the user specifies to use INTERVALS, the code will fail if the vcfs are not indexed, so we set USE_VCF_INDEX to true and check that the vcfs are indexed.
         IOUtil.assertFileIsReadable(TRUTH_VCF);
         IOUtil.assertFileIsReadable(CALL_VCF);
-        final boolean usingIntervals = this.INTERVALS != null && this.INTERVALS.size() > 0;
+        final boolean usingIntervals = this.INTERVALS != null && !this.INTERVALS.isEmpty();
         final List<String> errors = new ArrayList<String>();
         if (usingIntervals) {
             USE_VCF_INDEX = true;
@@ -223,7 +223,7 @@ public class GenotypeConcordance extends CommandLineProgram {
         IOUtil.assertFileIsWritable(detailedMetricsFile);
         IOUtil.assertFileIsWritable(contingencyMetricsFile);
 
-        final boolean usingIntervals = this.INTERVALS != null && this.INTERVALS.size() > 0;
+        final boolean usingIntervals = this.INTERVALS != null && !this.INTERVALS.isEmpty();
         IntervalList intervals = null;
         SAMSequenceDictionary intervalsSamSequenceDictionary = null;
         if (usingIntervals) {
diff --git a/src/java/picard/vcf/filter/AlleleBalanceFilter.java b/src/java/picard/vcf/filter/AlleleBalanceFilter.java
index d33ed5a..340d3d8 100644
--- a/src/java/picard/vcf/filter/AlleleBalanceFilter.java
+++ b/src/java/picard/vcf/filter/AlleleBalanceFilter.java
@@ -64,7 +64,7 @@ public class AlleleBalanceFilter implements VariantFilter {
         final Map<List<Allele>, Counts> countsMap = new HashMap<List<Allele>, Counts>();
 
         for (final Genotype gt : ctx.getGenotypesOrderedByName()) {
-            if (gt.isNoCall() || !gt.isHet()) continue;
+            if (gt.isNoCall() || !gt.isHet() || !gt.hasAD()) continue;
 
             final List<Allele> alleles = gt.getAlleles();
             Counts counts = countsMap.get(alleles);
diff --git a/src/java/picard/vcf/filter/FilterVcf.java b/src/java/picard/vcf/filter/FilterVcf.java
index 0c277f5..ee9798b 100644
--- a/src/java/picard/vcf/filter/FilterVcf.java
+++ b/src/java/picard/vcf/filter/FilterVcf.java
@@ -20,12 +20,16 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
+ * 
  */
 package picard.vcf.filter;
 
 import htsjdk.samtools.SAMSequenceDictionary;
+import htsjdk.samtools.util.CloserUtil;
 import htsjdk.samtools.util.CollectionUtil;
 import htsjdk.samtools.util.IOUtil;
+import htsjdk.variant.variantcontext.VariantContext;
+import htsjdk.variant.variantcontext.filter.JavascriptVariantFilter;
 import htsjdk.variant.variantcontext.writer.VariantContextWriter;
 import htsjdk.variant.variantcontext.writer.VariantContextWriterBuilder;
 import htsjdk.variant.vcf.VCFFileReader;
@@ -42,12 +46,15 @@ import picard.cmdline.StandardOptionDefinitions;
 import picard.cmdline.programgroups.VcfOrBcf;
 
 import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
 import java.util.List;
 
 /**
  * Applies a set of hard filters to Variants and to Genotypes within a VCF.
  *
  * @author Tim Fennell
+ * @author Pierre Lindenbaum added the javascript filter in 2016 
  */
 @CommandLineProgramProperties(
         usage = "Applies one or more hard filters to a VCF file to filter out genotypes and variants.",
@@ -77,6 +84,15 @@ public class FilterVcf extends CommandLineProgram {
 
     @Option(doc="The minimum QD value to accept or otherwise filter out the variant.")
     public double MIN_QD = 0;
+    
+	@Option(shortName = "JS", doc = "Filters a VCF file with a javascript expression interpreted by the java javascript engine. "
+	        + " The script puts the following variables in the script context: "
+	        + " 'variant' a VariantContext ( https://samtools.github.io/htsjdk/javadoc/htsjdk/htsjdk/variant/variantcontext/VariantContext.html ) and "
+	        + " 'header' a VCFHeader ( https://samtools.github.io/htsjdk/javadoc/htsjdk/htsjdk/variant/vcf/VCFHeader.html )."
+	        + " Last value of the script should be a boolean to tell wether we should accept or reject the record.",
+	        optional = true)
+	public File JAVASCRIPT_FILE = null;
+
 
     /** Constructor to default to having index creation on. */
     public FilterVcf() { this.CREATE_INDEX = true; }
@@ -91,44 +107,93 @@ public class FilterVcf extends CommandLineProgram {
         IOUtil.assertFileIsReadable(INPUT);
         IOUtil.assertFileIsWritable(OUTPUT);
 
-        final List<VariantFilter>  variantFilters = CollectionUtil.makeList(new AlleleBalanceFilter(MIN_AB), new FisherStrandFilter(MAX_FS), new QdFilter(MIN_QD));
-        final List<GenotypeFilter> genotypeFilters = CollectionUtil.makeList(new GenotypeQualityFilter(MIN_GQ), new DepthFilter(MIN_DP));
-        final VCFFileReader in = new VCFFileReader(INPUT, false);
-        final FilterApplyingVariantIterator iterator = new FilterApplyingVariantIterator(in.iterator(), variantFilters, genotypeFilters);
-
-        final VCFHeader header = in.getFileHeader();
-        // If the user is writing to a .bcf or .vcf, VariantContextBuilderWriter requires a Sequence Dictionary.  Make sure that the
-        // Input VCF has one.
-        final VariantContextWriterBuilder variantContextWriterBuilder = new VariantContextWriterBuilder();
-        if (isVcfOrBcf(OUTPUT)) {
-            final SAMSequenceDictionary sequenceDictionary = header.getSequenceDictionary();
-            if (sequenceDictionary == null) {
-                throw new PicardException("The input vcf must have a sequence dictionary in order to create indexed vcf or bcfs.");
-            }
-            variantContextWriterBuilder.setReferenceDictionary(sequenceDictionary);
-        }
-        final VariantContextWriter out = variantContextWriterBuilder.setOutputFile(OUTPUT).build();
-        header.addMetaDataLine(new VCFFilterHeaderLine("AllGtsFiltered", "Site filtered out because all genotypes are filtered out."));
-        header.addMetaDataLine(new VCFFormatHeaderLine("FT", VCFHeaderLineCount.UNBOUNDED, VCFHeaderLineType.String, "Genotype filters."));
-        for (final VariantFilter filter : variantFilters) {
-            for (final VCFFilterHeaderLine line : filter.headerLines()) {
-                header.addMetaDataLine(line);
-            }
-        }
-
-        out.writeHeader(in.getFileHeader());
-
-        while (iterator.hasNext()) {
-            out.add(iterator.next());
+        VCFFileReader in = null;
+        VariantContextWriter out = null;
+        try {// try/finally used to close 'in' and 'out'
+	        in = new VCFFileReader(INPUT, false);
+	        final List<VariantFilter>  variantFilters = new ArrayList<VariantFilter>(4);
+	        variantFilters.add(new AlleleBalanceFilter(MIN_AB));
+	        variantFilters.add(new FisherStrandFilter(MAX_FS));
+	        variantFilters.add(new QdFilter(MIN_QD));
+	        if( JAVASCRIPT_FILE != null) {
+	            try {
+	                variantFilters.add(new VariantContextJavascriptFilter(JAVASCRIPT_FILE, in.getFileHeader()));
+	            } catch(final IOException error) {
+	                throw new PicardException("javascript-related error", error);
+	            }
+	        }
+	        final List<GenotypeFilter> genotypeFilters = CollectionUtil.makeList(new GenotypeQualityFilter(MIN_GQ), new DepthFilter(MIN_DP));
+	        @SuppressWarnings("resource")
+			final FilterApplyingVariantIterator iterator = new FilterApplyingVariantIterator(in.iterator(), variantFilters, genotypeFilters);
+	
+	        final VCFHeader header = in.getFileHeader();
+	        // If the user is writing to a .bcf or .vcf, VariantContextBuilderWriter requires a Sequence Dictionary.  Make sure that the
+	        // Input VCF has one.
+	        final VariantContextWriterBuilder variantContextWriterBuilder = new VariantContextWriterBuilder();
+	        if (isVcfOrBcf(OUTPUT)) {
+	            final SAMSequenceDictionary sequenceDictionary = header.getSequenceDictionary();
+	            if (sequenceDictionary == null) {
+	                throw new PicardException("The input vcf must have a sequence dictionary in order to create indexed vcf or bcfs.");
+	            }
+	            variantContextWriterBuilder.setReferenceDictionary(sequenceDictionary);
+	        }
+	        out = variantContextWriterBuilder.setOutputFile(OUTPUT).build();
+	        header.addMetaDataLine(new VCFFilterHeaderLine("AllGtsFiltered", "Site filtered out because all genotypes are filtered out."));
+	        header.addMetaDataLine(new VCFFormatHeaderLine("FT", VCFHeaderLineCount.UNBOUNDED, VCFHeaderLineType.String, "Genotype filters."));
+	        for (final VariantFilter filter : variantFilters) {
+	            for (final VCFFilterHeaderLine line : filter.headerLines()) {
+	                header.addMetaDataLine(line);
+	            }
+	        }
+	
+	        out.writeHeader(in.getFileHeader());
+	
+	        while (iterator.hasNext()) {
+	            out.add(iterator.next());
+	        }
+	        return 0;
+        } finally {
+        	CloserUtil.close(out);
+        	CloserUtil.close(in);
         }
-
-        out.close();
-        in.close();
-        return 0;
     }
 
     private boolean isVcfOrBcf(final File file) {
         final String fileName = file.getName();
         return fileName.endsWith(".vcf") || fileName.endsWith(".bcf");
     }
+    
+    /** Javascript filter implementing VariantFilter */
+    private static class VariantContextJavascriptFilter
+            extends JavascriptVariantFilter
+            implements VariantFilter {
+        /** filter name */
+        private final String filterName;
+        /** script file */
+        private final File scriptFile;
+        
+        private VariantContextJavascriptFilter(final File scriptFile, final VCFHeader header) throws IOException {
+           super(scriptFile, header);
+           this.scriptFile = scriptFile;
+           /* create filter name using file basename */
+           String fname = IOUtil.basename(scriptFile);
+           if(fname.isEmpty()) fname="JSFILTER";
+           this.filterName = fname;
+        }
+
+        /**
+         * returns the filterName if the javascript doesn't accept the variant ,
+         * null otherwise
+         */
+        @Override
+        public String filter(final VariantContext ctx) {
+            return (super.accept(ctx) ? null : this.filterName );
+        }
+
+        @Override
+        public List<VCFFilterHeaderLine> headerLines() {
+            return CollectionUtil.makeList(
+                    new VCFFilterHeaderLine(this.filterName, "Variant Filtered by Javascript file " + this.scriptFile));
+        }
+    }
 }
diff --git a/src/java/picard/vcf/processor/VcfFileSegment.java b/src/java/picard/vcf/processor/VcfFileSegment.java
index 104aabb..ff0ca4e 100644
--- a/src/java/picard/vcf/processor/VcfFileSegment.java
+++ b/src/java/picard/vcf/processor/VcfFileSegment.java
@@ -52,7 +52,7 @@ public abstract class VcfFileSegment {
         return new SequenceSizedChunk(sequence, vcf);
     }
     
-    static class SequenceSizedChunk extends VcfFileSegment {
+    static final class SequenceSizedChunk extends VcfFileSegment {
         final SAMSequenceRecord sequence;
         final File vcf;
 
diff --git a/src/java/picard/vcf/processor/VcfFileSegmentGenerator.java b/src/java/picard/vcf/processor/VcfFileSegmentGenerator.java
index e8a639e..8955883 100644
--- a/src/java/picard/vcf/processor/VcfFileSegmentGenerator.java
+++ b/src/java/picard/vcf/processor/VcfFileSegmentGenerator.java
@@ -118,7 +118,7 @@ public abstract class VcfFileSegmentGenerator {
      *
      * @author mccowan
      */
-    static class WidthLimitingDecorator extends VcfFileSegmentGenerator {
+    static final class WidthLimitingDecorator extends VcfFileSegmentGenerator {
         final VcfFileSegmentGenerator underlyingStrategy;
         final long width;
 
@@ -135,7 +135,7 @@ public abstract class VcfFileSegmentGenerator {
          * The thing that does the work; accepts a {@link VcfFileSegment} (produced by the parent {@link VcfFileSegmentGenerator}) and breaks
          * it down into subsegments.
          */
-        private class VcfFileSegmentSubdivider implements Iterable<VcfFileSegment> {
+        private final class VcfFileSegmentSubdivider implements Iterable<VcfFileSegment> {
             final VcfFileSegment basis;
 
             private VcfFileSegmentSubdivider(final VcfFileSegment basis) {
diff --git a/src/tests/java/picard/analysis/CollectAlignmentSummaryMetricsTest.java b/src/tests/java/picard/analysis/CollectAlignmentSummaryMetricsTest.java
index 11b1fc4..58e2da9 100644
--- a/src/tests/java/picard/analysis/CollectAlignmentSummaryMetricsTest.java
+++ b/src/tests/java/picard/analysis/CollectAlignmentSummaryMetricsTest.java
@@ -28,6 +28,7 @@ import htsjdk.samtools.metrics.MetricsFile;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 import picard.cmdline.CommandLineProgramTest;
+import picard.util.TestNGUtil;
 
 import java.io.File;
 import java.io.FileReader;
@@ -524,7 +525,10 @@ public class CollectAlignmentSummaryMetricsTest extends CommandLineProgramTest {
 
         for (final AlignmentSummaryMetrics metrics : output.getMetrics()) {
             if (metrics.CATEGORY == AlignmentSummaryMetrics.Category.FIRST_OF_PAIR) {
-                Assert.assertEquals(metrics.PCT_CHIMERAS, 0.8);
+                TestNGUtil.compareDoubleWithAccuracy(metrics.PCT_CHIMERAS, 5D / 6, 0.0001);
+            }
+            if (metrics.CATEGORY == AlignmentSummaryMetrics.Category.SECOND_OF_PAIR) {
+                TestNGUtil.compareDoubleWithAccuracy(metrics.PCT_CHIMERAS, 3D / 6, 0.0001);
             }
         }
     }
diff --git a/src/tests/java/picard/cmdline/CommandLineParserTest.java b/src/tests/java/picard/cmdline/CommandLineParserTest.java
index f136d08..4a78ff3 100644
--- a/src/tests/java/picard/cmdline/CommandLineParserTest.java
+++ b/src/tests/java/picard/cmdline/CommandLineParserTest.java
@@ -29,7 +29,11 @@ import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 import picard.cmdline.programgroups.Testing;
 
+import java.io.ByteArrayOutputStream;
 import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -977,4 +981,162 @@ public class CommandLineParserTest {
         Assert.assertTrue(propsSet.STRING3.equals("String3Supplied"));
         Assert.assertTrue(((StaticParent) propsSet).STRING3.equals("String3Supplied"));
     }
+
+
+    @DataProvider(name = "testHtmlEscapeData")
+    public Object[][] testHtmlEscapeData() {
+        final List<Object[]> retval = new ArrayList<>();
+
+        retval.add(new Object[]{"<", "<"});
+        retval.add(new Object[]{"x<y", "x<y"});
+        retval.add(new Object[]{"x<y<z", "x<y<z"});
+        retval.add(new Object[]{"\n", "<p>"});
+        retval.add(new Object[]{"<html> x<y </html> y< <strong> x </strong>","<html> x<y </html> y< <strong> x </strong>"});
+
+        return retval.toArray(new Object[0][]);
+    }
+
+//    @Test(dataProvider = "testHtmlEscapeData")
+//    public void testHtmlEscape(final String text, final String expected) {
+//        Assert.assertEquals(CommandLineParser.htmlEscape(text), expected, "problems");
+//    }
+
+    @Test(dataProvider = "testHtmlEscapeData")
+    public void testHtmlUnescape(final String expected, final String html) {
+        Assert.assertEquals(CommandLineParser.htmlUnescape(html), expected, "problems");
+    }
+
+    @DataProvider(name = "testHTMLConverter")
+    public Object[][] testHTMLConverterData() {
+        final List<Object[]> retval = new ArrayList<>();
+
+        retval.add(new Object[]{"hello", "hello"});
+        retval.add(new Object[]{"", ""});
+        retval.add(new Object[]{"hi</th>bye", "hi\tbye"});
+        retval.add(new Object[]{"hi<th>bye", "hibye"});
+        retval.add(new Object[]{"hi<li>bye", "hi - bye"});
+        retval.add(new Object[]{"hi<NOT_A_REAL_TAG>bye", "hibye"});
+        retval.add(new Object[]{"</h4><pre>", "\n\n"});
+        retval.add(new Object[]{"<a href=\"http://go.here.org\"> string</ a >", " string (http://go.here.org)"});
+        retval.add(new Object[]{"<a href=\"http://go.here.org\" > string</ a>", " string (http://go.here.org)"});
+        retval.add(new Object[]{"< a href=\"http://go.here.org\"> string<a />", " string (http://go.here.org)"});
+
+
+        //for some reason, the next test seems to break intelliJ, but it works on the commandline
+        retval.add(new Object[]{"hi</li>bye", "hi\nbye"});
+
+        retval.add(new Object[]{"Using read outputs from high throughput sequencing (HTS) technologies, this tool provides " +
+                "metrics regarding the quality of read alignments to a reference sequence, as well as the proportion of the reads " +
+                "that passed machine signal-to-noise threshold quality filters (Illumina)." +
+                "<h4>Usage example:</h4>" +
+                "<pre>" +
+                "    java -jar picard.jar CollectAlignmentSummaryMetrics \\<br />" +
+                "          R=reference_sequence.fasta \\<br />" +
+                "          I=input.bam \\<br />" +
+                "          O=output.txt" +
+                "</pre>" +
+                "Please see <a href='http://broadinstitute.github.io/picard/picard-metric-definitions.html#AlignmentSummaryMetrics'>" +
+                "the AlignmentSummaryMetrics documentation</a> for detailed explanations of each metric. <br /> <br />" +
+                "Additional information about Illumina's quality filters can be found in the following documents on the Illumina website:" +
+                "<ul><li><a href=\"http://support.illumina.com/content/dam/illumina-marketing/documents/products/technotes/hiseq-x-percent-pf-technical-note-770-2014-043.pdf\">" +
+                "hiseq-x-percent-pf-technical-note</a></li>" +
+                "<li><a href=\"http://support.illumina.com/content/dam/illumina-support/documents/documentation/system_documentation/hiseqx/hiseq-x-system-guide-15050091-d.pdf\">" +
+                "hiseq-x-system-guide</a></li></ul>" +
+                "<hr />",
+
+                "Using read outputs from high throughput sequencing (HTS) technologies, this tool provides " +
+                        "metrics regarding the quality of read alignments to a reference sequence, as well as the proportion of the reads " +
+                        "that passed machine signal-to-noise threshold quality filters (Illumina)." +
+                        "\nUsage example:\n" +
+                        "\n" +
+                        "    java -jar picard.jar CollectAlignmentSummaryMetrics \\\n" +
+                        "          R=reference_sequence.fasta \\\n" +
+                        "          I=input.bam \\\n" +
+                        "          O=output.txt" +
+                        "\n" +
+                        "Please see the AlignmentSummaryMetrics documentation (http://broadinstitute.github.io/picard/picard-metric-definitions.html#AlignmentSummaryMetrics) for detailed explanations of each metric. \n \n" +
+                        "Additional information about Illumina's quality filters can be found in the following documents on the Illumina website:" +
+                        "\n" +
+                        " - hiseq-x-percent-pf-technical-note (http://support.illumina.com/content/dam/illumina-marketing/documents/products/technotes/hiseq-x-percent-pf-technical-note-770-2014-043.pdf)\n" +
+                        " - hiseq-x-system-guide (http://support.illumina.com/content/dam/illumina-support/documents/documentation/system_documentation/hiseqx/hiseq-x-system-guide-15050091-d.pdf)\n\n" +
+                        "\n"});
+
+        return retval.toArray(new Object[0][]);
+    }
+
+    @Test(dataProvider = "testHTMLConverter")
+    public void testHTMLConverter(String input, String expected) {
+        final String converted = CommandLineParser.convertFromHtml(input);
+        Assert.assertEquals(converted, expected, "common part:\"" + expected.substring(0, lengthOfCommonSubstring(converted, expected)) + "\"\n\n");
+    }
+
+    @CommandLineProgramProperties(
+            usage = TestParserFail.USAGE_SUMMARY + TestParserFail.USAGE_DETAILS,
+            usageShort = TestParserFail.USAGE_SUMMARY,
+            programGroup = Testing.class
+    )
+    protected class TestParserFail extends CommandLineProgram {
+
+        static public final String USAGE_DETAILS = "blah &blah; blah ";
+        static public final String USAGE_SUMMARY = "This tool offers.....";
+
+        @Override
+        protected int doWork() {return 0;}
+    }
+
+    @CommandLineProgramProperties(
+            usage = TestParserSucceed.USAGE_SUMMARY + TestParserSucceed.USAGE_DETAILS,
+            usageShort = TestParserSucceed.USAGE_SUMMARY,
+            programGroup = Testing.class
+    )
+
+    protected class TestParserSucceed extends CommandLineProgram {
+
+        static public final String USAGE_DETAILS = "This is the first row <p>And this is the second";
+        static public final String USAGE_SUMMARY = " X < Y ";
+
+        @Override
+        protected int doWork() {return 0;}
+    }
+
+    @Test(expectedExceptions = AssertionError.class)
+    public void testNonAsciiAssertion() {
+        TestParserFail testparserFail = new TestParserFail();
+        testparserFail.parseArgs(new String[]{});
+
+        PrintStream stream = new PrintStream(new NullOutputStream());
+        testparserFail.getCommandLineParser().usage(stream, true);
+    }
+
+    @Test
+    public void testNonAsciiConverted() {
+        TestParserSucceed testparserSucceed = new TestParserSucceed();
+        testparserSucceed.parseArgs(new String[]{});
+
+        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+        PrintStream stream = new PrintStream(byteArrayOutputStream);
+        testparserSucceed.getCommandLineParser().usage(stream, true);
+
+        String expected = "USAGE: TestParserSucceed [options]\n" +
+                "\n" +
+                "Documentation: http://broadinstitute.github.io/picard/command-line-overview.html#TestParserSucceed\n" +
+                "\n" +
+                " X < Y This is the first row \n" +
+                "And this is the second";
+        Assert.assertEquals(byteArrayOutputStream.toString().substring(0, expected.length()), expected);
+    }
+
+    static private int lengthOfCommonSubstring(String lhs, String rhs) {
+        int i = 0;
+        while (i < Math.min(lhs.length(), rhs.length()) && lhs.charAt(i) == rhs.charAt(i)) i++;
+
+        return i;
+    }
+
+    private class NullOutputStream extends OutputStream {
+        @Override
+        public void write(final int b) throws IOException {
+
+        }
+    }
 }
diff --git a/src/tests/java/picard/illumina/CheckIlluminaDirectoryTest.java b/src/tests/java/picard/illumina/CheckIlluminaDirectoryTest.java
index 7828b22..d4de278 100644
--- a/src/tests/java/picard/illumina/CheckIlluminaDirectoryTest.java
+++ b/src/tests/java/picard/illumina/CheckIlluminaDirectoryTest.java
@@ -100,7 +100,7 @@ public class CheckIlluminaDirectoryTest extends CommandLineProgramTest {
             dataTypeArgs[i + 5] = "DT=" + dataTypes[i];
         }
 
-        if (filterTiles.size() > 0) {
+        if (!filterTiles.isEmpty()) {
             final int start = dataTypes.length + 5;
             for (int i = start; i < dataTypeArgs.length; i++) {
                 dataTypeArgs[i] = "T=" + filterTiles.get(i - start);
diff --git a/src/tests/java/picard/sam/FilterSamReadsTest.java b/src/tests/java/picard/sam/FilterSamReadsTest.java
new file mode 100644
index 0000000..c611246
--- /dev/null
+++ b/src/tests/java/picard/sam/FilterSamReadsTest.java
@@ -0,0 +1,77 @@
+/*
+ * The MIT License
+ *
+ * Pierre Lindenbaum - Institut du Thorax - 2016
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package picard.sam;
+
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import htsjdk.samtools.SAMRecordIterator;
+import htsjdk.samtools.SamReader;
+import htsjdk.samtools.SamReaderFactory;
+import picard.cmdline.CommandLineProgramTest;
+
+import java.io.File;
+
+public class FilterSamReadsTest extends CommandLineProgramTest {
+    @Override
+    public String getCommandLineProgramName() {
+        return FilterSamReads.class.getSimpleName();
+    }
+
+    @DataProvider(name = "dataTestJsFilter")
+    public Object[][] dataTestJsFilter() {
+        return new Object[][]{
+                {"testdata/picard/sam/aligned.sam","testdata/picard/sam/FilterSamReads/filterOddStarts.js",3},
+                {"testdata/picard/sam/aligned.sam","testdata/picard/sam/FilterSamReads/filterReadsWithout5primeSoftClip.js", 0}
+        };
+    }
+    
+    /**
+     * filters a SAM using a javascript filter
+     */
+    @Test(dataProvider = "dataTestJsFilter")
+    public void testJavaScriptFilters(final String samFilename, final String javascriptFilename,final int expectNumber) throws Exception {
+        // input as SAM file 
+        final File inputSam = new File(samFilename);
+        final File javascriptFile = new File(javascriptFilename);
+        //loop over javascript filters
+        final FilterSamReads program = new FilterSamReads();
+        program.INPUT = inputSam;
+        program.OUTPUT = File.createTempFile("FilterSamReads.output.", ".sam");
+        program.OUTPUT.deleteOnExit();
+        program.FILTER = FilterSamReads.Filter.includeJavascript;
+        program.JAVASCRIPT_FILE = javascriptFile;
+        Assert.assertEquals(program.doWork(),0);
+        
+        //count reads
+        final SamReader samReader = SamReaderFactory.makeDefault().open(program.OUTPUT);
+        final SAMRecordIterator iter = samReader.iterator();
+        int count = 0;
+        while(iter.hasNext()) { iter.next(); ++ count; }
+        iter.close();
+        samReader.close();
+        Assert.assertEquals(count, expectNumber);
+    	}
+	}
diff --git a/src/tests/java/picard/util/BedToIntervalListTest.java b/src/tests/java/picard/util/BedToIntervalListTest.java
index 6ad561e..191bc4b 100644
--- a/src/tests/java/picard/util/BedToIntervalListTest.java
+++ b/src/tests/java/picard/util/BedToIntervalListTest.java
@@ -16,7 +16,7 @@ import java.io.InputStream;
  */
 public class BedToIntervalListTest {
 
-    private final String TEST_DATA_DIR = "testdata/picard/util/BedToIntervalListTest";
+    private static final String TEST_DATA_DIR = "testdata/picard/util/BedToIntervalListTest";
 
     private void doTest(final String inputBed, final String header) throws IOException, SAMException {
         final File outputFile  = File.createTempFile("bed_to_interval_list_test.", ".interval_list");
diff --git a/src/tests/java/picard/util/IntervalListToBedTest.java b/src/tests/java/picard/util/IntervalListToBedTest.java
index 8626d78..03cfeaa 100644
--- a/src/tests/java/picard/util/IntervalListToBedTest.java
+++ b/src/tests/java/picard/util/IntervalListToBedTest.java
@@ -11,7 +11,7 @@ import java.util.List;
  * Tests for IntervalListToBed
  */
 public class IntervalListToBedTest {
-    private final String TEST_DATA_DIR = "testdata/picard/util/";
+    private static final String TEST_DATA_DIR = "testdata/picard/util/";
     private final File INTERVAL_LIST = new File(TEST_DATA_DIR, "interval_list_to_bed_test.interval_list");
     private final File BED_FILE      = new File(TEST_DATA_DIR, "interval_list_to_bed_test.bed");
 
diff --git a/src/tests/java/picard/vcf/SortVcfsTest.java b/src/tests/java/picard/vcf/SortVcfsTest.java
index c2836e1..7808cb3 100644
--- a/src/tests/java/picard/vcf/SortVcfsTest.java
+++ b/src/tests/java/picard/vcf/SortVcfsTest.java
@@ -10,7 +10,6 @@ import picard.cmdline.CommandLineProgram;
 
 import java.io.File;
 import java.io.IOException;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
diff --git a/src/tests/java/picard/vcf/UpdateVcfSequenceDictionaryTest.java b/src/tests/java/picard/vcf/UpdateVcfSequenceDictionaryTest.java
index e0c8bed..3f8f4d9 100644
--- a/src/tests/java/picard/vcf/UpdateVcfSequenceDictionaryTest.java
+++ b/src/tests/java/picard/vcf/UpdateVcfSequenceDictionaryTest.java
@@ -23,16 +23,11 @@
  */
 package picard.vcf;
 
-import htsjdk.samtools.SAMSequenceDictionary;
-import htsjdk.samtools.util.CloserUtil;
 import htsjdk.samtools.util.IOUtil;
 import htsjdk.variant.utils.SAMSequenceDictionaryExtractor;
-import htsjdk.variant.vcf.VCFFileReader;
-import htsjdk.variant.vcf.VCFHeader;
 import org.testng.Assert;
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.Test;
-import picard.PicardException;
 
 import java.io.File;
 
diff --git a/src/tests/java/picard/vcf/TestFilterVcf.java b/src/tests/java/picard/vcf/filter/TestFilterVcf.java
similarity index 87%
rename from src/tests/java/picard/vcf/TestFilterVcf.java
rename to src/tests/java/picard/vcf/filter/TestFilterVcf.java
index 306488b..cb9a1cd 100644
--- a/src/tests/java/picard/vcf/TestFilterVcf.java
+++ b/src/tests/java/picard/vcf/filter/TestFilterVcf.java
@@ -23,6 +23,7 @@
  */
 package picard.vcf.filter;
 
+import htsjdk.samtools.util.CloseableIterator;
 import htsjdk.samtools.util.CollectionUtil;
 import htsjdk.samtools.util.ListMap;
 import htsjdk.variant.variantcontext.VariantContext;
@@ -30,8 +31,10 @@ import htsjdk.variant.vcf.VCFFileReader;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 import picard.PicardException;
+import picard.vcf.filter.FilterVcf;
 
 import java.io.File;
+import java.io.PrintWriter;
 import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
@@ -43,6 +46,43 @@ public class TestFilterVcf {
     private final File INPUT = new File("testdata/picard/vcf/filter/testFiltering.vcf");
     private final File BAD_INPUT = new File("testdata/picard/vcf/filter/testFilteringNoSeqDictionary.vcf");
 
+
+    /* write content of javascript in the returned file */
+	private File quickJavascriptFilter(String content) throws Exception {
+		final File out = File.createTempFile("jsfilter", ".js");
+		out.deleteOnExit();
+		try (final PrintWriter pw = new PrintWriter(out)) {
+			pw.println(content);
+		}
+		return out;
+	}
+
+	@Test
+	public void testJavaScript() throws Exception {
+		final File out = File.createTempFile("filterVcfTestJS.", ".vcf");
+		out.deleteOnExit();
+		final FilterVcf filterer = new FilterVcf();
+		filterer.INPUT = INPUT;
+		filterer.OUTPUT = out;
+		filterer.JAVASCRIPT_FILE = quickJavascriptFilter("variant.getStart()%5 != 0");
+
+		final int retval = filterer.doWork();
+		Assert.assertEquals(retval, 0);
+		
+		//count the number of reads
+		final int expectedNumber = 4;
+		int count=0;
+		VCFFileReader in = new VCFFileReader(filterer.OUTPUT, false);
+		CloseableIterator<VariantContext> iter = in.iterator();
+		while(iter.hasNext()) {
+			final VariantContext ctx = iter.next();
+			count += (ctx.isFiltered()?1:0);
+		}
+		iter.close();
+		in.close();
+		Assert.assertEquals(count, expectedNumber);
+	}
+    
     /** Returns a sorted copy of the supplied set, for safer comparison. */
     <T extends Comparable> SortedSet<T> sorted(Set<T> in) { return new TreeSet<T>(in); }
 
@@ -55,6 +95,7 @@ public class TestFilterVcf {
                 Assert.fail("Context should not have been filtered: " + ctx.toString());
             }
         }
+        in.close();
     }
 
     /** Tests that sites with a het allele balance < 0.4 are marked as filtered out. */
diff --git a/src/tests/java/picard/vcf/processor/VcfFileSegmentGeneratorTest.java b/src/tests/java/picard/vcf/processor/VcfFileSegmentGeneratorTest.java
index c41eb83..26d25f3 100644
--- a/src/tests/java/picard/vcf/processor/VcfFileSegmentGeneratorTest.java
+++ b/src/tests/java/picard/vcf/processor/VcfFileSegmentGeneratorTest.java
@@ -39,7 +39,7 @@ public class VcfFileSegmentGeneratorTest {
     final static Log LOG = Log.getInstance(VcfFileSegmentGeneratorTest.class);
     
     final File VCF_WITH_LOGS_OF_GAPS =  new File("testdata/picard/vcf/chunking/multi_allelic_at_10M.vcf");
-    final int TEN_MILLION = (int) 10e6;
+    static final int TEN_MILLION = (int) 10e6;
 
     @Test
     public void ensureOverlapExclusionTest() {
diff --git a/testdata/picard/sam/FilterSamReads/filterOddStarts.js b/testdata/picard/sam/FilterSamReads/filterOddStarts.js
new file mode 100644
index 0000000..f0007f6
--- /dev/null
+++ b/testdata/picard/sam/FilterSamReads/filterOddStarts.js
@@ -0,0 +1,2 @@
+/** reads mapped and having start%2 = 0 */
+!record.getReadUnmappedFlag() && record.getStart()%2==0
diff --git a/testdata/picard/sam/FilterSamReads/filterReadsWithout5primeSoftClip.js b/testdata/picard/sam/FilterSamReads/filterReadsWithout5primeSoftClip.js
new file mode 100644
index 0000000..4a16340
--- /dev/null
+++ b/testdata/picard/sam/FilterSamReads/filterReadsWithout5primeSoftClip.js
@@ -0,0 +1,10 @@
+/** reads having a soft clip in 5' larger than 2 bases  */
+function accept(rec) {
+	if( rec.getReadUnmappedFlag()) return false;
+	var cigar = rec.getCigar();
+	if( cigar == null ) return false;
+	var ce = cigar.getCigarElement(0);
+	return ce.getOperator().name()=="S" && ce.length()>2;
+	}
+
+accept(record);
diff --git a/testdata/picard/sam/summary_alignment_stats_test_chimeras.sam b/testdata/picard/sam/summary_alignment_stats_test_chimeras.sam
index 95143c9..583072e 100644
--- a/testdata/picard/sam/summary_alignment_stats_test_chimeras.sam
+++ b/testdata/picard/sam/summary_alignment_stats_test_chimeras.sam
@@ -8,13 +8,15 @@
 @SQ	SN:chr7	LN:202
 @SQ	SN:chr8	LN:202
 @RG	ID:0	SM:Hi,Momma!	LB:whatever	PU:me	PL:ILLUMINA
-SL-XAV:1:1:0:764#0/1	113	chr1	1	255	6M	chr1	10	10	TTCATG	&/,&-.
-SL-XAV:1:1:0:764#0/1	177	chr1	10	255	6M	chr1	1	10	TTCATG	&/,&-.
-SL-XAV:1:1:0:800#0/1	81	chr2	1	255	6M	chr2	10	10	TTCATG	&/,&-.
-SL-XAV:1:1:0:800#0/1	161	chr2	10	255	6M	chr2	1	10	TTCATG	&/,&-.
-SL-XAV:1:1:0:877#0/1	97	chr3	1	255	6M	chr4	10	10	TTCATG	&/,&-.
-SL-XAV:1:1:0:877#0/1	145	chr4	10	255	6M	chr3	1	10	TTCATG	&/,&-.
-SL-XAV:1:1:0:940#0/1	97	chr5	1	255	6M	chr5	10	10	TTCATG	&/,&-.
-SL-XAV:1:1:0:940#0/1	145	chr5	10	255	6M	chr5	1	10	TTCATG	&/,&-.
-SL-XAV:1:1:0:999#0/1	97	chr6	1	255	6M	chr5	10	60	TTCATG	&/,&-.
-SL-XAV:1:1:0:999#0/1	145	chr6	60	255	6M	chr5	1	60	TTCATG	&/,&-.
+SL-XAV:1:1:0:764#0/1	0113	chr1	1	255	6M	chr1	10	10	TTCATG	&/,&-.	OT:Z:left pointing
+SL-XAV:1:1:0:764#0/1	0177	chr1	10	255	6M	chr1	1	10	TTCATG	&/,&-.	OT:Z:normal
+SL-XAV:1:1:0:800#0/1	0081	chr2	1	255	6M	chr2	10	10	TTCATG	&/,&-.	OT:Z:outtie
+SL-XAV:1:1:0:800#0/1	00161	chr2	10	255	6M	chr2	1	10	TTCATG	&/,&-.	OT:Z:outtie
+SL-XAV:1:1:0:877#0/1	0097	chr3	1	255	6M	chr4	10	10	TTCATG	&/,&-.	OT:Z:chimeric
+SL-XAV:1:1:0:877#0/1	00145	chr4	10	255	6M	chr3	1	10	TTCATG	&/,&-.	OT:Z:chimeric
+SL-XAV:1:1:0:940#0/1	0097	chr5	1	255	6M	chr5	10	10	TTCATG	&/,&-.	OT:Z:normal
+SL-XAV:1:1:0:940#0/1	00145	chr5	10	255	6M	chr5	1	10	TTCATG	&/,&-.	OT:Z:normal
+SL-XAV:1:1:0:999#0/1	0097	chr6	1	255	6M	chr5	10	60	TTCATG	&/,&-.	OT:Z:chimeric
+SL-XAV:1:1:0:999#0/1	00145	chr6	60	255	6M	chr5	1	60	TTCATG	&/,&-.	OT:Z:chimeric
+SL-XAV:1:1:0:430#0/1	0097	chr7	1	255	6M	chr5	10	10	TTCATG	&/,&-.	OT:Z:hasSa SA:Z:gotSA
+SL-XAV:1:1:0:430#0/1	00145	chr7	10	255	6M	chr5	1	10	TTCATG	&/,&-.	OT:Z:normal

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/picard-tools.git



More information about the debian-med-commit mailing list