merge in oc-release history after reset to master
diff --git a/BUILDING.txt b/BUILDING.txt
new file mode 100644
index 0000000..8d6ee82
--- /dev/null
+++ b/BUILDING.txt
@@ -0,0 +1,19 @@
+                    **********************

+********************* Building Hamcrest *********************

+                    **********************

+

+--[ Build requirements ]-------------------------------------

+

+* JDK 1.7

+

+* Gradle

+

+--[ Building from the command line ]-------------------------

+

+Execute the default ant target:

+  ./gradlew clean build javadoc

+

+This will do a full clean build, run all tests and (if

+successful) package up a distribution. The resulting builds

+reside in the 'build' directory.

+

diff --git a/CHANGES.txt b/CHANGES.txt
new file mode 100644
index 0000000..f0a392b
--- /dev/null
+++ b/CHANGES.txt
@@ -0,0 +1,135 @@
+== Version 2.0.0.0 ==

+

+A new beginning...

+

+* Upgraded to Java 7

+

+* Build with Gradle

+

+* Publish a single jar java-hamcrest-x.x.x.x.jar

+

+* Removed deprecated methods from previous release

+

+* Improve mismatch description of hasItem/hasItems

+

+* General improvements to mismatch descriptions

+

+* Several JavaDoc improvements and corrections

+

+* Fix gh issue #69 - Iterable contains in order is null-safe

+

+* Fix gh issue #59 - added equalToObject() (i.e. unchecked) method

+

+* Fix gh issue #25 - arrayContaining(null, null) cause NullPointerException

+

+* Fix gh issue #36 - string matching on regular expressions

+

+* Fix gh issue #8 - isCloseTo() shows wrong delta in mismatch description

+

+* Fix issue 131 - Implement IsEmptyMap, IsMapWithSize

+

+* Fix issue 155 - Deprecated several matcher factory methods of the for "isXyz"

+

+* Fix issue 187 - IsArray.describeMismatchSafely() should use Matcher.describeMismatch

+

+* Fix issue 155 - Add Matcher implementation for files

+

+* Fix issue 59 - add untyped version of equalTo, named equalToObject

+

+* Fix issue 69 - fix NPE in IsIterableContainingInOrder

+

+* Fix issue 75 - address doclint errors reported in JDK 1.8

+

+== Version 1.3: Released July 09 2012 ==

+

+* Introduce Condition class to ease the implementation of multi-step matches

+

+* Upgrade qdox (included in the generator) to the latest stable version

+

+* Correct inadvertent deprecation of the Is.isA factory method

+

+* Fix issue 179 - AllOf does not output mismatch description

+

+* Fix issue 177 - Introduced closeTo matcher for BigDecimals

+

+* Fix issue 152 - Factory classes missing from matchers.xml

+

+* Fix issue 144 - OrderingComparison doesn't describe mismatch of comparables that return values other than (-1,0,1)

+

+* Fix issue 134 - DescribedAs does not delegate describeMismatch

+

+* Fix issue 106 - deprecation warning when writing custom matchers

+

+* Fix issue 101 - Added theInstance alias for sameInstance factory method

+

+== Version 1.3 RC2: Released October 22 2010 ==

+

+* Added FeatureMatcher

+

+* distinguish between instanceOf() and any()

+

+== Version 1.2: Released May 16 2009 ==

+

+* Added mismatch reporting

+

+* Added WithSamePropertyValuesAs matcher

+

+* Moved any() from IsAnything to IsInstanceOf. It now checks the type of the matched object

+

+* Moved MatcherAssert from integration to core

+

+* Tightened up generics.  

+

+* Added IsMapContainingKey and IsMapContainingValue matchers to resolve a 

+  generics bug in hasKey and hasValue static factories previously declared

+  in IsMapContaining (ngd)

+

+* Added IsCollectionOnlyContaining and IsArrayOnlyContaining which matches 

+  collections (and arrays) where all match a given matcher. E.g onlyContains(3,4,5) 

+  or onlyContains(lessThan(9))

+

+* text module moved to separate project, hamcrest-text-patterns

+

+* added more colection matchers: xContainingInAnyOrder, xContainingInOrder, xWithSize

+

+* new text Matcher: IsEmptyString

+

+* hamcrest generator uses method return type 

+

+== Version 1.1: Released Jun 30 2007 ==

+

+* Hamcrest Generator now includes JavaDoc and parameter names in generated code

+  by using QDox to parse the source code.

+

+* Created hamcrest-core.jar (and removed hamcrest-api.jar).

+  Moved core set of matchers (and, eq, not, etc)

+  to this package to make it more practical for external libraries

+  to embed Hamcrest.

+

+* Created CoreMatchers (static import sugar) in hamcrest-core.jar.

+

+* StringBuilder can use any Appendable (not just StringBuffer).

+

+* Added sensible toString() method to BaseMatcher.

+

+* Created StringDescription.asString() alias (because toString() caused issues

+  with static imports).

+

+* Relaxed isInstanceOf() matcher generic type so it can be used on any kind of

+  object. e.g. assertThat(someUnknownObject, isInstanceOf(String.class));

+

+* Added any(Class<T>), null(Class<T>) and notNull(Class<T>) matchers, which returns

+  Matcher<T>. Helpful when the compiler struggles with type inference.

+

+* Modified anyOf() and allOf() to accept mixed-types.

+

+* TypeSafeMatcher.matchesSafely() is now public.

+

+* Generator recognizes @Factory methods that return subclass of Matcher.

+  (Fix by David Saff)

+

+== Version 1.0: Released Dec 15 2006 ==

+

+Initial release.

+* Support for namespaces in HasXPath

+* Bug fix for matching empty elements with HasXPath

diff --git a/LICENSE.txt b/LICENSE.txt
index 5ebe92c..71806dd 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,6 +1,6 @@
 BSD License

 

-Copyright (c) 2000-2006, www.hamcrest.org

+Copyright (c) 2000-20014 www.hamcrest.org

 All rights reserved.

 

 Redistribution and use in source and binary forms, with or without

diff --git a/README.android b/README.android
deleted file mode 100644
index a1bbfd2..0000000
--- a/README.android
+++ /dev/null
@@ -1 +0,0 @@
-unmodified source obtained from http://code.google.com/p/hamcrest/downloads/detail?name=hamcrest-core-1.1.jar&can=2&q=, 
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..c1e1e0f
--- /dev/null
+++ b/README.md
@@ -0,0 +1,63 @@
+![JavaHamcrest](http://hamcrest.org/images/logo.jpg)
+
+[![Build Status](https://travis-ci.org/hamcrest/JavaHamcrest.png?branch=master)](https://travis-ci.org/hamcrest/JavaHamcrest)
+
+Java Hamcrest
+=============
+Licensed under [BSD License][].
+
+What is Hamcrest?
+-----------------
+Hamcrest is a library of matchers, which can be combined in to create flexible expressions of intent in tests.
+They've also been used for other purposes.
+
+Downloads
+---------
+You can obtain Hamcrest binaries from [maven central][], or from [google code downloads][].
+
+Extensions
+----------
+
+For Hamcrest extension projects see the [hamcrest extensions page][].
+
+Documentation
+-------------
+Documentation can be found on the [Hamcrest site](http://hamcrest.org).
+
+Reporting Bugs/Issues
+---------------------
+If you find an issue with Java Hamcrest, please report it via the 
+[GitHub issue tracker](https://github.com/hamcrest/JavaHamcrest/issues), 
+after first checking that it hasn't been raised already. 
+
+Source
+------
+To build, please read BUILDING.txt
+
+Acknowledgements
+----------------
+Developers:
+
+  * Joe Walnes
+  * Nat Pryce
+  * Steve Freeman
+
+Contributors:
+
+  * Robert Chatley
+  * Tom White
+  * Neil Dunn
+  * Dan North
+  * Magne Rasmussen
+  * David Saff
+  * Tom Denley
+
+Also, thanks to everyone who has worked on DynaMock, nMock, jMock, EasyMock and MiniMock! These libraries inspired Hamcrest.
+
+
+[logo]: https://raw.github.com/hamcrest/JavaHamcrest/master/doc/images/logo.jpg
+[website]: https://github.com/hamcrest/JavaHamcrest
+[BSD License]: http://opensource.org/licenses/BSD-3-Clause
+[Maven central]: http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.hamcrest
+[hamcrest extensions page]: https://github.com/hamcrest/JavaHamcrest/wiki/Related-Projects
+[GitHub issue tracker]: https://github.com/hamcrest/JavaHamcrest/issues
diff --git a/README.version b/README.version
new file mode 100644
index 0000000..660cee5
--- /dev/null
+++ b/README.version
@@ -0,0 +1,15 @@
+URL: https://github.com/hamcrest/JavaHamcrest/archive/f540af9fd49f33cc07b3446a8895c7b51cbf0944.zip
+Version: f540af9fd49f33cc07b3446a8895c7b51cbf0944
+BugComponent: 40416
+
+Version f540af9fd49f33cc07b3446a8895c7b51cbf0944 was chosen because it is the
+point at which v2.0.0.0 and master diverge. There are only about 7 commits
+on v2.0.0.0 which are not on master but they do conflict with some changes in
+master. Those changes appear to be relatively minor and while it is not clear
+what the future holds for Hamcrest given that it has had no activity since June
+2016 it seems unnecessary to take those extra 7 commits given the potential for
+conflicts in future upgrades.
+
+Local Changes:
+    Remove hamcrest-library/src/main/java/org/hamcrest/beans/ as Android does not support java.beans.
+    
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index b169d73..cd23be2 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,9 +1,116 @@
+import static org.gradle.api.JavaVersion.VERSION_1_7
+
 apply plugin: 'java'
+apply plugin: 'maven'
+apply plugin: 'signing'
+
+sourceCompatibility = VERSION_1_7
+targetCompatibility = VERSION_1_7
+archivesBaseName = "java-hamcrest"
+
+group = "org.hamcrest"
+version = "2.0.0.0"
+
+
+repositories {
+    mavenCentral()
+}
+
+dependencies {
+    testCompile(group: 'junit', name: 'junit', version: '4.12') {
+        transitive = false
+    }
+}
 
 sourceSets {
     main {
         java {
-            srcDirs = ['src']
+            srcDirs 'hamcrest-core/src/main/java', 'hamcrest-library/src/main/java'
+        }
+
+    }
+    test {
+        java {
+            srcDirs 'hamcrest-core/src/test/java', 'hamcrest-library/src/test/java'
+        }
+    }
+}
+
+jar {
+    manifest {
+        attributes 'Implementation-Title': 'hamcrest-all',
+                'Implementation-Vendor': 'hamcrest.org',
+                'Implementation-Version': version
+    }
+}
+
+task sourcesJar(type: Jar) {
+    classifier = 'sources'
+    from sourceSets.main.allSource
+}
+
+task javadocJar(type: Jar) {
+    classifier = 'javadoc'
+    from javadoc
+}
+
+artifacts {
+    archives sourcesJar, javadocJar
+}
+
+signing {
+    required { gradle.taskGraph.hasTask("uploadArchives") }
+    sign configurations.archives
+}
+
+uploadArchives {
+    if (hasProperty('ossrhUsername') && hasProperty('ossrhPassword')) {
+        repositories {
+            mavenDeployer {
+                beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
+
+                repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") {
+                    authentication(userName: ossrhUsername, password: ossrhPassword)
+                }
+
+                snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") {
+                    authentication(userName: ossrhUsername, password: ossrhPassword)
+                }
+
+                pom.project {
+                    name 'Java Hamcrest'
+                    packaging 'jar'
+                    description 'Hamcrest matcher library for Java'
+                    url 'http://hamcrest.org/JavaHamcrest/'
+
+                    scm {
+                        connection 'git@github.com:hamcrest/JavaHamcrest.git'
+                        url 'https://github.com/hamcrest/JavaHamcrest'
+                    }
+
+                    licenses {
+                        license {
+                            name 'BSD Licence 3'
+                            url 'http://opensource.org/licenses/BSD-3-Clause'
+                        }
+                    }
+
+                    developers {
+                        developer {
+                            id 'joewalnes'
+                            name 'Joe Walnes'
+                        }
+                        developer {
+                            id 'npryce'
+                            name 'Nat Pryce'
+                        }
+                        developer {
+                            id 'sf105'
+                            name 'Steve Freeman'
+                        }
+                    }
+                }
+            }
         }
     }
 }
diff --git a/build.xml.original b/build.xml.original
new file mode 100644
index 0000000..95662ee
--- /dev/null
+++ b/build.xml.original
@@ -0,0 +1,289 @@
+<project name="hamcrest" default="all">
+
+    <property name="version" value="SNAPSHOT" description="Version number to use in build files"/>
+    <property name="haltonfailure" value="true" description="Whether to halt the build if the tests fail"/>
+    <property name="debug" value="true" description="Whether to build with debug information"/>
+    <property name="javaversion" value="1.5" description="Java version to target"/>
+    <tstamp><format property="build.timestamp" pattern="yyyy-MM-dd HH:mm:ss" timezone="GMT"/></tstamp>
+    <taskdef name="junit" classname="org.apache.tools.ant.taskdefs.optional.junit.JUnitTask" classpath="lib/integration/ant-junit-1.8.4.jar"/>
+
+
+    <target name="all" depends="clean, bigjar, javadoc" description="Performs clean build, runs tests and packages for distribution"/>
+
+    <target name="clean" description="Clean up all built files">
+        <delete dir="build"/>
+    </target>
+
+    <target name="api" description="Build Hamcrest APIs">
+        <path id="cp-hamcrest-api-main" path=""/>
+        <path id="cp-hamcrest-api-test" path=""/>
+        <compile-module modulename="hamcrest-api"/>
+        <jar-module modulename="hamcrest-api"/>
+        <test-module modulename="hamcrest-api"/>
+    </target>
+
+    <target name="generator" depends="api" description="Build code generator tool">
+        <path id="cp-hamcrest-generator-main" path="lib/generator/qdox-2.0-M2.jar;build/hamcrest-api-${version}.jar"/>
+        <path id="cp-hamcrest-generator-test" path=""/>
+        <compile-module modulename="hamcrest-generator"/>
+        <jar-module modulename="hamcrest-generator"/>
+        <test-module modulename="hamcrest-generator"/>
+
+        <!-- Include QDox classes in hamcrest-generator.jar using JarJar to place classes under a different package -->
+        <taskdef name="jarjar" classname="com.tonicsystems.jarjar.JarJarTask" classpath="lib/generator/jarjar-1.3.jar"/>
+        <copy file="build/hamcrest-generator-${version}.jar" tofile="build/hamcrest-generator-${version}-nodep.jar"/>
+        <jarjar jarfile="build/hamcrest-generator-${version}.jar">
+            <zipfileset src="build/hamcrest-generator-${version}-nodep.jar"/>
+            <zipfileset src="lib/generator/qdox-2.0-M2.jar"/>
+            <rule pattern="com.thoughtworks.qdox.**" result="org.hamcrest.generator.qdox.@1"/>
+        </jarjar>
+    </target>
+
+    <target name="core" depends="generator" description="Build core Hamcrest library">
+        <path id="cp-hamcrest-core-main" path="build/hamcrest-api-${version}.jar"/>
+        <path id="cp-hamcrest-core-test" path=""/>
+        <compile-module modulename="hamcrest-core"/>
+        <generate-module-factory modulename="hamcrest-core" configurationfile="hamcrest-core/core-matchers.xml" targetclass="org.hamcrest.CoreMatchers" sources="hamcrest-core/src/main/java"/>
+        <jar-module modulename="hamcrest-core"/>
+        <test-module modulename="hamcrest-core"/>
+    </target>
+
+    <target name="library" depends="core" description="Build library of matchers">
+        <path id="cp-hamcrest-library-main" path="build/hamcrest-api-${version}.jar;build/hamcrest-core-${version}.jar"/>
+        <path id="cp-hamcrest-library-test" path="build/hamcrest-core-${version}-tests.jar"/>
+        <compile-module modulename="hamcrest-library"/>
+        <generate-module-factory modulename="hamcrest-library" configurationfile="hamcrest-library/matchers.xml" targetclass="org.hamcrest.Matchers" sources="hamcrest-core/src/main/java,hamcrest-library/src/main/java"/>
+        <jar-module modulename="hamcrest-library"/>
+        <test-module modulename="hamcrest-library"/>
+    </target>
+
+    <target name="integration" depends="library" description="Build integration with external tools">
+        <path id="cp-hamcrest-integration-main">
+            <fileset file="build/hamcrest-api-${version}.jar"/>
+            <fileset file="build/hamcrest-core-${version}.jar"/>
+            <fileset file="build/hamcrest-library-${version}.jar"/>
+            <fileset dir="lib/integration" includes="**/*.jar"/>
+        </path>
+        <path id="cp-hamcrest-integration-test" path="build/hamcrest-core-${version}-tests.jar"/>
+        <compile-module modulename="hamcrest-integration"/>
+        <jar-module modulename="hamcrest-integration"/>
+        <test-module modulename="hamcrest-integration"/>
+    </target>
+
+    <target name="examples" depends="core, library, integration" description="Build and run unit tests.">
+        <path id="cp-hamcrest-examples-main">
+            <fileset file="build/hamcrest-api-${version}.jar"/>
+            <fileset file="build/hamcrest-core-${version}.jar"/>
+            <fileset file="build/hamcrest-library-${version}.jar"/>
+            <fileset file="build/hamcrest-integration-${version}.jar"/>
+            <fileset dir="lib/integration" includes="**/*.jar"/>
+        </path>
+        <compile-module modulename="hamcrest-examples"/>
+        <jar-module modulename="hamcrest-examples"/>
+    </target>
+
+    <target name="bigjar" depends="core,library,integration,generator" description="Build composite jars">
+        <!-- Bundle api into core jar -->
+        <copy todir="build/temp/hamcrest-core-${version}.jar.contents">
+            <fileset dir="build/temp/hamcrest-api-${version}.jar.contents"/>
+        </copy>
+        <copy todir="build/temp/hamcrest-core-${version}-sources.jar.contents">
+            <fileset dir="build/temp/hamcrest-api-${version}-sources.jar.contents"/>
+        </copy>
+        <jar-module modulename="hamcrest-core"/>
+
+        <!-- Bundle core, library, integration, and generator into all jar-->
+        <copy todir="build/temp/hamcrest-all-${version}.jar.contents">
+            <fileset dir="build/temp/hamcrest-core-${version}.jar.contents"/>
+            <fileset dir="build/temp/hamcrest-library-${version}.jar.contents"/>
+            <fileset dir="build/temp/hamcrest-integration-${version}.jar.contents"/>
+            <fileset dir="build/temp/hamcrest-generator-${version}.jar.contents"/>
+        </copy>
+        <copy todir="build/temp/hamcrest-all-${version}-sources.jar.contents">
+            <fileset dir="build/temp/hamcrest-core-${version}-sources.jar.contents"/>
+            <fileset dir="build/temp/hamcrest-library-${version}-sources.jar.contents"/>
+            <fileset dir="build/temp/hamcrest-integration-${version}-sources.jar.contents"/>
+            <fileset dir="build/temp/hamcrest-generator-${version}-sources.jar.contents"/>
+        </copy>
+        <path id="cp-hamcrest-all-main">
+            <path refid="cp-hamcrest-core-main"/>
+            <path refid="cp-hamcrest-library-main"/>
+            <path refid="cp-hamcrest-integration-main"/>
+            <path refid="cp-hamcrest-generator-main"/>
+        </path>
+        <jar-module modulename="hamcrest-all"/>
+    </target>
+
+    <target name="javadoc" depends="bigjar" description="build javadoc jars">
+        <javadoc-module modulename="hamcrest-generator"/>
+        <javadoc-module modulename="hamcrest-core"/>
+        <javadoc-module modulename="hamcrest-library"/>
+        <javadoc-module modulename="hamcrest-integration"/>
+        <javadoc-module modulename="hamcrest-all"/>
+    </target>
+
+    <target name="bundle" description="Create a release bundle for deployment to maven central" depends="clean, javadoc">
+        <copy todir="build">
+            <fileset dir="pom" includes="*.pom"/>
+            <filterset><filter token="VERSION" value="${version}"/></filterset>
+            <mapper type="regexp" from="(.*)\.pom" to="\1-${version}.pom"/>
+        </copy>
+
+        <sign target="hamcrest-parent-${version}.pom"/>
+        <jar-bundle modulename="hamcrest-parent"/>
+
+        <bundle-module modulename="hamcrest-core"/>
+        <bundle-module modulename="hamcrest-generator"/>
+        <bundle-module modulename="hamcrest-library"/>
+        <bundle-module modulename="hamcrest-integration"/>
+        <bundle-module modulename="hamcrest-all"/>
+    </target>
+
+    <macrodef name="make-manifest">
+        <attribute name="modulename" description="Name of the module"/>
+        <sequential>
+            <mkdir dir="build/temp/@{modulename}-${version}.jar.manifest"/>
+            <manifest file="build/temp/@{modulename}-${version}.jar.manifest/MANIFEST.MF">
+               <attribute name="Implementation-Title" value="@{modulename}"/>
+               <attribute name="Implementation-Vendor" value="hamcrest.org"/>
+               <attribute name="Implementation-Version" value="${version}"/>
+               <attribute name="Built-By" value="${user.name}"/>
+               <attribute name="Built-Date" value="${build.timestamp}"/>
+           </manifest>
+        </sequential>
+    </macrodef>
+
+    <macrodef name="compile-module">
+        <attribute name="modulename" description="Name of the module to jar"/>
+        <sequential>
+            <compile-content srcdir="@{modulename}/src/main/java" jarname="@{modulename}-${version}" classpathref="cp-@{modulename}-main" />
+            <path id="cp-@{modulename}-test-complete">
+                <path path="lib/integration/junit-dep-4.11.jar"/>
+                <path refid="cp-@{modulename}-main"/>
+                <path refid="cp-@{modulename}-test"/>
+                <path path="build/temp/@{modulename}-${version}.jar.contents"/>
+            </path>
+            <compile-content srcdir="@{modulename}/src/test/java" jarname="@{modulename}-${version}-tests" classpathref="cp-@{modulename}-test-complete" />
+        </sequential>
+    </macrodef>
+
+    <macrodef name="compile-content">
+        <attribute name="srcdir"/>
+        <attribute name="jarname" description="Name of the jar whose content is being compiled (without .jar suffix)"/>
+        <attribute name="classpathref"/>
+        <sequential>
+            <mkdir dir="build/temp/@{jarname}-sources.jar.contents"/>
+            <copy failonerror="false" todir="build/temp/@{jarname}-sources.jar.contents">
+                <fileset dir="@{srcdir}"/>
+            </copy>
+            <mkdir dir="build/temp/@{jarname}.jar.contents"/>
+            <javac srcdir="build/temp/@{jarname}-sources.jar.contents"
+                   destdir="build/temp/@{jarname}.jar.contents"
+                   debug="${debug}" source="${javaversion}" target="${javaversion}" includeantruntime="false">
+                <classpath refid="@{classpathref}"/>
+            </javac>
+        </sequential>
+    </macrodef>
+
+    <macrodef name="jar-module">
+        <attribute name="modulename" description="Name of the module to jar"/>
+        <sequential>
+            <make-manifest modulename="@{modulename}"/>
+            <jar-module-component modulename="@{modulename}"/>
+            <jar-module-component modulename="@{modulename}" suffix="-tests"/>
+            <jar-module-component modulename="@{modulename}" suffix="-sources"/>
+        </sequential>
+    </macrodef>
+
+    <macrodef name="jar-module-component">
+        <attribute name="modulename" description="Name of the module to jar"/>
+        <attribute name="suffix" default="" description="Name of the module to jar"/>
+        <sequential>
+            <copy file="LICENSE.txt" todir="build/temp/@{modulename}-${version}@{suffix}.jar.contents/META-INF"/>
+            <jar jarfile="build/@{modulename}-${version}@{suffix}.jar" manifest="build/temp/@{modulename}-${version}.jar.manifest/MANIFEST.MF">
+                <fileset dir="build/temp/@{modulename}-${version}@{suffix}.jar.contents"/>
+            </jar>
+        </sequential>
+    </macrodef>
+
+    <macrodef name="generate-module-factory" description="Generate one class with all static imports">
+        <attribute name="modulename" description="Name of the module to jar"/>
+        <attribute name="configurationfile" description="xml configuration file"/>
+        <attribute name="targetclass" description="factory class to generate"/>
+        <attribute name="sources" description="comma-separated source directories"/>
+        <sequential>
+            <mkdir dir="build/temp/@{modulename}/generated-code"/>
+            <java classname="org.hamcrest.generator.config.XmlConfigurator" fork="yes" failonerror="yes">
+                <classpath path="build/hamcrest-generator-${version}.jar"/>
+                <classpath refid="cp-@{modulename}-main"/>
+                <classpath path="build/temp/@{modulename}-${version}.jar.contents"/>
+                <arg value="@{configurationfile}"/>
+                <arg value="@{sources}"/>
+                <arg value="@{targetclass}"/>
+                <arg value="build/temp/@{modulename}/generated-code"/>
+            </java>
+
+            <copy todir="build/temp/@{modulename}-${version}-sources.jar.contents">
+                <fileset dir="build/temp/@{modulename}/generated-code"/>
+            </copy>
+            <compile-module modulename="@{modulename}"/>
+        </sequential>
+    </macrodef>
+
+    <macrodef name="test-module" description="run unit tests.">
+        <attribute name="modulename" description="Name of the module to test"/>
+        <sequential>
+            <mkdir dir="build/temp/@{modulename}/test-wrk"/>
+            <junit printsummary="no" forkmode="once" tempdir="build/temp/@{modulename}/test-wrk" haltonfailure="${haltonfailure}" dir="@{modulename}">
+                <formatter type="brief" usefile="no"/>
+                <classpath refid="cp-@{modulename}-test-complete"/>
+                <classpath path="build/@{modulename}-${version}-tests.jar"/>
+                <batchtest fork="yes" todir="${build.dir}/testreport">
+                    <zipfileset src="build/@{modulename}-${version}-tests.jar">
+                        <include name="org/hamcrest/**/*Test.class"/>
+                        <exclude name="**/Abstract*.class"/>
+                    </zipfileset>
+                </batchtest>
+            </junit>
+        </sequential>
+    </macrodef>
+
+    <macrodef name="javadoc-module" description="Generate javadoc for a module and build a Jar">
+        <attribute name="modulename" description="Name of the module to document"/>
+        <sequential>
+            <javadoc packagenames="org.hamcrest.*" sourcepath="build/temp/@{modulename}-${version}-sources.jar.contents"
+                     destdir="build/temp/@{modulename}-${version}-javadoc.jar.contents" author="true" version="true"
+                     use="true" windowtitle="Hamcrest" source="${javaversion}" failonerror="yes" defaultexcludes="yes">
+                <classpath refid="cp-@{modulename}-main"/>
+            </javadoc>
+            <jar-module-component modulename="@{modulename}" suffix="-javadoc"/>
+        </sequential>
+    </macrodef>
+
+    <macrodef name="bundle-module" description="Generate maven bundle jar for a module">
+        <attribute name="modulename" description="Name of the module to bundle"/>
+        <sequential>
+            <sign target="@{modulename}-${version}.pom"/>
+            <sign target="@{modulename}-${version}.jar"/>
+            <sign target="@{modulename}-${version}-javadoc.jar"/>
+            <sign target="@{modulename}-${version}-sources.jar"/>
+            <jar-bundle modulename="@{modulename}"/>
+        </sequential>
+    </macrodef>
+
+    <macrodef name="jar-bundle" description="Jar maven bundle contents">
+        <attribute name="modulename" description="Name of the module to create bundle jar for"/>
+        <sequential>
+            <jar destfile="build/maven-bundle-@{modulename}.jar">
+                <fileset dir="build"><include name="@{modulename}-${version}*"/></fileset>
+            </jar>
+        </sequential>
+    </macrodef>
+
+    <macrodef name="sign" description="Sign a file with a gpg key">
+        <attribute name="target" description="Name of the resource to sign"/>
+        <sequential>
+            <exec executable="gpg" dir="build"><arg value="-ab"/><arg value="@{target}"/></exec>
+        </sequential>
+    </macrodef>
+</project>
diff --git a/doc/images/logo.jpg b/doc/images/logo.jpg
new file mode 100644
index 0000000..efd750d
--- /dev/null
+++ b/doc/images/logo.jpg
Binary files differ
diff --git a/hamcrest-core/src/main/java/org/hamcrest/BaseDescription.java b/hamcrest-core/src/main/java/org/hamcrest/BaseDescription.java
index 4c98e5f..6e62e69 100644
--- a/hamcrest-core/src/main/java/org/hamcrest/BaseDescription.java
+++ b/hamcrest-core/src/main/java/org/hamcrest/BaseDescription.java
@@ -1,127 +1,144 @@
-package org.hamcrest;

-

-import static java.lang.String.valueOf;

-

-import java.util.Arrays;

-import java.util.Iterator;

-

-import org.hamcrest.internal.ArrayIterator;

-import org.hamcrest.internal.SelfDescribingValueIterator;

-

-/**

- * A {@link Description} that is stored as a string.

- */

-public abstract class BaseDescription implements Description {

-    public Description appendText(String text) {

-        append(text);

-        return this;

-    }

-    

-    public Description appendDescriptionOf(SelfDescribing value) {

-    	value.describeTo(this);

-    	return this;

-    }

-    

-    public Description appendValue(Object value) {

-        if (value == null) {

-            append("null");

-        } else if (value instanceof String) {

-            toJavaSyntax((String) value);

-        } else if (value instanceof Character) {

-            append('"');

-            toJavaSyntax((Character) value);

-            append('"');

-        } else if (value instanceof Short) {

-            append('<');

-            append(valueOf(value));

-            append("s>");

-        } else if (value instanceof Long) {

-            append('<');

-            append(valueOf(value));

-            append("L>");

-        } else if (value instanceof Float) {

-            append('<');

-            append(valueOf(value));

-            append("F>");

-        } else if (value.getClass().isArray()) {

-        	appendValueList("[",", ","]", new ArrayIterator(value));

-        } else {

-            append('<');

-            append(valueOf(value));

-            append('>');

-        }

-        return this;

-    }

-    

-    public <T> Description appendValueList(String start, String separator, String end, T... values) {

-        return appendValueList(start, separator, end, Arrays.asList(values));

-	}

-    

-	public <T> Description appendValueList(String start, String separator, String end, Iterable<T> values) {

-		return appendValueList(start, separator, end, values.iterator());

-	}

-	

-	private <T> Description appendValueList(String start, String separator, String end, Iterator<T> values) {

-		return appendList(start, separator, end, new SelfDescribingValueIterator<T>(values));

-	}

-	

-    public Description appendList(String start, String separator, String end, Iterable<? extends SelfDescribing> values) {

-        return appendList(start, separator, end, values.iterator());

-    }

-

-    private Description appendList(String start, String separator, String end, Iterator<? extends SelfDescribing> i) {

-        boolean separate = false;

-        

-        append(start);

-        while (i.hasNext()) {

-            if (separate) append(separator);

-            appendDescriptionOf(i.next());

-            separate = true;

-        }

-        append(end);

-        

-        return this;

-    }

-

-

-    /** Append the String <var>str</var> to the description.  

-     *  The default implementation passes every character to {@link #append(char)}.  

-     *  Override in subclasses to provide an efficient implementation.

-     */

-    protected void append(String str) {

-    	for (int i = 0; i < str.length(); i++) {

-    		append(str.charAt(i));

-    	}

-    }

-    

-    /** Append the char <var>c</var> to the description.  

-     */

-    protected abstract void append(char c);

-

-    private void toJavaSyntax(String unformatted) {

-        append('"');

-        for (int i = 0; i < unformatted.length(); i++) {

-            toJavaSyntax(unformatted.charAt(i));

-        }

-        append('"');

-    }

-

-    private void toJavaSyntax(char ch) {

-        switch (ch) {

-            case '"':

-                append("\\\"");

-                break;

-            case '\n':

-                append("\\n");

-                break;

-            case '\r':

-                append("\\r");

-                break;

-            case '\t':

-                append("\\t");

-                break;

-            default:

-                append(ch);

-        }

-    }

-}

+package org.hamcrest;
+
+import org.hamcrest.internal.ArrayIterator;
+import org.hamcrest.internal.SelfDescribingValueIterator;
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+import static java.lang.String.valueOf;
+
+/**
+ * A {@link Description} that is stored as a string.
+ */
+public abstract class BaseDescription implements Description {
+
+    @Override
+    public Description appendText(String text) {
+        append(text);
+        return this;
+    }
+    
+    @Override
+    public Description appendDescriptionOf(SelfDescribing value) {
+        value.describeTo(this);
+        return this;
+    }
+    
+    @Override
+    public Description appendValue(Object value) {
+        if (value == null) {
+            append("null");
+        } else if (value instanceof String) {
+            toJavaSyntax((String) value);
+        } else if (value instanceof Character) {
+            append('"');
+            toJavaSyntax((Character) value);
+            append('"');
+        } else if (value instanceof Short) {
+            append('<');
+            append(descriptionOf(value));
+            append("s>");
+        } else if (value instanceof Long) {
+            append('<');
+            append(descriptionOf(value));
+            append("L>");
+        } else if (value instanceof Float) {
+            append('<');
+            append(descriptionOf(value));
+            append("F>");
+        } else if (value.getClass().isArray()) {
+            appendValueList("[",", ","]", new ArrayIterator(value));
+        } else {
+            append('<');
+            append(descriptionOf(value));
+            append('>');
+        }
+        return this;
+    }
+
+    private String descriptionOf(Object value) {
+        try {
+            return valueOf(value);
+        }
+        catch (Exception e) {
+            return value.getClass().getName() + "@" + Integer.toHexString(value.hashCode());
+        }
+    }
+
+    @Override
+    public <T> Description appendValueList(String start, String separator, String end, T... values) {
+        return appendValueList(start, separator, end, Arrays.asList(values));
+    }
+    
+    @Override
+    public <T> Description appendValueList(String start, String separator, String end, Iterable<T> values) {
+        return appendValueList(start, separator, end, values.iterator());
+    }
+    
+    private <T> Description appendValueList(String start, String separator, String end, Iterator<T> values) {
+        return appendList(start, separator, end, new SelfDescribingValueIterator<T>(values));
+    }
+    
+    @Override
+    public Description appendList(String start, String separator, String end, Iterable<? extends SelfDescribing> values) {
+        return appendList(start, separator, end, values.iterator());
+    }
+
+    private Description appendList(String start, String separator, String end, Iterator<? extends SelfDescribing> i) {
+        boolean separate = false;
+        
+        append(start);
+        while (i.hasNext()) {
+            if (separate) append(separator);
+            appendDescriptionOf(i.next());
+            separate = true;
+        }
+        append(end);
+        
+        return this;
+    }
+
+    /**
+     * Append the String <var>str</var> to the description.  
+     * The default implementation passes every character to {@link #append(char)}.  
+     * Override in subclasses to provide an efficient implementation.
+     */
+    protected void append(String str) {
+        for (int i = 0; i < str.length(); i++) {
+            append(str.charAt(i));
+        }
+    }
+    
+    /**
+     * Append the char <var>c</var> to the description.  
+     */
+    protected abstract void append(char c);
+
+    private void toJavaSyntax(String unformatted) {
+        append('"');
+        for (int i = 0; i < unformatted.length(); i++) {
+            toJavaSyntax(unformatted.charAt(i));
+        }
+        append('"');
+    }
+
+    private void toJavaSyntax(char ch) {
+        switch (ch) {
+            case '"':
+                append("\\\"");
+                break;
+            case '\n':
+                append("\\n");
+                break;
+            case '\r':
+                append("\\r");
+                break;
+            case '\t':
+                append("\\t");
+                break;
+            default:
+                append(ch);
+        }
+    }
+}
diff --git a/hamcrest-core/src/main/java/org/hamcrest/BaseMatcher.java b/hamcrest-core/src/main/java/org/hamcrest/BaseMatcher.java
index 3fdd6f7..484c101 100644
--- a/hamcrest-core/src/main/java/org/hamcrest/BaseMatcher.java
+++ b/hamcrest-core/src/main/java/org/hamcrest/BaseMatcher.java
@@ -1,5 +1,3 @@
-/*  Copyright (c) 2000-2006 hamcrest.org
- */
 package org.hamcrest;
 
 /**
@@ -12,11 +10,18 @@
     /**
      * @see Matcher#_dont_implement_Matcher___instead_extend_BaseMatcher_()
      */
+    @Override
+    @Deprecated
     public final void _dont_implement_Matcher___instead_extend_BaseMatcher_() {
         // See Matcher interface for an explanation of this method.
     }
 
     @Override
+    public void describeMismatch(Object item, Description description) {
+        description.appendText("was ").appendValue(item);
+    }
+
+    @Override
     public String toString() {
         return StringDescription.toString(this);
     }
diff --git a/hamcrest-core/src/main/java/org/hamcrest/Condition.java b/hamcrest-core/src/main/java/org/hamcrest/Condition.java
new file mode 100644
index 0000000..02ce09e
--- /dev/null
+++ b/hamcrest-core/src/main/java/org/hamcrest/Condition.java
@@ -0,0 +1,69 @@
+package org.hamcrest;
+
+/**
+ * A Condition implements part of a multi-step match. We sometimes need to write matchers
+ * that have a sequence of steps, where each step depends on the result of the previous
+ * step and we can stop processing as soon as a step fails. These classes provide
+ * infrastructure for writing such a sequence.
+ *
+ * Based on https://github.com/npryce/maybe-java
+ * @author Steve Freeman 2012 http://www.hamcrest.com
+ */
+
+public abstract class Condition<T> {
+    public static final NotMatched<Object> NOT_MATCHED = new NotMatched<Object>();
+
+    public interface Step<I, O> {
+        Condition<O> apply(I value, Description mismatch);
+    }
+
+    private Condition() { }
+
+    public abstract boolean matching(Matcher<T> match, String message);
+    public abstract <U> Condition<U> and(Step<? super T, U> mapping);
+
+    public final boolean matching(Matcher<T> match) { return matching(match, ""); }
+    public final <U> Condition<U> then(Step<? super T, U> mapping) { return and(mapping); }
+
+    @SuppressWarnings("unchecked")
+    public static <T> Condition<T> notMatched() {
+        return (Condition<T>) NOT_MATCHED;
+    }
+
+    public static <T> Condition<T> matched(final T theValue, final Description mismatch) {
+        return new Matched<T>(theValue, mismatch);
+    }
+
+    private static final class Matched<T> extends Condition<T> {
+        private final T theValue;
+        private final Description mismatch;
+
+        private Matched(T theValue, Description mismatch) {
+            this.theValue = theValue;
+            this.mismatch = mismatch;
+        }
+
+        @Override
+        public boolean matching(Matcher<T> matcher, String message) {
+            if (matcher.matches(theValue)) {
+                return true;
+            }
+            mismatch.appendText(message);
+            matcher.describeMismatch(theValue, mismatch);
+            return false;
+        }
+
+        @Override
+        public <U> Condition<U> and(Step<? super T, U> next) {
+            return next.apply(theValue, mismatch);
+        }
+    }
+
+    private static final class NotMatched<T> extends Condition<T> {
+        @Override public boolean matching(Matcher<T> match, String message) { return false; }
+
+        @Override public <U> Condition<U> and(Step<? super T, U> mapping) {
+            return notMatched();
+        }
+    }
+}
diff --git a/hamcrest-core/src/main/java/org/hamcrest/CoreMatchers.java b/hamcrest-core/src/main/java/org/hamcrest/CoreMatchers.java
index 400a491..799a26a 100644
--- a/hamcrest-core/src/main/java/org/hamcrest/CoreMatchers.java
+++ b/hamcrest-core/src/main/java/org/hamcrest/CoreMatchers.java
@@ -1,24 +1,114 @@
-// Generated source.
 package org.hamcrest;
 
+@SuppressWarnings("UnusedDeclaration")
 public class CoreMatchers {
 
   /**
-   * Decorates another Matcher, retaining the behavior but allowing tests
-   * to be slightly more expressive.
+   * Creates a matcher that matches if the examined object matches <b>ALL</b> of the specified matchers.
+   * For example:
+   * <pre>assertThat("myValue", allOf(startsWith("my"), containsString("Val")))</pre>
+   */
+  public static <T> org.hamcrest.Matcher<T> allOf(java.lang.Iterable<org.hamcrest.Matcher<? super T>> matchers) {
+    return org.hamcrest.core.AllOf.<T>allOf(matchers);
+  }
+
+  /**
+   * Creates a matcher that matches if the examined object matches <b>ALL</b> of the specified matchers.
+   * For example:
+   * <pre>assertThat("myValue", allOf(startsWith("my"), containsString("Val")))</pre>
+   */
+  @SafeVarargs
+  public static <T> org.hamcrest.Matcher<T> allOf(org.hamcrest.Matcher<? super T>... matchers) {
+    return org.hamcrest.core.AllOf.<T>allOf(matchers);
+  }
+
+
+  /**
+   * Creates a matcher that matches if the examined object matches <b>ANY</b> of the specified matchers.
+   * For example:
+   * <pre>assertThat("myValue", anyOf(startsWith("foo"), containsString("Val")))</pre>
+   */
+  public static <T> org.hamcrest.core.AnyOf<T> anyOf(java.lang.Iterable<org.hamcrest.Matcher<? super T>> matchers) {
+    return org.hamcrest.core.AnyOf.<T>anyOf(matchers);
+  }
+
+  /**
+   * Creates a matcher that matches if the examined object matches <b>ANY</b> of the specified matchers.
+   * For example:
+   * <pre>assertThat("myValue", anyOf(startsWith("foo"), containsString("Val")))</pre>
+   */
+  @SafeVarargs
+  public static <T> org.hamcrest.core.AnyOf<T> anyOf(org.hamcrest.Matcher<? super T>... matchers) {
+    return org.hamcrest.core.AnyOf.<T>anyOf(matchers);
+  }
+
+  /**
+   * Creates a matcher that matches when both of the specified matchers match the examined object.
+   * For example:
+   * <pre>assertThat("fab", both(containsString("a")).and(containsString("b")))</pre>
+   */
+  public static <LHS> org.hamcrest.core.CombinableMatcher.CombinableBothMatcher<LHS> both(org.hamcrest.Matcher<? super LHS> matcher) {
+    return org.hamcrest.core.CombinableMatcher.both(matcher);
+  }
+
+  /**
+   * Creates a matcher that matches when either of the specified matchers match the examined object.
+   * For example:
+   * <pre>assertThat("fan", either(containsString("a")).or(containsString("b")))</pre>
+   */
+  public static <LHS> org.hamcrest.core.CombinableMatcher.CombinableEitherMatcher<LHS> either(org.hamcrest.Matcher<? super LHS> matcher) {
+    return org.hamcrest.core.CombinableMatcher.either(matcher);
+  }
+
+  /**
+   * Wraps an existing matcher, overriding its description with that specified.  All other functions are
+   * delegated to the decorated matcher, including its mismatch description.
+   * For example:
+   * <pre>describedAs("a big decimal equal to %0", equalTo(myBigDecimal), myBigDecimal.toPlainString())</pre>
    * 
-   * eg. assertThat(cheese, equalTo(smelly))
-   * vs assertThat(cheese, is(equalTo(smelly)))
+   * @param description
+   *     the new description for the wrapped matcher
+   * @param matcher
+   *     the matcher to wrap
+   * @param values
+   *     optional values to insert into the tokenised description
+   */
+  public static <T> org.hamcrest.Matcher<T> describedAs(java.lang.String description, org.hamcrest.Matcher<T> matcher, java.lang.Object... values) {
+    return org.hamcrest.core.DescribedAs.describedAs(description, matcher, values);
+  }
+
+  /**
+   * Creates a matcher for {@link Iterable}s that only matches when a single pass over the
+   * examined {@link Iterable} yields items that are all matched by the specified
+   * <code>itemMatcher</code>.
+   * For example:
+   * <pre>assertThat(Arrays.asList("bar", "baz"), everyItem(startsWith("ba")))</pre>
+   * 
+   * @param itemMatcher
+   *     the matcher to apply to every item provided by the examined {@link Iterable}
+   */
+  public static <U> org.hamcrest.Matcher<java.lang.Iterable<? extends U>> everyItem(org.hamcrest.Matcher<U> itemMatcher) {
+    return org.hamcrest.core.Every.everyItem(itemMatcher);
+  }
+
+  /**
+   * Decorates another Matcher, retaining its behaviour, but allowing tests
+   * to be slightly more expressive.
+   * For example:
+   * <pre>assertThat(cheese, is(equalTo(smelly)))</pre>
+   * instead of:
+   * <pre>assertThat(cheese, equalTo(smelly))</pre>
    */
   public static <T> org.hamcrest.Matcher<T> is(org.hamcrest.Matcher<T> matcher) {
     return org.hamcrest.core.Is.is(matcher);
   }
 
   /**
-   * This is a shortcut to the frequently used is(equalTo(x)).
-   * 
-   * eg. assertThat(cheese, is(equalTo(smelly)))
-   * vs assertThat(cheese, is(smelly))
+   * A shortcut to the frequently used <code>is(equalTo(x))</code>.
+   * For example:
+   * <pre>assertThat(cheese, is(smelly))</pre>
+   * instead of:
+   * <pre>assertThat(cheese, is(equalTo(smelly)))</pre>
    */
   public static <T> org.hamcrest.Matcher<T> is(T value) {
     return org.hamcrest.core.Is.is(value);
@@ -41,131 +131,334 @@
   }
 
   /**
-   * Inverts the rule.
+   * A shortcut to the frequently used <code>is(instanceOf(SomeClass.class))</code>.
+   * For example:
+   * <pre>assertThat(cheese, isA(Cheddar.class))</pre>
+   * instead of:
+   * <pre>assertThat(cheese, is(instanceOf(Cheddar.class)))</pre>
    */
-  public static <T> org.hamcrest.Matcher<T> not(org.hamcrest.Matcher<T> matcher) {
-    return org.hamcrest.core.IsNot.not(matcher);
+  public static <T> org.hamcrest.Matcher<T> isA(java.lang.Class<T> type) {
+    return org.hamcrest.core.Is.isA(type);
   }
 
   /**
-   * This is a shortcut to the frequently used not(equalTo(x)).
+   * Creates a matcher that always matches, regardless of the examined object.
+   */
+  public static org.hamcrest.Matcher<java.lang.Object> anything() {
+    return org.hamcrest.core.IsAnything.anything();
+  }
+
+  /**
+   * Creates a matcher that always matches, regardless of the examined object, but describes
+   * itself with the specified {@link String}.
    * 
-   * eg. assertThat(cheese, is(not(equalTo(smelly))))
-   * vs assertThat(cheese, is(not(smelly)))
+   * @param description
+   *     a meaningful {@link String} used when describing itself
    */
-  public static <T> org.hamcrest.Matcher<T> not(T value) {
-    return org.hamcrest.core.IsNot.not(value);
+  public static org.hamcrest.Matcher<java.lang.Object> anything(java.lang.String description) {
+    return org.hamcrest.core.IsAnything.anything(description);
   }
 
   /**
-   * Is the value equal to another value, as tested by the
-   * {@link java.lang.Object#equals} invokedMethod?
+   * Creates a matcher for {@link Iterable}s that only matches when a single pass over the
+   * examined {@link Iterable} yields at least one item that is matched by the specified
+   * <code>itemMatcher</code>.  Whilst matching, the traversal of the examined {@link Iterable}
+   * will stop as soon as a matching item is found.
+   * For example:
+   * <pre>assertThat(Arrays.asList("foo", "bar"), hasItem(startsWith("ba")))</pre>
+   * 
+   * @param itemMatcher
+   *     the matcher to apply to items provided by the examined {@link Iterable}
+   */
+  public static <T> org.hamcrest.Matcher<java.lang.Iterable<? super T>> hasItem(org.hamcrest.Matcher<? super T> itemMatcher) {
+    return org.hamcrest.core.IsCollectionContaining.<T>hasItem(itemMatcher);
+  }
+
+  /**
+   * Creates a matcher for {@link Iterable}s that only matches when a single pass over the
+   * examined {@link Iterable} yields at least one item that is equal to the specified
+   * <code>item</code>.  Whilst matching, the traversal of the examined {@link Iterable}
+   * will stop as soon as a matching item is found.
+   * For example:
+   * <pre>assertThat(Arrays.asList("foo", "bar"), hasItem("bar"))</pre>
+   * 
+   * @param item
+   *     the item to compare against the items provided by the examined {@link Iterable}
+   */
+  public static <T> org.hamcrest.Matcher<java.lang.Iterable<? super T>> hasItem(T item) {
+    return org.hamcrest.core.IsCollectionContaining.<T>hasItem(item);
+  }
+
+  /**
+   * Creates a matcher for {@link Iterable}s that matches when consecutive passes over the
+   * examined {@link Iterable} yield at least one item that is matched by the corresponding
+   * matcher from the specified <code>itemMatchers</code>.  Whilst matching, each traversal of
+   * the examined {@link Iterable} will stop as soon as a matching item is found.
+   * For example:
+   * <pre>assertThat(Arrays.asList("foo", "bar", "baz"), hasItems(endsWith("z"), endsWith("o")))</pre>
+   * 
+   * @param itemMatchers
+   *     the matchers to apply to items provided by the examined {@link Iterable}
+   */
+  @SafeVarargs
+  public static <T> org.hamcrest.Matcher<java.lang.Iterable<T>> hasItems(org.hamcrest.Matcher<? super T>... itemMatchers) {
+    return org.hamcrest.core.IsCollectionContaining.<T>hasItems(itemMatchers);
+  }
+
+  /**
+   * Creates a matcher for {@link Iterable}s that matches when consecutive passes over the
+   * examined {@link Iterable} yield at least one item that is equal to the corresponding
+   * item from the specified <code>items</code>.  Whilst matching, each traversal of the
+   * examined {@link Iterable} will stop as soon as a matching item is found.
+   * For example:
+   * <pre>assertThat(Arrays.asList("foo", "bar", "baz"), hasItems("baz", "foo"))</pre>
+   * 
+   * @param items
+   *     the items to compare against the items provided by the examined {@link Iterable}
+   */
+  @SafeVarargs
+  public static <T> org.hamcrest.Matcher<java.lang.Iterable<T>> hasItems(T... items) {
+    return org.hamcrest.core.IsCollectionContaining.<T>hasItems(items);
+  }
+
+  /**
+   * Creates a matcher that matches when the examined object is logically equal to the specified
+   * <code>operand</code>, as determined by calling the {@link java.lang.Object#equals} method on
+   * the <b>examined</b> object.
+   * 
+   * <p>If the specified operand is <code>null</code> then the created matcher will only match if
+   * the examined object's <code>equals</code> method returns <code>true</code> when passed a
+   * <code>null</code> (which would be a violation of the <code>equals</code> contract), unless the
+   * examined object itself is <code>null</code>, in which case the matcher will return a positive
+   * match.</p>
+   * 
+   * <p>The created matcher provides a special behaviour when examining <code>Array</code>s, whereby
+   * it will match if both the operand and the examined object are arrays of the same length and
+   * contain items that are equal to each other (according to the above rules) <b>in the same
+   * indexes</b>.</p> 
+   * For example:
+   * <pre>
+   * assertThat("foo", equalTo("foo"));
+   * assertThat(new String[] {"foo", "bar"}, equalTo(new String[] {"foo", "bar"}));
+   * </pre>
    */
   public static <T> org.hamcrest.Matcher<T> equalTo(T operand) {
     return org.hamcrest.core.IsEqual.equalTo(operand);
   }
 
   /**
-   * Is the value an instance of a particular type?
+   * Creates an {@link org.hamcrest.core.IsEqual} matcher that does not enforce the values being
+   * compared to be of the same static type.
    */
-  public static org.hamcrest.Matcher<java.lang.Object> instanceOf(java.lang.Class<?> type) {
+  public static org.hamcrest.Matcher<java.lang.Object> equalToObject(java.lang.Object operand) {
+    return org.hamcrest.core.IsEqual.equalToObject(operand);
+  }
+
+  /**
+   * Creates a matcher that matches when the examined object is an instance of the specified <code>type</code>,
+   * as determined by calling the {@link java.lang.Class#isInstance(Object)} method on that type, passing the
+   * the examined object.
+   * 
+   * <p>The created matcher forces a relationship between specified type and the examined object, and should be
+   * used when it is necessary to make generics conform, for example in the JMock clause
+   * <code>with(any(Thing.class))</code></p>
+   * For example:
+   * <pre>assertThat(new Canoe(), instanceOf(Canoe.class));</pre>
+   */
+  public static <T> org.hamcrest.Matcher<T> any(java.lang.Class<T> type) {
+    return org.hamcrest.core.IsInstanceOf.any(type);
+  }
+
+  /**
+   * Creates a matcher that matches when the examined object is an instance of the specified <code>type</code>,
+   * as determined by calling the {@link java.lang.Class#isInstance(Object)} method on that type, passing the
+   * the examined object.
+   * 
+   * <p>The created matcher assumes no relationship between specified type and the examined object.</p>
+   * For example:
+   * <pre>assertThat(new Canoe(), instanceOf(Paddlable.class));</pre>
+   */
+  public static <T> org.hamcrest.Matcher<T> instanceOf(java.lang.Class<?> type) {
     return org.hamcrest.core.IsInstanceOf.instanceOf(type);
   }
 
   /**
-   * Evaluates to true only if ALL of the passed in matchers evaluate to true.
-   */
-  public static <T> org.hamcrest.Matcher<T> allOf(org.hamcrest.Matcher<? extends T>... matchers) {
-    return org.hamcrest.core.AllOf.<T>allOf(matchers);
-  }
-
-  /**
-   * Evaluates to true only if ALL of the passed in matchers evaluate to true.
-   */
-  public static <T> org.hamcrest.Matcher<T> allOf(java.lang.Iterable<org.hamcrest.Matcher<? extends T>> matchers) {
-    return org.hamcrest.core.AllOf.allOf(matchers);
-  }
-
-  /**
-   * Evaluates to true if ANY of the passed in matchers evaluate to true.
-   */
-  public static <T> org.hamcrest.Matcher<T> anyOf(org.hamcrest.Matcher<? extends T>... matchers) {
-    return org.hamcrest.core.AnyOf.<T>anyOf(matchers);
-  }
-
-  /**
-   * Evaluates to true if ANY of the passed in matchers evaluate to true.
-   */
-  public static <T> org.hamcrest.Matcher<T> anyOf(java.lang.Iterable<org.hamcrest.Matcher<? extends T>> matchers) {
-    return org.hamcrest.core.AnyOf.anyOf(matchers);
-  }
-
-  /**
-   * Creates a new instance of IsSame
+   * Creates a matcher that wraps an existing matcher, but inverts the logic by which
+   * it will match.
+   * For example:
+   * <pre>assertThat(cheese, is(not(equalTo(smelly))))</pre>
    * 
-   * @param object The predicate evaluates to true only when the argument is
-   * this object.
+   * @param matcher
+   *     the matcher whose sense should be inverted
    */
-  public static <T> org.hamcrest.Matcher<T> sameInstance(T object) {
-    return org.hamcrest.core.IsSame.sameInstance(object);
+  public static <T> org.hamcrest.Matcher<T> not(org.hamcrest.Matcher<T> matcher) {
+    return org.hamcrest.core.IsNot.not(matcher);
   }
 
   /**
-   * This matcher always evaluates to true.
-   */
-  public static <T> org.hamcrest.Matcher<T> anything() {
-    return org.hamcrest.core.IsAnything.anything();
-  }
-
-  /**
-   * This matcher always evaluates to true.
+   * A shortcut to the frequently used <code>not(equalTo(x))</code>.
+   * For example:
+   * <pre>assertThat(cheese, is(not(smelly)))</pre>
+   * instead of:
+   * <pre>assertThat(cheese, is(not(equalTo(smelly))))</pre>
    * 
-   * @param description A meaningful string used when describing itself.
+   * @param value
+   *     the value that any examined object should <b>not</b> equal
    */
-  public static <T> org.hamcrest.Matcher<T> anything(java.lang.String description) {
-    return org.hamcrest.core.IsAnything.anything(description);
+  public static <T> org.hamcrest.Matcher<T> not(T value) {
+    return org.hamcrest.core.IsNot.not(value);
   }
 
   /**
-   * This matcher always evaluates to true. With type inference.
+   * A shortcut to the frequently used <code>not(nullValue())</code>.
+   * For example:
+   * <pre>assertThat(cheese, is(notNullValue()))</pre>
+   * instead of:
+   * <pre>assertThat(cheese, is(not(nullValue())))</pre>
    */
-  public static <T> org.hamcrest.Matcher<T> any(java.lang.Class<T> type) {
-    return org.hamcrest.core.IsAnything.any(type);
-  }
-
-  /**
-   * Matches if value is null.
-   */
-  public static <T> org.hamcrest.Matcher<T> nullValue() {
-    return org.hamcrest.core.IsNull.nullValue();
-  }
-
-  /**
-   * Matches if value is null. With type inference.
-   */
-  public static <T> org.hamcrest.Matcher<T> nullValue(java.lang.Class<T> type) {
-    return org.hamcrest.core.IsNull.nullValue(type);
-  }
-
-  /**
-   * Matches if value is not null.
-   */
-  public static <T> org.hamcrest.Matcher<T> notNullValue() {
+  public static org.hamcrest.Matcher<java.lang.Object> notNullValue() {
     return org.hamcrest.core.IsNull.notNullValue();
   }
 
   /**
-   * Matches if value is not null. With type inference.
+   * A shortcut to the frequently used <code>not(nullValue(X.class)). Accepts a
+   * single dummy argument to facilitate type inference.</code>.
+   * For example:
+   * <pre>assertThat(cheese, is(notNullValue(X.class)))</pre>
+   * instead of:
+   * <pre>assertThat(cheese, is(not(nullValue(X.class))))</pre>
+   * 
+   * @param type
+   *     dummy parameter used to infer the generic type of the returned matcher
    */
   public static <T> org.hamcrest.Matcher<T> notNullValue(java.lang.Class<T> type) {
     return org.hamcrest.core.IsNull.notNullValue(type);
   }
 
   /**
-   * Wraps an existing matcher and overrides the description when it fails.
+   * Creates a matcher that matches if examined object is <code>null</code>.
+   * For example:
+   * <pre>assertThat(cheese, is(nullValue())</pre>
    */
-  public static <T> org.hamcrest.Matcher<T> describedAs(java.lang.String description, org.hamcrest.Matcher<T> matcher, java.lang.Object... values) {
-    return org.hamcrest.core.DescribedAs.describedAs(description, matcher, values);
+  public static org.hamcrest.Matcher<java.lang.Object> nullValue() {
+    return org.hamcrest.core.IsNull.nullValue();
+  }
+
+  /**
+   * Creates a matcher that matches if examined object is <code>null</code>. Accepts a
+   * single dummy argument to facilitate type inference.
+   * For example:
+   * <pre>assertThat(cheese, is(nullValue(Cheese.class))</pre>
+   * 
+   * @param type
+   *     dummy parameter used to infer the generic type of the returned matcher
+   */
+  public static <T> org.hamcrest.Matcher<T> nullValue(java.lang.Class<T> type) {
+    return org.hamcrest.core.IsNull.nullValue(type);
+  }
+
+  /**
+   * Creates a matcher that matches only when the examined object is the same instance as
+   * the specified target object.
+   * 
+   * @param target
+   *     the target instance against which others should be assessed
+   */
+  public static <T> org.hamcrest.Matcher<T> sameInstance(T target) {
+    return org.hamcrest.core.IsSame.sameInstance(target);
+  }
+
+  /**
+   * Creates a matcher that matches only when the examined object is the same instance as
+   * the specified target object.
+   * 
+   * @param target
+   *     the target instance against which others should be assessed
+   */
+  public static <T> org.hamcrest.Matcher<T> theInstance(T target) {
+    return org.hamcrest.core.IsSame.theInstance(target);
+  }
+
+  /**
+   * Creates a matcher that matches if the examined {@link String} contains the specified
+   * {@link String} anywhere.
+   * For example:
+   * <pre>assertThat("myStringOfNote", containsString("ring"))</pre>
+   * 
+   * @param substring
+   *     the substring that the returned matcher will expect to find within any examined string
+   */
+  public static org.hamcrest.Matcher<java.lang.String> containsString(java.lang.String substring) {
+    return org.hamcrest.core.StringContains.containsString(substring);
+  }
+
+  /**
+   * Creates a matcher that matches if the examined {@link String} contains the specified
+   * {@link String} anywhere, ignoring case.
+   * For example:
+   * <pre>assertThat("myStringOfNote", containsString("ring"))</pre>
+   * 
+   * @param substring
+   *     the substring that the returned matcher will expect to find within any examined string
+   */
+  public static org.hamcrest.Matcher<java.lang.String> containsStringIgnoringCase(java.lang.String substring) {
+    return org.hamcrest.core.StringContains.containsStringIgnoringCase(substring);
+  }
+
+  /**
+   * <p>
+   * Creates a matcher that matches if the examined {@link String} starts with the specified
+   * {@link String}.
+   * </p>
+   * For example:
+   * <pre>assertThat("myStringOfNote", startsWith("my"))</pre>
+   * 
+   * @param prefix
+   *      the substring that the returned matcher will expect at the start of any examined string
+   */
+  public static org.hamcrest.Matcher<java.lang.String> startsWith(java.lang.String prefix) {
+    return org.hamcrest.core.StringStartsWith.startsWith(prefix);
+  }
+
+  /**
+   * <p>
+   * Creates a matcher that matches if the examined {@link String} starts with the specified
+   * {@link String}, ignoring case
+   * </p>
+   * For example:
+   * <pre>assertThat("myStringOfNote", startsWith("my"))</pre>
+   * 
+   * @param prefix
+   *      the substring that the returned matcher will expect at the start of any examined string
+   */
+  public static org.hamcrest.Matcher<java.lang.String> startsWithIgnoringCase(java.lang.String prefix) {
+    return org.hamcrest.core.StringStartsWith.startsWithIgnoringCase(prefix);
+  }
+
+  /**
+   * Creates a matcher that matches if the examined {@link String} ends with the specified
+   * {@link String}.
+   * For example:
+   * <pre>assertThat("myStringOfNote", endsWith("Note"))</pre>
+   * 
+   * @param suffix
+   *      the substring that the returned matcher will expect at the end of any examined string
+   */
+  public static org.hamcrest.Matcher<java.lang.String> endsWith(java.lang.String suffix) {
+    return org.hamcrest.core.StringEndsWith.endsWith(suffix);
+  }
+
+  /**
+   * Creates a matcher that matches if the examined {@link String} ends with the specified
+   * {@link String}, ignoring case.
+   * For example:
+   * <pre>assertThat("myStringOfNote", endsWith("Note"))</pre>
+   * 
+   * @param suffix
+   *      the substring that the returned matcher will expect at the end of any examined string
+   */
+  public static org.hamcrest.Matcher<java.lang.String> endsWithIgnoringCase(java.lang.String suffix) {
+    return org.hamcrest.core.StringEndsWith.endsWithIgnoringCase(suffix);
   }
 
 }
diff --git a/hamcrest-core/src/main/java/org/hamcrest/CustomMatcher.java b/hamcrest-core/src/main/java/org/hamcrest/CustomMatcher.java
new file mode 100644
index 0000000..036a764
--- /dev/null
+++ b/hamcrest-core/src/main/java/org/hamcrest/CustomMatcher.java
@@ -0,0 +1,37 @@
+package org.hamcrest;
+
+/**
+ * Utility class for writing one off matchers.
+ * For example:
+ * <pre>
+ * Matcher&lt;String&gt; aNonEmptyString = new CustomMatcher&lt;String&gt;("a non empty string") {
+ *   public boolean matches(Object object) {
+ *     return ((object instanceof String) &amp;&amp; !((String) object).isEmpty();
+ *   }
+ * };
+ * </pre>
+ * <p>
+ * This class is designed for scenarios where an anonymous inner class
+ * matcher makes sense. It should not be used by API designers implementing
+ * matchers.
+ *
+ * @author Neil Dunn
+ * @see CustomTypeSafeMatcher for a type safe variant of this class that you probably
+ *  want to use.
+ * @param <T> The type of object being matched.
+ */
+public abstract class CustomMatcher<T> extends BaseMatcher<T> {
+    private final String fixedDescription;
+
+    public CustomMatcher(String description) {
+        if (description == null) {
+            throw new IllegalArgumentException("Description should be non null!");
+        }
+        this.fixedDescription = description;
+    }
+
+    @Override
+    public final void describeTo(Description description) {
+        description.appendText(fixedDescription);
+    }
+}
diff --git a/hamcrest-core/src/main/java/org/hamcrest/CustomTypeSafeMatcher.java b/hamcrest-core/src/main/java/org/hamcrest/CustomTypeSafeMatcher.java
new file mode 100644
index 0000000..7c5c46c
--- /dev/null
+++ b/hamcrest-core/src/main/java/org/hamcrest/CustomTypeSafeMatcher.java
@@ -0,0 +1,39 @@
+package org.hamcrest;
+
+
+/**
+ * Utility class for writing one off matchers.
+ * For example:
+ * <pre>
+ * Matcher&lt;String&gt; aNonEmptyString = new CustomTypeSafeMatcher&lt;String&gt;("a non empty string") {
+ *   public boolean matchesSafely(String string) {
+ *     return !string.isEmpty();
+ *   }
+ *   public void describeMismatchSafely(String string, Description mismatchDescription) {
+ *     mismatchDescription.appendText("was empty");
+ *   }
+ * };
+ * </pre>
+ * This is a variant of {@link CustomMatcher} that first type checks
+ * the argument being matched. By the time {@link TypeSafeMatcher#matchesSafely} is
+ * is called the argument is guaranteed to be non-null and of the correct
+ * type.
+ *
+ * @author Neil Dunn
+ * @param <T> The type of object being matched
+ */
+public abstract class CustomTypeSafeMatcher<T> extends TypeSafeMatcher<T> {
+    private final String fixedDescription;
+
+    public CustomTypeSafeMatcher(String description) {
+        if (description == null) {
+            throw new IllegalArgumentException("Description must be non null!");
+        }
+        this.fixedDescription = description;
+    }
+
+    @Override
+    public final void describeTo(Description description) {
+        description.appendText(fixedDescription);
+    }
+}
diff --git a/hamcrest-core/src/main/java/org/hamcrest/Description.java b/hamcrest-core/src/main/java/org/hamcrest/Description.java
index 36ddeda..73bfa38 100644
--- a/hamcrest-core/src/main/java/org/hamcrest/Description.java
+++ b/hamcrest-core/src/main/java/org/hamcrest/Description.java
@@ -1,44 +1,89 @@
-package org.hamcrest;

-

-/**

- * A description of a Matcher. A Matcher will describe itself to a description

- * which can later be used for reporting.

- *

- * @see Matcher#describeTo(Description)

- */

-public interface Description {

-

-    /**

-     * Appends some plain text to the description.

-     */

-    Description appendText(String text);

-    

-    /**

-     * Appends the description of a {@link SelfDescribing} value to this description.

-     */

-    Description appendDescriptionOf(SelfDescribing value);

-    

-    /**

-     * Appends an arbitary value to the description.

-     */

-    Description appendValue(Object value);

-    

-    /**

-     * Appends a list of values to the description.

-     */

-    <T> Description appendValueList(String start, String separator, String end,

-    							    T... values);

-

-    /**

-     * Appends a list of values to the description.

-     */

-    <T> Description appendValueList(String start, String separator, String end,

-    							    Iterable<T> values);

-    

-    /** 

-     * Appends a list of {@link org.hamcrest.SelfDescribing} objects

-     * to the description. 

-     */

-    Description appendList(String start, String separator, String end, 

-                           Iterable<? extends SelfDescribing> values);

-}

+package org.hamcrest;
+
+/**
+ * A description of a Matcher. A Matcher will describe itself to a description
+ * which can later be used for reporting.
+ *
+ * @see Matcher#describeTo(Description)
+ */
+public interface Description {
+  /**
+   * A description that consumes input but does nothing.
+   */
+  static final Description NONE = new NullDescription();
+  
+    /**
+     * Appends some plain text to the description.
+     */
+    Description appendText(String text);
+
+    /**
+     * Appends the description of a {@link SelfDescribing} value to this description.
+     */
+    Description appendDescriptionOf(SelfDescribing value);
+
+    /**
+     * Appends an arbitrary value to the description.
+     */
+    Description appendValue(Object value);
+
+    /**
+     * Appends a list of values to the description.
+     */
+    <T> Description appendValueList(String start, String separator, String end,
+                                    T... values);
+
+    /**
+     * Appends a list of values to the description.
+     */
+    <T> Description appendValueList(String start, String separator, String end,
+                                    Iterable<T> values);
+
+    /**
+     * Appends a list of {@link org.hamcrest.SelfDescribing} objects
+     * to the description.
+     */
+    Description appendList(String start, String separator, String end,
+                           Iterable<? extends SelfDescribing> values);
+
+
+    public static final class NullDescription implements Description {
+      @Override
+      public Description appendDescriptionOf(SelfDescribing value) {
+        return this;
+      }
+
+      @Override
+      public Description appendList(String start, String separator,
+          String end, Iterable<? extends SelfDescribing> values) {
+        return this;
+      }
+
+      @Override
+      public Description appendText(String text) {
+        return this;
+      }
+
+      @Override
+      public Description appendValue(Object value) {
+        return this;
+      }
+
+      @Override
+      public <T> Description appendValueList(String start, String separator,
+          String end, T... values) {
+        return this;
+      }
+
+      @Override
+      public <T> Description appendValueList(String start, String separator,
+          String end, Iterable<T> values) {
+        return this;
+      }
+
+      @Override
+        public String toString() {
+          return "";
+        }
+    }
+}
diff --git a/hamcrest-core/src/main/java/org/hamcrest/DiagnosingMatcher.java b/hamcrest-core/src/main/java/org/hamcrest/DiagnosingMatcher.java
new file mode 100644
index 0000000..f87de2d
--- /dev/null
+++ b/hamcrest-core/src/main/java/org/hamcrest/DiagnosingMatcher.java
@@ -0,0 +1,21 @@
+package org.hamcrest;
+
+/**
+ * TODO(ngd): Document.
+ *
+ * @param <T>
+ */
+public abstract class DiagnosingMatcher<T> extends BaseMatcher<T> {
+
+    @Override
+    public final boolean matches(Object item) {
+        return matches(item, Description.NONE);
+    }
+
+    @Override
+    public final void describeMismatch(Object item, Description mismatchDescription) {
+        matches(item, mismatchDescription);
+    }
+
+    protected abstract boolean matches(Object item, Description mismatchDescription);
+}
diff --git a/hamcrest-core/src/main/java/org/hamcrest/Factory.java b/hamcrest-core/src/main/java/org/hamcrest/Factory.java
index a8bf5f9..99a5132 100644
--- a/hamcrest-core/src/main/java/org/hamcrest/Factory.java
+++ b/hamcrest-core/src/main/java/org/hamcrest/Factory.java
@@ -1,17 +1,20 @@
 package org.hamcrest;
 
-import static java.lang.annotation.ElementType.METHOD;
 import java.lang.annotation.Retention;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
 import java.lang.annotation.Target;
 
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
 /**
  * Marks a Hamcrest static factory method so tools recognise them.
  * A factory method is an equivalent to a named constructor.
- * 
+ *
+ * @deprecated The code generator is no longer maintained. Write classes of syntactic sugar by hand.
  * @author Joe Walnes
  */
 @Retention(RUNTIME)
 @Target({METHOD})
+@Deprecated
 public @interface Factory {
 }
diff --git a/hamcrest-core/src/main/java/org/hamcrest/FeatureMatcher.java b/hamcrest-core/src/main/java/org/hamcrest/FeatureMatcher.java
new file mode 100644
index 0000000..385cf99
--- /dev/null
+++ b/hamcrest-core/src/main/java/org/hamcrest/FeatureMatcher.java
@@ -0,0 +1,54 @@
+package org.hamcrest;
+
+import org.hamcrest.internal.ReflectiveTypeFinder;
+
+/**
+ * Supporting class for matching a feature of an object. Implement <code>featureValueOf()</code>
+ * in a subclass to pull out the feature to be matched against. 
+ *
+ * @param <T> The type of the object to be matched
+ * @param <U> The type of the feature to be matched
+ */
+public abstract class FeatureMatcher<T, U> extends TypeSafeDiagnosingMatcher<T> {
+  private static final ReflectiveTypeFinder TYPE_FINDER = new ReflectiveTypeFinder("featureValueOf", 1, 0); 
+  private final Matcher<? super U> subMatcher;
+  private final String featureDescription;
+  private final String featureName;
+  
+  /**
+   * Constructor
+   * @param subMatcher The matcher to apply to the feature
+   * @param featureDescription Descriptive text to use in describeTo
+   * @param featureName Identifying text for mismatch message
+   */
+  public FeatureMatcher(Matcher<? super U> subMatcher, String featureDescription, String featureName) {
+    super(TYPE_FINDER);
+    this.subMatcher = subMatcher;
+    this.featureDescription = featureDescription;
+    this.featureName = featureName;
+  }
+  
+  /**
+   * Implement this to extract the interesting feature.
+   * @param actual the target object
+   * @return the feature to be matched
+   */
+  protected abstract U featureValueOf(T actual);
+
+  @Override
+  protected boolean matchesSafely(T actual, Description mismatch) {
+    final U featureValue = featureValueOf(actual);
+    if (!subMatcher.matches(featureValue)) {
+      mismatch.appendText(featureName).appendText(" ");
+      subMatcher.describeMismatch(featureValue, mismatch);
+      return false;
+    }
+    return true;
+  }
+      
+  @Override
+  public final void describeTo(Description description) {
+    description.appendText(featureDescription).appendText(" ")
+               .appendDescriptionOf(subMatcher);
+  }
+}
diff --git a/hamcrest-core/src/main/java/org/hamcrest/Matcher.java b/hamcrest-core/src/main/java/org/hamcrest/Matcher.java
index fd10207..3ac1a53 100644
--- a/hamcrest-core/src/main/java/org/hamcrest/Matcher.java
+++ b/hamcrest-core/src/main/java/org/hamcrest/Matcher.java
@@ -1,32 +1,31 @@
-/*  Copyright (c) 2000-2006 hamcrest.org
- */
 package org.hamcrest;
 
 /**
+ * <p>
  * A matcher over acceptable values.
  * A matcher is able to describe itself to give feedback when it fails.
- * <p/>
+ * </p>
+ * <p>
  * Matcher implementations should <b>NOT directly implement this interface</b>.
  * Instead, <b>extend</b> the {@link BaseMatcher} abstract class,
  * which will ensure that the Matcher API can grow to support
  * new features and remain compatible with all Matcher implementations.
- * <p/>
- * For easy access to common Matcher implementations, use the static factory
- * methods in {@link CoreMatchers}.
+ * </p>
+ * <p>
+ * N.B. Well designed matchers should be immutable.
+ * </p>
  *
- * @see CoreMatchers
  * @see BaseMatcher
  */
-@SuppressWarnings({"unused", "UnusedDeclaration"})
 public interface Matcher<T> extends SelfDescribing {
 
     /**
      * Evaluates the matcher for argument <var>item</var>.
-     * <p/>
+     *
      * This method matches against Object, instead of the generic type T. This is
      * because the caller of the Matcher does not know at runtime what the type is
      * (because of type erasure with Java generics). It is down to the implementations
-     * to check the correct type. 
+     * to check the correct type.
      *
      * @param item the object against which the matcher is evaluated.
      * @return <code>true</code> if <var>item</var> matches, otherwise <code>false</code>.
@@ -34,6 +33,19 @@
      * @see BaseMatcher
      */
     boolean matches(Object item);
+    
+    /**
+     * Generate a description of why the matcher has not accepted the item.
+     * The description will be part of a larger description of why a matching
+     * failed, so it should be concise. 
+     * This method assumes that <code>matches(item)</code> is false, but 
+     * will not check this.
+     *
+     * @param item The item that the Matcher has rejected.
+     * @param mismatchDescription
+     *     The description to be built or appended to.
+     */
+    void describeMismatch(Object item, Description mismatchDescription);
 
     /**
      * This method simply acts a friendly reminder not to implement Matcher directly and
@@ -42,6 +54,8 @@
      *
      * @see Matcher for reasons why.
      * @see BaseMatcher
+     * @deprecated to make
      */
+    @Deprecated
     void _dont_implement_Matcher___instead_extend_BaseMatcher_();
 }
diff --git a/hamcrest-core/src/main/java/org/hamcrest/MatcherAssert.java b/hamcrest-core/src/main/java/org/hamcrest/MatcherAssert.java
index 3eb234a..049e1df 100644
--- a/hamcrest-core/src/main/java/org/hamcrest/MatcherAssert.java
+++ b/hamcrest-core/src/main/java/org/hamcrest/MatcherAssert.java
@@ -1,24 +1,27 @@
-/*  Copyright (c) 2000-2006 hamcrest.org

- */

-package org.hamcrest;

-

-

-public class MatcherAssert {

-    public static <T> void assertThat(T actual, Matcher<T> matcher) {

-        assertThat("", actual, matcher);

-    }

-    

-    public static <T> void assertThat(String reason, T actual, Matcher<T> matcher) {

-        if (!matcher.matches(actual)) {

-            Description description = new StringDescription();

-            description.appendText(reason)

-                       .appendText("\nExpected: ")

-                       .appendDescriptionOf(matcher)

-                       .appendText("\n     got: ")

-                       .appendValue(actual)

-                       .appendText("\n");

-            

-            throw new java.lang.AssertionError(description.toString());

-        }

-    }

-}

+package org.hamcrest;
+
+
+public class MatcherAssert {
+    public static <T> void assertThat(T actual, Matcher<? super T> matcher) {
+        assertThat("", actual, matcher);
+    }
+    
+    public static <T> void assertThat(String reason, T actual, Matcher<? super T> matcher) {
+        if (!matcher.matches(actual)) {
+            Description description = new StringDescription();
+            description.appendText(reason)
+                       .appendText("\nExpected: ")
+                       .appendDescriptionOf(matcher)
+                       .appendText("\n     but: ");
+            matcher.describeMismatch(actual, description);
+            
+            throw new AssertionError(description.toString());
+        }
+    }
+    
+    public static void assertThat(String reason, boolean assertion) {
+        if (!assertion) {
+            throw new AssertionError(reason);
+        }
+    }
+}
diff --git a/hamcrest-core/src/main/java/org/hamcrest/SelfDescribing.java b/hamcrest-core/src/main/java/org/hamcrest/SelfDescribing.java
index cd53070..06b361d 100644
--- a/hamcrest-core/src/main/java/org/hamcrest/SelfDescribing.java
+++ b/hamcrest-core/src/main/java/org/hamcrest/SelfDescribing.java
@@ -12,5 +12,5 @@
      * @param description
      *     The description to be built or appended to.
      */
-	void describeTo(Description description);
+    void describeTo(Description description);
 }
\ No newline at end of file
diff --git a/hamcrest-core/src/main/java/org/hamcrest/StringDescription.java b/hamcrest-core/src/main/java/org/hamcrest/StringDescription.java
index 66709ee..813c178 100644
--- a/hamcrest-core/src/main/java/org/hamcrest/StringDescription.java
+++ b/hamcrest-core/src/main/java/org/hamcrest/StringDescription.java
@@ -1,60 +1,63 @@
-package org.hamcrest;

-

-import java.io.IOException;

-

-/**

- * A {@link Description} that is stored as a string.

- */

-public class StringDescription extends BaseDescription {

-    private final Appendable out;

-

-    public StringDescription() {

-        this(new StringBuilder());

-    }

-

-    public StringDescription(Appendable out) {

-        this.out = out;

-    }

-    

-    /**

-     * Return the description of a {@link SelfDescribing} object as a String.

-     * 

-     * @param selfDescribing

-     *   The object to be described.

-     * @return

-     *   The description of the object.

-     */

-    public static String toString(SelfDescribing value) {

-    	return new StringDescription().appendDescriptionOf(value).toString();

-    }

-

-    /**

-     * Alias for {@link #toString(SelfDescribing)}.

-     */

-    public static String asString(SelfDescribing selfDescribing) {

-        return toString(selfDescribing);

-    }

-

-    protected void append(String str) {

-        try {

-            out.append(str);

-        } catch (IOException e) {

-            throw new RuntimeException("Could not write description", e);

-        }

-    }

-

-    protected void append(char c) {

-        try {

-            out.append(c);

-        } catch (IOException e) {

-            throw new RuntimeException("Could not write description", e);

-        }

-    }

-    

-    /**

-     * Returns the description as a string.

-     */

-    public String toString() {

-        return out.toString();

-    }

-}

+package org.hamcrest;
+
+import java.io.IOException;
+
+/**
+ * A {@link Description} that is stored as a string.
+ */
+public class StringDescription extends BaseDescription {
+    private final Appendable out;
+
+    public StringDescription() {
+        this(new StringBuilder());
+    }
+
+    public StringDescription(Appendable out) {
+        this.out = out;
+    }
+    
+    /**
+     * Return the description of a {@link SelfDescribing} object as a String.
+     * 
+     * @param selfDescribing
+     *   The object to be described.
+     * @return
+     *   The description of the object.
+     */
+    public static String toString(SelfDescribing selfDescribing) {
+        return new StringDescription().appendDescriptionOf(selfDescribing).toString();
+    }
+
+    /**
+     * Alias for {@link #toString(SelfDescribing)}.
+     */
+    public static String asString(SelfDescribing selfDescribing) {
+        return toString(selfDescribing);
+    }
+
+    @Override
+    protected void append(String str) {
+        try {
+            out.append(str);
+        } catch (IOException e) {
+            throw new RuntimeException("Could not write description", e);
+        }
+    }
+
+    @Override
+    protected void append(char c) {
+        try {
+            out.append(c);
+        } catch (IOException e) {
+            throw new RuntimeException("Could not write description", e);
+        }
+    }
+    
+    /**
+     * Returns the description as a string.
+     */
+    @Override
+    public String toString() {
+        return out.toString();
+    }
+}
diff --git a/hamcrest-core/src/main/java/org/hamcrest/TypeSafeDiagnosingMatcher.java b/hamcrest-core/src/main/java/org/hamcrest/TypeSafeDiagnosingMatcher.java
new file mode 100644
index 0000000..c204120
--- /dev/null
+++ b/hamcrest-core/src/main/java/org/hamcrest/TypeSafeDiagnosingMatcher.java
@@ -0,0 +1,69 @@
+package org.hamcrest;
+
+import org.hamcrest.internal.ReflectiveTypeFinder;
+
+
+/**
+ * Convenient base class for Matchers that require a non-null value of a specific type
+ * and that will report why the received value has been rejected.
+ * This implements the null check, checks the type and then casts. 
+ * To use, implement <pre>matchesSafely()</pre>. 
+ *
+ * @param <T>
+ * @author Neil Dunn
+ * @author Nat Pryce
+ * @author Steve Freeman
+ */
+public abstract class TypeSafeDiagnosingMatcher<T> extends BaseMatcher<T> {
+    private static final ReflectiveTypeFinder TYPE_FINDER = new ReflectiveTypeFinder("matchesSafely", 2, 0); 
+    private final Class<?> expectedType;
+
+    /**
+     * Subclasses should implement this. The item will already have been checked
+     * for the specific type and will never be null.
+     */
+    protected abstract boolean matchesSafely(T item, Description mismatchDescription);
+
+    /**
+     * Use this constructor if the subclass that implements <code>matchesSafely</code> 
+     * is <em>not</em> the class that binds &lt;T&gt; to a type. 
+     * @param expectedType The expectedType of the actual value.
+     */
+    protected TypeSafeDiagnosingMatcher(Class<?> expectedType) {
+      this.expectedType = expectedType;
+    }
+
+    /**
+     * Use this constructor if the subclass that implements <code>matchesSafely</code> 
+     * is <em>not</em> the class that binds &lt;T&gt; to a type. 
+     * @param typeFinder A type finder to extract the type
+     */
+    protected TypeSafeDiagnosingMatcher(ReflectiveTypeFinder typeFinder) {
+      this.expectedType = typeFinder.findExpectedType(getClass()); 
+    }
+
+    /**
+     * The default constructor for simple sub types
+     */
+    protected TypeSafeDiagnosingMatcher() {
+      this(TYPE_FINDER); 
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public final boolean matches(Object item) {
+        return item != null
+            && expectedType.isInstance(item)
+            && matchesSafely((T) item, new Description.NullDescription());
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public final void describeMismatch(Object item, Description mismatchDescription) {
+      if (item == null || !expectedType.isInstance(item)) {
+        super.describeMismatch(item, mismatchDescription);
+      } else {
+        matchesSafely((T) item, mismatchDescription);
+      }
+    }
+}
diff --git a/hamcrest-core/src/main/java/org/hamcrest/TypeSafeMatcher.java b/hamcrest-core/src/main/java/org/hamcrest/TypeSafeMatcher.java
index 7f18fd3..08dfce8 100644
--- a/hamcrest-core/src/main/java/org/hamcrest/TypeSafeMatcher.java
+++ b/hamcrest-core/src/main/java/org/hamcrest/TypeSafeMatcher.java
@@ -1,58 +1,85 @@
 package org.hamcrest;
 
-import java.lang.reflect.Method;
+import org.hamcrest.internal.ReflectiveTypeFinder;
 
 /**
  * Convenient base class for Matchers that require a non-null value of a specific type.
  * This simply implements the null check, checks the type and then casts.
  *
  * @author Joe Walnes
+ * @author Steve Freeman
+ * @author Nat Pryce
  */
 public abstract class TypeSafeMatcher<T> extends BaseMatcher<T> {
+    private static final ReflectiveTypeFinder TYPE_FINDER = new ReflectiveTypeFinder("matchesSafely", 1, 0);
+    
+    final private Class<?> expectedType;
 
-    private Class expectedType;
-
+    /**
+     * The default constructor for simple sub types
+     */
+    protected TypeSafeMatcher() {
+        this(TYPE_FINDER);
+    }
+   
+    /**
+     * Use this constructor if the subclass that implements <code>matchesSafely</code> 
+     * is <em>not</em> the class that binds &lt;T&gt; to a type. 
+     * @param expectedType The expectedType of the actual value.
+     */
+    protected TypeSafeMatcher(Class<?> expectedType) {
+        this.expectedType = expectedType;
+    }
+    
+    /**
+     * Use this constructor if the subclass that implements <code>matchesSafely</code> 
+     * is <em>not</em> the class that binds &lt;T&gt; to a type. 
+     * @param typeFinder A type finder to extract the type
+     */
+    protected TypeSafeMatcher(ReflectiveTypeFinder typeFinder) {
+      this.expectedType = typeFinder.findExpectedType(getClass()); 
+    }
+ 
     /**
      * Subclasses should implement this. The item will already have been checked for
      * the specific type and will never be null.
      */
-    public abstract boolean matchesSafely(T item);
-
-    protected TypeSafeMatcher() {
-        expectedType = findExpectedType(getClass());
-    }
+    protected abstract boolean matchesSafely(T item);
     
-    private static Class<?> findExpectedType(Class<?> fromClass) {
-        for (Class<?> c = fromClass; c != Object.class; c = c.getSuperclass()) {
-            for (Method method : c.getDeclaredMethods()) {
-                if (isMatchesSafelyMethod(method)) {
-                    return method.getParameterTypes()[0];
-                }
-            }
-        }
-        
-        throw new Error("Cannot determine correct type for matchesSafely() method.");
-    }
-    
-    private static boolean isMatchesSafelyMethod(Method method) {
-        return method.getName().equals("matchesSafely") 
-            && method.getParameterTypes().length == 1
-            && !method.isSynthetic(); 
-    }
-    
-    protected TypeSafeMatcher(Class<T> expectedType) {
-    	this.expectedType = expectedType;
-    }
-
     /**
-     * Method made final to prevent accidental override.
+     * Subclasses should override this. The item will already have been checked for
+     * the specific type and will never be null.
+     */
+    protected void describeMismatchSafely(T item, Description mismatchDescription) {
+        super.describeMismatch(item, mismatchDescription);
+    }
+    
+    /**
+     * Methods made final to prevent accidental override.
      * If you need to override this, there's no point on extending TypeSafeMatcher.
      * Instead, extend the {@link BaseMatcher}.
      */
+    @Override
     @SuppressWarnings({"unchecked"})
     public final boolean matches(Object item) {
         return item != null
                 && expectedType.isInstance(item)
                 && matchesSafely((T) item);
     }
+    
+    @SuppressWarnings("unchecked")
+    @Override
+    final public void describeMismatch(Object item, Description description) {
+        if (item == null) {
+            super.describeMismatch(null, description);
+        } else if (! expectedType.isInstance(item)) {
+            description.appendText("was a ")
+                       .appendText(item.getClass().getName())
+                       .appendText(" (")
+                       .appendValue(item)
+                       .appendText(")");
+        } else {
+            describeMismatchSafely((T)item, description);
+        }
+    }
 }
diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/AllOf.java b/hamcrest-core/src/main/java/org/hamcrest/core/AllOf.java
index f619a7d..2cbe2e3 100644
--- a/hamcrest-core/src/main/java/org/hamcrest/core/AllOf.java
+++ b/hamcrest-core/src/main/java/org/hamcrest/core/AllOf.java
@@ -1,51 +1,57 @@
 package org.hamcrest.core;
 
-import org.hamcrest.BaseMatcher;
-import org.hamcrest.Matcher;
 import org.hamcrest.Description;
-import org.hamcrest.Factory;
+import org.hamcrest.DiagnosingMatcher;
+import org.hamcrest.Matcher;
 
 import java.util.Arrays;
+import java.util.List;
 
 /**
- * Calculates the logical conjunction of two matchers. Evaluation is
- * shortcut, so that the second matcher is not called if the first
- * matcher returns <code>false</code>.
+ * Calculates the logical conjunction of multiple matchers. Evaluation is shortcut, so
+ * subsequent matchers are not called if an earlier matcher returns <code>false</code>.
  */
-public class AllOf<T> extends BaseMatcher<T> {
-    private final Iterable<Matcher<? extends T>> matchers;
+public class AllOf<T> extends DiagnosingMatcher<T> {
 
-    public AllOf(Iterable<Matcher<? extends T>> matchers) {
+    private final Iterable<Matcher<? super T>> matchers;
+
+    public AllOf(Iterable<Matcher<? super T>> matchers) {
         this.matchers = matchers;
     }
 
-    public boolean matches(Object o) {
-        for (Matcher<? extends T> matcher : matchers) {
+    @Override
+    public boolean matches(Object o, Description mismatch) {
+        for (Matcher<? super T> matcher : matchers) {
             if (!matcher.matches(o)) {
-                return false;
+                mismatch.appendDescriptionOf(matcher).appendText(" ");
+                matcher.describeMismatch(o, mismatch);
+              return false;
             }
         }
         return true;
     }
 
+    @Override
     public void describeTo(Description description) {
-    	description.appendList("(", " and ", ")", matchers);
+        description.appendList("(", " " + "and" + " ", ")", matchers);
     }
 
     /**
-     * Evaluates to true only if ALL of the passed in matchers evaluate to true.
+     * Creates a matcher that matches if the examined object matches <b>ALL</b> of the specified matchers.
+     * For example:
+     * <pre>assertThat("myValue", allOf(startsWith("my"), containsString("Val")))</pre>
      */
-    @Factory
-    public static <T> Matcher<T> allOf(Matcher<? extends T>... matchers) {
-        return allOf(Arrays.asList(matchers));
+    public static <T> Matcher<T> allOf(Iterable<Matcher<? super T>> matchers) {
+        return new AllOf<>(matchers);
     }
 
     /**
-     * Evaluates to true only if ALL of the passed in matchers evaluate to true.
+     * Creates a matcher that matches if the examined object matches <b>ALL</b> of the specified matchers.
+     * For example:
+     * <pre>assertThat("myValue", allOf(startsWith("my"), containsString("Val")))</pre>
      */
-    @Factory
-    public static <T> Matcher<T> allOf(Iterable<Matcher<? extends T>> matchers) {
-        return new AllOf<T>(matchers);
+    @SafeVarargs
+    public static <T> Matcher<T> allOf(Matcher<? super T>... matchers) {
+        return allOf((List) Arrays.asList(matchers));
     }
-
 }
diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/AnyOf.java b/hamcrest-core/src/main/java/org/hamcrest/core/AnyOf.java
index e7e9181..106a473 100644
--- a/hamcrest-core/src/main/java/org/hamcrest/core/AnyOf.java
+++ b/hamcrest-core/src/main/java/org/hamcrest/core/AnyOf.java
@@ -1,51 +1,47 @@
 package org.hamcrest.core;
 
-import org.hamcrest.BaseMatcher;
-import org.hamcrest.Matcher;
 import org.hamcrest.Description;
-import org.hamcrest.Factory;
+import org.hamcrest.Matcher;
 
 import java.util.Arrays;
+import java.util.List;
 
 /**
- * Calculates the logical disjunction of two matchers. Evaluation is
- * shortcut, so that the second matcher is not called if the first
- * matcher returns <code>true</code>.
+ * Calculates the logical disjunction of multiple matchers. Evaluation is shortcut, so
+ * subsequent matchers are not called if an earlier matcher returns <code>true</code>.
  */
-public class AnyOf<T> extends BaseMatcher<T> {
+public class AnyOf<T> extends ShortcutCombination<T> {
 
-    private final Iterable<Matcher<? extends T>> matchers;
-
-    public AnyOf(Iterable<Matcher<? extends T>> matchers) {
-        this.matchers = matchers;
+    public AnyOf(Iterable<Matcher<? super T>> matchers) {
+        super(matchers);
     }
 
+    @Override
     public boolean matches(Object o) {
-        for (Matcher<? extends T> matcher : matchers) {
-            if (matcher.matches(o)) {
-                return true;
-            }
-        }
-        return false;
+        return matches(o, true);
     }
 
+    @Override
     public void describeTo(Description description) {
-    	description.appendList("(", " or ", ")", matchers);
+        describeTo(description, "or");
     }
 
     /**
-     * Evaluates to true if ANY of the passed in matchers evaluate to true.
+     * Creates a matcher that matches if the examined object matches <b>ANY</b> of the specified matchers.
+     * For example:
+     * <pre>assertThat("myValue", anyOf(startsWith("foo"), containsString("Val")))</pre>
      */
-    @Factory
-    public static <T> Matcher<T> anyOf(Matcher<? extends T>... matchers) {
-        return anyOf(Arrays.asList(matchers));
+    public static <T> AnyOf<T> anyOf(Iterable<Matcher<? super T>> matchers) {
+        return new AnyOf<>(matchers);
     }
-
+    
     /**
-     * Evaluates to true if ANY of the passed in matchers evaluate to true.
+     * Creates a matcher that matches if the examined object matches <b>ANY</b> of the specified matchers.
+     * For example:
+     * <pre>assertThat("myValue", anyOf(startsWith("foo"), containsString("Val")))</pre>
      */
-    @Factory
-    public static <T> Matcher<T> anyOf(Iterable<Matcher<? extends T>> matchers) {
-        return new AnyOf<T>(matchers);
+    @SafeVarargs
+    public static <T> AnyOf<T> anyOf(Matcher<? super T>... matchers) {
+        return anyOf((List) Arrays.asList(matchers));
     }
 }
diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/CombinableMatcher.java b/hamcrest-core/src/main/java/org/hamcrest/core/CombinableMatcher.java
new file mode 100644
index 0000000..2414bbb
--- /dev/null
+++ b/hamcrest-core/src/main/java/org/hamcrest/core/CombinableMatcher.java
@@ -0,0 +1,82 @@
+package org.hamcrest.core;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeDiagnosingMatcher;
+
+import java.util.ArrayList;
+
+public class CombinableMatcher<T> extends TypeSafeDiagnosingMatcher<T> {
+  private final Matcher<? super T> matcher;
+
+  public CombinableMatcher(Matcher<? super T> matcher) {
+    this.matcher = matcher;
+  }
+
+  @Override
+  protected boolean matchesSafely(T item, Description mismatch) {
+    if (!matcher.matches(item)) {
+      matcher.describeMismatch(item, mismatch);
+      return false;
+    }
+    return true;
+  }
+
+  @Override
+  public void describeTo(Description description) {
+    description.appendDescriptionOf(matcher);
+  }
+
+  public CombinableMatcher<T> and(Matcher<? super T> other) {
+    return new CombinableMatcher<T>(new AllOf<T>(templatedListWith(other)));
+  }
+
+  public CombinableMatcher<T> or(Matcher<? super T> other) {
+    return new CombinableMatcher<T>(new AnyOf<T>(templatedListWith(other)));
+  }
+
+  private ArrayList<Matcher<? super T>> templatedListWith(Matcher<? super T> other) {
+    ArrayList<Matcher<? super T>> matchers = new ArrayList<Matcher<? super T>>();
+    matchers.add(matcher);
+    matchers.add(other);
+    return matchers;
+  }
+
+  /**
+   * Creates a matcher that matches when both of the specified matchers match the examined object.
+   * For example:
+   * <pre>assertThat("fab", both(containsString("a")).and(containsString("b")))</pre>
+   */
+  public static <LHS> CombinableBothMatcher<LHS> both(Matcher<? super LHS> matcher) {
+    return new CombinableBothMatcher<LHS>(matcher);
+  }
+  
+  public static final class CombinableBothMatcher<X> {
+    private final Matcher<? super X> first;
+    public CombinableBothMatcher(Matcher<? super X> matcher) {
+        this.first = matcher;
+    }
+    public CombinableMatcher<X> and(Matcher<? super X> other) {
+      return new CombinableMatcher<X>(first).and(other);
+    }
+  }
+
+  /**
+   * Creates a matcher that matches when either of the specified matchers match the examined object.
+   * For example:
+   * <pre>assertThat("fan", either(containsString("a")).or(containsString("b")))</pre>
+   */
+  public static <LHS> CombinableEitherMatcher<LHS> either(Matcher<? super LHS> matcher) {
+    return new CombinableEitherMatcher<LHS>(matcher);
+  }
+  
+  public static final class CombinableEitherMatcher<X> {
+    private final Matcher<? super X> first;
+    public CombinableEitherMatcher(Matcher<? super X> matcher) {
+        this.first = matcher;
+    }
+    public CombinableMatcher<X> or(Matcher<? super X> other) {
+      return new CombinableMatcher<X>(first).or(other);
+    }
+  }
+}
diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/DescribedAs.java b/hamcrest-core/src/main/java/org/hamcrest/core/DescribedAs.java
index 7b8c151..2387609 100644
--- a/hamcrest-core/src/main/java/org/hamcrest/core/DescribedAs.java
+++ b/hamcrest-core/src/main/java/org/hamcrest/core/DescribedAs.java
@@ -1,55 +1,69 @@
-/*  Copyright (c) 2000-2006 hamcrest.org

- */

-package org.hamcrest.core;

-

-import java.util.regex.Pattern;

-

-import org.hamcrest.Description;

-import org.hamcrest.Matcher;

-import org.hamcrest.Factory;

-import org.hamcrest.BaseMatcher;

-

-/**

- * Provides a custom description to another matcher.

- */

-public class DescribedAs<T> extends BaseMatcher<T> {

-    private final String descriptionTemplate;

-    private final Matcher<T> matcher;

-    private final Object[] values;

-    

-    private final static Pattern ARG_PATTERN = Pattern.compile("%([0-9]+)"); 

-    

-    public DescribedAs(String descriptionTemplate, Matcher<T> matcher, Object[] values) {

-        this.descriptionTemplate = descriptionTemplate;

-        this.matcher = matcher;

-        this.values = values.clone();

-    }

-    

-    public boolean matches(Object o) {

-        return matcher.matches(o);

-    }

-

-    public void describeTo(Description description) {

-        java.util.regex.Matcher arg = ARG_PATTERN.matcher(descriptionTemplate);

-        

-        int textStart = 0;

-        while (arg.find()) {

-            description.appendText(descriptionTemplate.substring(textStart, arg.start()));

-            int argIndex = Integer.parseInt(arg.group(1));

-            description.appendValue(values[argIndex]);

-            textStart = arg.end();

-        }

-        

-        if (textStart < descriptionTemplate.length()) {

-            description.appendText(descriptionTemplate.substring(textStart));

-        }

-    }

-

-    /**

-     * Wraps an existing matcher and overrides the description when it fails.

-     */

-    @Factory

-    public static <T> Matcher<T> describedAs(String description, Matcher<T> matcher, Object... values) {

-        return new DescribedAs<T>(description, matcher, values);

-    }

-}

+package org.hamcrest.core;
+
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+
+import java.util.regex.Pattern;
+
+import static java.lang.Integer.parseInt;
+
+/**
+ * Provides a custom description to another matcher.
+ */
+public class DescribedAs<T> extends BaseMatcher<T> {
+    private final String descriptionTemplate;
+    private final Matcher<T> matcher;
+    private final Object[] values;
+    
+    private final static Pattern ARG_PATTERN = Pattern.compile("%([0-9]+)"); 
+    
+    public DescribedAs(String descriptionTemplate, Matcher<T> matcher, Object[] values) {
+        this.descriptionTemplate = descriptionTemplate;
+        this.matcher = matcher;
+        this.values = values.clone();
+    }
+    
+    @Override
+    public boolean matches(Object o) {
+        return matcher.matches(o);
+    }
+
+    @Override
+    public void describeTo(Description description) {
+        java.util.regex.Matcher arg = ARG_PATTERN.matcher(descriptionTemplate);
+        
+        int textStart = 0;
+        while (arg.find()) {
+            description.appendText(descriptionTemplate.substring(textStart, arg.start()));
+            description.appendValue(values[parseInt(arg.group(1))]);
+            textStart = arg.end();
+        }
+        
+        if (textStart < descriptionTemplate.length()) {
+            description.appendText(descriptionTemplate.substring(textStart));
+        }
+    }
+    
+    @Override
+    public void describeMismatch(Object item, Description description) {
+        matcher.describeMismatch(item, description);
+    }
+
+    /**
+     * Wraps an existing matcher, overriding its description with that specified.  All other functions are
+     * delegated to the decorated matcher, including its mismatch description.
+     * For example:
+     * <pre>describedAs("a big decimal equal to %0", equalTo(myBigDecimal), myBigDecimal.toPlainString())</pre> 
+     * 
+     * @param description
+     *     the new description for the wrapped matcher
+     * @param matcher
+     *     the matcher to wrap
+     * @param values
+     *     optional values to insert into the tokenised description
+     */
+    public static <T> Matcher<T> describedAs(String description, Matcher<T> matcher, Object... values) {
+        return new DescribedAs<T>(description, matcher, values);
+    }
+}
diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/Every.java b/hamcrest-core/src/main/java/org/hamcrest/core/Every.java
new file mode 100644
index 0000000..757b7b4
--- /dev/null
+++ b/hamcrest-core/src/main/java/org/hamcrest/core/Every.java
@@ -0,0 +1,44 @@
+package org.hamcrest.core;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeDiagnosingMatcher;
+
+public class Every<T> extends TypeSafeDiagnosingMatcher<Iterable<? extends T>> {
+    private final Matcher<? super T> matcher;
+
+    public Every(Matcher<? super T> matcher) {
+        this.matcher= matcher;
+    }
+
+    @Override
+    public boolean matchesSafely(Iterable<? extends T> collection, Description mismatchDescription) {
+        for (T t : collection) {
+            if (!matcher.matches(t)) {
+                mismatchDescription.appendText("an item ");
+                matcher.describeMismatch(t, mismatchDescription);
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public void describeTo(Description description) {
+        description.appendText("every item is ").appendDescriptionOf(matcher);
+    }
+
+    /**
+     * Creates a matcher for {@link Iterable}s that only matches when a single pass over the
+     * examined {@link Iterable} yields items that are all matched by the specified
+     * <code>itemMatcher</code>.
+     * For example:
+     * <pre>assertThat(Arrays.asList("bar", "baz"), everyItem(startsWith("ba")))</pre>
+     * 
+     * @param itemMatcher
+     *     the matcher to apply to every item provided by the examined {@link Iterable}
+     */
+    public static <U> Matcher<Iterable<? extends U>> everyItem(final Matcher<U> itemMatcher) {
+        return new Every<U>(itemMatcher);
+    }
+}
diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/Is.java b/hamcrest-core/src/main/java/org/hamcrest/core/Is.java
index f9152e9..ec22238 100644
--- a/hamcrest-core/src/main/java/org/hamcrest/core/Is.java
+++ b/hamcrest-core/src/main/java/org/hamcrest/core/Is.java
@@ -1,68 +1,76 @@
 package org.hamcrest.core;
 
-import static org.hamcrest.core.IsInstanceOf.instanceOf;
-import static org.hamcrest.core.IsEqual.equalTo;
-import org.hamcrest.Factory;
-import org.hamcrest.Matcher;
 import org.hamcrest.BaseMatcher;
 import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
 
 /**
- * Decorates another Matcher, retaining the behavior but allowing tests
+ * Decorates another Matcher, retaining the behaviour but allowing tests
  * to be slightly more expressive.
  *
- * eg. assertThat(cheese, equalTo(smelly))
- * vs  assertThat(cheese, is(equalTo(smelly)))
+ * For example:  assertThat(cheese, equalTo(smelly))
+ *          vs.  assertThat(cheese, is(equalTo(smelly)))
  */
 public class Is<T> extends BaseMatcher<T> {
-
     private final Matcher<T> matcher;
 
     public Is(Matcher<T> matcher) {
         this.matcher = matcher;
     }
 
+    @Override
     public boolean matches(Object arg) {
         return matcher.matches(arg);
     }
 
+    @Override
     public void describeTo(Description description) {
         description.appendText("is ").appendDescriptionOf(matcher);
     }
-    
+
+    @Override
+    public void describeMismatch(Object item, Description mismatchDescription) {
+        matcher.describeMismatch(item, mismatchDescription);
+    }
+
     /**
-     * Decorates another Matcher, retaining the behavior but allowing tests
+     * Decorates another Matcher, retaining its behaviour, but allowing tests
      * to be slightly more expressive.
-     *
-     * eg. assertThat(cheese, equalTo(smelly))
-     * vs  assertThat(cheese, is(equalTo(smelly)))
+     * For example:
+     * <pre>assertThat(cheese, is(equalTo(smelly)))</pre>
+     * instead of:
+     * <pre>assertThat(cheese, equalTo(smelly))</pre>
+     * 
      */
-    @Factory
     public static <T> Matcher<T> is(Matcher<T> matcher) {
         return new Is<T>(matcher);
     }
 
     /**
-     * This is a shortcut to the frequently used is(equalTo(x)).
-     *
-     * eg. assertThat(cheese, is(equalTo(smelly)))
-     * vs  assertThat(cheese, is(smelly))
+     * A shortcut to the frequently used <code>is(equalTo(x))</code>.
+     * For example:
+     * <pre>assertThat(cheese, is(smelly))</pre>
+     * instead of:
+     * <pre>assertThat(cheese, is(equalTo(smelly)))</pre>
+     * 
      */
-    @Factory
     public static <T> Matcher<T> is(T value) {
         return is(equalTo(value));
     }
 
     /**
-     * This is a shortcut to the frequently used is(instanceOf(SomeClass.class)).
-     *
-     * eg. assertThat(cheese, is(instanceOf(Cheddar.class)))
-     * vs  assertThat(cheese, is(Cheddar.class))
+     * A shortcut to the frequently used <code>is(instanceOf(SomeClass.class))</code>.
+     * For example:
+     * <pre>assertThat(cheese, isA(Cheddar.class))</pre>
+     * instead of:
+     * <pre>assertThat(cheese, is(instanceOf(Cheddar.class)))</pre>
+     * 
      */
-    @Factory
-    public static Matcher<Object> is(Class<?> type) {
-        return is(instanceOf(type));
+    public static <T> Matcher<T> isA(Class<T> type) {
+        final Matcher<T> typeMatcher = instanceOf(type);
+        return is(typeMatcher);
     }
-
 }
-
diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/IsAnything.java b/hamcrest-core/src/main/java/org/hamcrest/core/IsAnything.java
index c5ca49d..4c71a9b 100644
--- a/hamcrest-core/src/main/java/org/hamcrest/core/IsAnything.java
+++ b/hamcrest-core/src/main/java/org/hamcrest/core/IsAnything.java
@@ -1,11 +1,8 @@
-/*  Copyright (c) 2000-2006 hamcrest.org
- */
 package org.hamcrest.core;
 
+import org.hamcrest.BaseMatcher;
 import org.hamcrest.Description;
 import org.hamcrest.Matcher;
-import org.hamcrest.Factory;
-import org.hamcrest.BaseMatcher;
 
 
 /**
@@ -13,47 +10,41 @@
  */
 public class IsAnything<T> extends BaseMatcher<T> {
 
-    private final String description;
+    private final String message;
 
     public IsAnything() {
         this("ANYTHING");
     }
 
-    public IsAnything(String description) {
-        this.description = description;
+    public IsAnything(String message) {
+        this.message = message;
     }
 
+    @Override
     public boolean matches(Object o) {
         return true;
     }
 
+    @Override
     public void describeTo(Description description) {
-        description.appendText(this.description);
+        description.appendText(message);
     }
 
     /**
-     * This matcher always evaluates to true.
+     * Creates a matcher that always matches, regardless of the examined object.
      */
-    @Factory
-    public static <T> Matcher<T> anything() {
-        return new IsAnything<T>();
+    public static Matcher<Object> anything() {
+        return new IsAnything<Object>();
     }
 
     /**
-     * This matcher always evaluates to true.
+     * Creates a matcher that always matches, regardless of the examined object, but describes
+     * itself with the specified {@link String}.
      *
-     * @param description A meaningful string used when describing itself.
+     * @param description
+     *     a meaningful {@link String} used when describing itself
      */
-    @Factory
-    public static <T> Matcher<T> anything(String description) {
-        return new IsAnything<T>(description);
-    }
-
-    /**
-     * This matcher always evaluates to true. With type inference.
-     */
-    @Factory
-    public static <T> Matcher<T> any(@SuppressWarnings("unused")Class<T> type) {
-        return new IsAnything<T>();
+    public static Matcher<Object> anything(String description) {
+        return new IsAnything<Object>(description);
     }
 }
diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/IsCollectionContaining.java b/hamcrest-core/src/main/java/org/hamcrest/core/IsCollectionContaining.java
new file mode 100644
index 0000000..c55853d
--- /dev/null
+++ b/hamcrest-core/src/main/java/org/hamcrest/core/IsCollectionContaining.java
@@ -0,0 +1,133 @@
+package org.hamcrest.core;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeDiagnosingMatcher;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.hamcrest.core.AllOf.allOf;
+import static org.hamcrest.core.IsEqual.equalTo;
+
+public class IsCollectionContaining<T> extends TypeSafeDiagnosingMatcher<Iterable<? super T>> {
+    private final Matcher<? super T> elementMatcher;
+
+    public IsCollectionContaining(Matcher<? super T> elementMatcher) {
+        this.elementMatcher = elementMatcher;
+    }
+
+    @Override
+    protected boolean matchesSafely(Iterable<? super T> collection, Description mismatchDescription) {
+        if (isEmpty(collection)) {
+          mismatchDescription.appendText("was empty");
+          return false;
+        }
+
+        for (Object item : collection) {
+            if (elementMatcher.matches(item)) {
+                return true;
+            }
+        }
+
+        mismatchDescription.appendText("mismatches were: [");
+        boolean isPastFirst = false;
+        for (Object item : collection) {
+            if (isPastFirst) {
+              mismatchDescription.appendText(", ");
+            }
+            elementMatcher.describeMismatch(item, mismatchDescription);
+            isPastFirst = true;
+        }
+        mismatchDescription.appendText("]");
+        return false;
+    }
+
+    private boolean isEmpty(Iterable<? super T> iterable) {
+      return ! iterable.iterator().hasNext();
+    }
+
+    @Override
+    public void describeTo(Description description) {
+        description
+            .appendText("a collection containing ")
+            .appendDescriptionOf(elementMatcher);
+    }
+
+    
+    /**
+     * Creates a matcher for {@link Iterable}s that only matches when a single pass over the
+     * examined {@link Iterable} yields at least one item that is matched by the specified
+     * <code>itemMatcher</code>.  Whilst matching, the traversal of the examined {@link Iterable}
+     * will stop as soon as a matching item is found.
+     * For example:
+     * <pre>assertThat(Arrays.asList("foo", "bar"), hasItem(startsWith("ba")))</pre>
+     * 
+     * @param itemMatcher
+     *     the matcher to apply to items provided by the examined {@link Iterable}
+     */
+    public static <T> Matcher<Iterable<? super T>> hasItem(Matcher<? super T> itemMatcher) {
+        return new IsCollectionContaining<>(itemMatcher);
+    }
+
+    /**
+     * Creates a matcher for {@link Iterable}s that only matches when a single pass over the
+     * examined {@link Iterable} yields at least one item that is equal to the specified
+     * <code>item</code>.  Whilst matching, the traversal of the examined {@link Iterable}
+     * will stop as soon as a matching item is found.
+     * For example:
+     * <pre>assertThat(Arrays.asList("foo", "bar"), hasItem("bar"))</pre>
+     * 
+     * @param item
+     *     the item to compare against the items provided by the examined {@link Iterable}
+     */
+    public static <T> Matcher<Iterable<? super T>> hasItem(T item) {
+        // Doesn't forward to hasItem() method so compiler can sort out generics.
+        return new IsCollectionContaining<>(equalTo(item));
+    }
+
+    /**
+     * Creates a matcher for {@link Iterable}s that matches when consecutive passes over the
+     * examined {@link Iterable} yield at least one item that is matched by the corresponding
+     * matcher from the specified <code>itemMatchers</code>.  Whilst matching, each traversal of
+     * the examined {@link Iterable} will stop as soon as a matching item is found.
+     * For example:
+     * <pre>assertThat(Arrays.asList("foo", "bar", "baz"), hasItems(endsWith("z"), endsWith("o")))</pre>
+     * 
+     * @param itemMatchers
+     *     the matchers to apply to items provided by the examined {@link Iterable}
+     */
+    @SafeVarargs
+    public static <T> Matcher<Iterable<T>> hasItems(Matcher<? super T>... itemMatchers) {
+        List<Matcher<? super Iterable<T>>> all = new ArrayList<>(itemMatchers.length);
+        
+        for (Matcher<? super T> elementMatcher : itemMatchers) {
+          // Doesn't forward to hasItem() method so compiler can sort out generics.
+          all.add(new IsCollectionContaining<>(elementMatcher));
+        }
+        
+        return allOf(all);
+    }
+    
+    /**
+     * Creates a matcher for {@link Iterable}s that matches when consecutive passes over the
+     * examined {@link Iterable} yield at least one item that is equal to the corresponding
+     * item from the specified <code>items</code>.  Whilst matching, each traversal of the
+     * examined {@link Iterable} will stop as soon as a matching item is found.
+     * For example:
+     * <pre>assertThat(Arrays.asList("foo", "bar", "baz"), hasItems("baz", "foo"))</pre>
+     * 
+     * @param items
+     *     the items to compare against the items provided by the examined {@link Iterable}
+     */
+    @SafeVarargs
+    public static <T> Matcher<Iterable<T>> hasItems(T... items) {
+        List<Matcher<? super Iterable<T>>> all = new ArrayList<>(items.length);
+        for (T item : items) {
+            all.add(hasItem(item));
+        }
+        
+        return allOf(all);
+    }
+
+}
diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/IsEqual.java b/hamcrest-core/src/main/java/org/hamcrest/core/IsEqual.java
index b9f17c5..860e85e 100644
--- a/hamcrest-core/src/main/java/org/hamcrest/core/IsEqual.java
+++ b/hamcrest-core/src/main/java/org/hamcrest/core/IsEqual.java
@@ -1,11 +1,8 @@
-/*  Copyright (c) 2000-2006 hamcrest.org
- */
 package org.hamcrest.core;
 
+import org.hamcrest.BaseMatcher;
 import org.hamcrest.Description;
 import org.hamcrest.Matcher;
-import org.hamcrest.Factory;
-import org.hamcrest.BaseMatcher;
 
 import java.lang.reflect.Array;
 
@@ -15,42 +12,47 @@
  * {@link java.lang.Object#equals} invokedMethod?
  */
 public class IsEqual<T> extends BaseMatcher<T> {
-    private final Object object;
+    private final Object expectedValue;
 
     public IsEqual(T equalArg) {
-        object = equalArg;
+        expectedValue = equalArg;
     }
 
-    public boolean matches(Object arg) {
-        return areEqual(object, arg);
+    @Override
+    public boolean matches(Object actualValue) {
+        return areEqual(actualValue, expectedValue);
     }
 
+    @Override
     public void describeTo(Description description) {
-        description.appendValue(object);
+        description.appendValue(expectedValue);
     }
 
-    private static boolean areEqual(Object o1, Object o2) {
-        if (o1 == null || o2 == null) {
-            return o1 == null && o2 == null;
-        } else if (isArray(o1)) {
-            return isArray(o2) && areArraysEqual(o1, o2);
-        } else {
-            return o1.equals(o2);
+    private static boolean areEqual(Object actual, Object expected) {
+        if (actual == null) {
+            return expected == null;
         }
+        
+        if (expected != null && isArray(actual)) {
+            return isArray(expected) && areArraysEqual(actual, expected);
+        }
+        
+        return actual.equals(expected);
     }
 
-    private static boolean areArraysEqual(Object o1, Object o2) {
-        return areArrayLengthsEqual(o1, o2)
-                && areArrayElementsEqual(o1, o2);
+    private static boolean areArraysEqual(Object actualArray, Object expectedArray) {
+        return areArrayLengthsEqual(actualArray, expectedArray) && areArrayElementsEqual(actualArray, expectedArray);
     }
 
-    private static boolean areArrayLengthsEqual(Object o1, Object o2) {
-        return Array.getLength(o1) == Array.getLength(o2);
+    private static boolean areArrayLengthsEqual(Object actualArray, Object expectedArray) {
+        return Array.getLength(actualArray) == Array.getLength(expectedArray);
     }
 
-    private static boolean areArrayElementsEqual(Object o1, Object o2) {
-        for (int i = 0; i < Array.getLength(o1); i++) {
-            if (!areEqual(Array.get(o1, i), Array.get(o2, i))) return false;
+    private static boolean areArrayElementsEqual(Object actualArray, Object expectedArray) {
+        for (int i = 0; i < Array.getLength(actualArray); i++) {
+            if (!areEqual(Array.get(actualArray, i), Array.get(expectedArray, i))) {
+                return false;
+            }
         }
         return true;
     }
@@ -60,12 +62,36 @@
     }
 
     /**
-     * Is the value equal to another value, as tested by the
-     * {@link java.lang.Object#equals} invokedMethod?
+     * Creates a matcher that matches when the examined object is logically equal to the specified
+     * <code>operand</code>, as determined by calling the {@link java.lang.Object#equals} method on
+     * the <b>examined</b> object.
+     * 
+     * <p>If the specified operand is <code>null</code> then the created matcher will only match if
+     * the examined object's <code>equals</code> method returns <code>true</code> when passed a
+     * <code>null</code> (which would be a violation of the <code>equals</code> contract), unless the
+     * examined object itself is <code>null</code>, in which case the matcher will return a positive
+     * match.</p>
+     * 
+     * <p>The created matcher provides a special behaviour when examining <code>Array</code>s, whereby
+     * it will match if both the operand and the examined object are arrays of the same length and
+     * contain items that are equal to each other (according to the above rules) <b>in the same
+     * indexes</b>.</p> 
+     * For example:
+     * <pre>
+     * assertThat("foo", equalTo("foo"));
+     * assertThat(new String[] {"foo", "bar"}, equalTo(new String[] {"foo", "bar"}));
+     * </pre>
+     * 
      */
-    @Factory
     public static <T> Matcher<T> equalTo(T operand) {
         return new IsEqual<T>(operand);
     }
-    
+
+    /**
+     * Creates an {@link org.hamcrest.core.IsEqual} matcher that does not enforce the values being
+     * compared to be of the same static type.
+     */
+    public static Matcher<Object> equalToObject(Object operand) {
+        return new IsEqual<Object>(operand);
+    }
 }
diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/IsInstanceOf.java b/hamcrest-core/src/main/java/org/hamcrest/core/IsInstanceOf.java
index df20824..5a508c9 100644
--- a/hamcrest-core/src/main/java/org/hamcrest/core/IsInstanceOf.java
+++ b/hamcrest-core/src/main/java/org/hamcrest/core/IsInstanceOf.java
@@ -1,44 +1,91 @@
-/*  Copyright (c) 2000-2006 hamcrest.org
- */
 package org.hamcrest.core;
 
 import org.hamcrest.Description;
+import org.hamcrest.DiagnosingMatcher;
 import org.hamcrest.Matcher;
-import org.hamcrest.Factory;
-import org.hamcrest.BaseMatcher;
 
 
 /**
  * Tests whether the value is an instance of a class.
+ * Classes of basic types will be converted to the relevant "Object" classes
  */
-public class IsInstanceOf extends BaseMatcher<Object> {
-    private final Class<?> theClass;
+public class IsInstanceOf extends DiagnosingMatcher<Object> {
+    private final Class<?> expectedClass;
+    private final Class<?> matchableClass;
 
     /**
      * Creates a new instance of IsInstanceOf
      *
-     * @param theClass The predicate evaluates to true for instances of this class
+     * @param expectedClass The predicate evaluates to true for instances of this class
      *                 or one of its subclasses.
      */
-    public IsInstanceOf(Class<?> theClass) {
-        this.theClass = theClass;
+    public IsInstanceOf(Class<?> expectedClass) {
+        this.expectedClass = expectedClass;
+        this.matchableClass = matchableClass(expectedClass);
     }
 
-    public boolean matches(Object item) {
-        return theClass.isInstance(item);
+    private static Class<?> matchableClass(Class<?> expectedClass) {
+      if (boolean.class.equals(expectedClass)) return Boolean.class; 
+      if (byte.class.equals(expectedClass)) return Byte.class; 
+      if (char.class.equals(expectedClass)) return Character.class; 
+      if (double.class.equals(expectedClass)) return Double.class; 
+      if (float.class.equals(expectedClass)) return Float.class; 
+      if (int.class.equals(expectedClass)) return Integer.class; 
+      if (long.class.equals(expectedClass)) return Long.class; 
+      if (short.class.equals(expectedClass)) return Short.class; 
+      return expectedClass;
     }
 
+    @Override
+    protected boolean matches(Object item, Description mismatch) {
+      if (null == item) {
+        mismatch.appendText("null");
+        return false;
+      }
+      
+      if (!matchableClass.isInstance(item)) {
+        mismatch.appendValue(item).appendText(" is a " + item.getClass().getName());
+        return false;
+      }
+      
+      return true;
+    }
+
+    @Override
     public void describeTo(Description description) {
-        description.appendText("an instance of ")
-                .appendText(theClass.getName());
+        description.appendText("an instance of ").appendText(expectedClass.getName());
     }
 
     /**
-     * Is the value an instance of a particular type?
+     * Creates a matcher that matches when the examined object is an instance of the specified <code>type</code>,
+     * as determined by calling the {@link java.lang.Class#isInstance(Object)} method on that type, passing the
+     * the examined object.
+     * 
+     * <p>The created matcher assumes no relationship between specified type and the examined object.</p>
+     * For example:
+     * <pre>assertThat(new Canoe(), instanceOf(Paddlable.class));</pre>
+     * 
      */
-    @Factory
-    public static Matcher<Object> instanceOf(Class<?> type) {
-        return new IsInstanceOf(type);
+    @SuppressWarnings("unchecked")
+    public static <T> Matcher<T> instanceOf(Class<?> type) {
+        return (Matcher<T>) new IsInstanceOf(type);
+    }
+    
+    /**
+     * Creates a matcher that matches when the examined object is an instance of the specified <code>type</code>,
+     * as determined by calling the {@link java.lang.Class#isInstance(Object)} method on that type, passing the
+     * the examined object.
+     * 
+     * <p>The created matcher forces a relationship between specified type and the examined object, and should be
+     * used when it is necessary to make generics conform, for example in the JMock clause
+     * <code>with(any(Thing.class))</code></p>
+     * For example:
+     * <pre>assertThat(new Canoe(), instanceOf(Canoe.class));</pre>
+     *
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> Matcher<T> any(Class<T> type) {
+        return (Matcher<T>) new IsInstanceOf(type);
     }
 
 }
diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/IsNot.java b/hamcrest-core/src/main/java/org/hamcrest/core/IsNot.java
index cb6946c..d5cf9c0 100644
--- a/hamcrest-core/src/main/java/org/hamcrest/core/IsNot.java
+++ b/hamcrest-core/src/main/java/org/hamcrest/core/IsNot.java
@@ -1,49 +1,57 @@
-/*  Copyright (c) 2000-2006 hamcrest.org
- */
 package org.hamcrest.core;
 
-import static org.hamcrest.core.IsEqual.equalTo;
+import org.hamcrest.BaseMatcher;
 import org.hamcrest.Description;
 import org.hamcrest.Matcher;
-import org.hamcrest.Factory;
-import org.hamcrest.BaseMatcher;
+
+import static org.hamcrest.core.IsEqual.equalTo;
 
 
 /**
  * Calculates the logical negation of a matcher.
  */
-public class IsNot<T> extends BaseMatcher<T> {
+public class IsNot<T> extends BaseMatcher<T>  {
     private final Matcher<T> matcher;
 
     public IsNot(Matcher<T> matcher) {
         this.matcher = matcher;
     }
 
+    @Override
     public boolean matches(Object arg) {
         return !matcher.matches(arg);
     }
 
+    @Override
     public void describeTo(Description description) {
         description.appendText("not ").appendDescriptionOf(matcher);
     }
 
+    
     /**
-     * Inverts the rule.
+     * Creates a matcher that wraps an existing matcher, but inverts the logic by which
+     * it will match.
+     * For example:
+     * <pre>assertThat(cheese, is(not(equalTo(smelly))))</pre>
+     * 
+     * @param matcher
+     *     the matcher whose sense should be inverted
      */
-    @Factory
     public static <T> Matcher<T> not(Matcher<T> matcher) {
         return new IsNot<T>(matcher);
     }
 
     /**
-     * This is a shortcut to the frequently used not(equalTo(x)).
-     *
-     * eg. assertThat(cheese, is(not(equalTo(smelly))))
-     * vs  assertThat(cheese, is(not(smelly)))
+     * A shortcut to the frequently used <code>not(equalTo(x))</code>.
+     * For example:
+     * <pre>assertThat(cheese, is(not(smelly)))</pre>
+     * instead of:
+     * <pre>assertThat(cheese, is(not(equalTo(smelly))))</pre>
+     * 
+     * @param value
+     *     the value that any examined object should <b>not</b> equal
      */
-    @Factory
     public static <T> Matcher<T> not(T value) {
         return not(equalTo(value));
     }
-
 }
diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/IsNull.java b/hamcrest-core/src/main/java/org/hamcrest/core/IsNull.java
index 737dcf2..9ebf080 100644
--- a/hamcrest-core/src/main/java/org/hamcrest/core/IsNull.java
+++ b/hamcrest-core/src/main/java/org/hamcrest/core/IsNull.java
@@ -1,55 +1,74 @@
-/*  Copyright (c) 2000-2006 hamcrest.org
- */
 package org.hamcrest.core;
 
-import static org.hamcrest.core.IsNot.not;
+import org.hamcrest.BaseMatcher;
 import org.hamcrest.Description;
 import org.hamcrest.Matcher;
-import org.hamcrest.Factory;
-import org.hamcrest.BaseMatcher;
+
+import static org.hamcrest.core.IsNot.not;
 
 /**
  * Is the value null?
  */
 public class IsNull<T> extends BaseMatcher<T> {
+    @Override
     public boolean matches(Object o) {
         return o == null;
     }
 
+    @Override
     public void describeTo(Description description) {
         description.appendText("null");
     }
 
     /**
-     * Matches if value is null.
+     * Creates a matcher that matches if examined object is <code>null</code>.
+     * For example:
+     * <pre>assertThat(cheese, is(nullValue())</pre>
+     * 
      */
-    @Factory
-    public static <T> Matcher<T> nullValue() {
+    public static Matcher<Object> nullValue() {
+        return new IsNull<Object>();
+    }
+
+    /**
+     * A shortcut to the frequently used <code>not(nullValue())</code>.
+     * For example:
+     * <pre>assertThat(cheese, is(notNullValue()))</pre>
+     * instead of:
+     * <pre>assertThat(cheese, is(not(nullValue())))</pre>
+     * 
+     */
+    public static Matcher<Object> notNullValue() {
+        return not(nullValue());
+    }
+
+    /**
+     * Creates a matcher that matches if examined object is <code>null</code>. Accepts a
+     * single dummy argument to facilitate type inference.
+     * For example:
+     * <pre>assertThat(cheese, is(nullValue(Cheese.class))</pre>
+     * 
+     * @param type
+     *     dummy parameter used to infer the generic type of the returned matcher
+     */
+    public static <T> Matcher<T> nullValue(Class<T> type) {
         return new IsNull<T>();
     }
 
     /**
-     * Matches if value is not null.
+     * A shortcut to the frequently used <code>not(nullValue(X.class)). Accepts a
+     * single dummy argument to facilitate type inference.</code>.
+     * For example:
+     * <pre>assertThat(cheese, is(notNullValue(X.class)))</pre>
+     * instead of:
+     * <pre>assertThat(cheese, is(not(nullValue(X.class))))</pre>
+     * 
+     * @param type
+     *     dummy parameter used to infer the generic type of the returned matcher
+     *  
      */
-    @Factory
-    public static <T> Matcher<T> notNullValue() {
-        return not(IsNull.<T>nullValue());
-    }
-
-    /**
-     * Matches if value is null. With type inference.
-     */
-    @Factory
-    public static <T> Matcher<T> nullValue(@SuppressWarnings("unused") Class<T> type) {
-        return nullValue();
-    }
-
-    /**
-     * Matches if value is not null. With type inference.
-     */
-    @Factory
-    public static <T> Matcher<T> notNullValue(@SuppressWarnings("unused") Class<T> type) {
-        return notNullValue();
+    public static <T> Matcher<T> notNullValue(Class<T> type) {
+        return not(nullValue(type));
     }
 }
 
diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/IsSame.java b/hamcrest-core/src/main/java/org/hamcrest/core/IsSame.java
index b3ad77e..cbc3971 100644
--- a/hamcrest-core/src/main/java/org/hamcrest/core/IsSame.java
+++ b/hamcrest-core/src/main/java/org/hamcrest/core/IsSame.java
@@ -1,11 +1,8 @@
-/*  Copyright (c) 2000-2006 hamcrest.org
- */
 package org.hamcrest.core;
 
+import org.hamcrest.BaseMatcher;
 import org.hamcrest.Description;
 import org.hamcrest.Matcher;
-import org.hamcrest.Factory;
-import org.hamcrest.BaseMatcher;
 
 
 /**
@@ -13,28 +10,42 @@
  */
 public class IsSame<T> extends BaseMatcher<T> {
     private final T object;
-
+    
     public IsSame(T object) {
         this.object = object;
     }
 
+    @Override
     public boolean matches(Object arg) {
         return arg == object;
     }
 
+    @Override
     public void describeTo(Description description) {
-        description.appendText("same(") .appendValue(object) .appendText(")");
+        description.appendText("sameInstance(")
+                .appendValue(object)
+                .appendText(")");
     }
-
+    
     /**
-     * Creates a new instance of IsSame
+     * Creates a matcher that matches only when the examined object is the same instance as
+     * the specified target object.
      *
-     * @param object The predicate evaluates to true only when the argument is
-     *               this object.
+     * @param target
+     *     the target instance against which others should be assessed
      */
-    @Factory
-    public static <T> Matcher<T> sameInstance(T object) {
-        return new IsSame<T>(object);
+    public static <T> Matcher<T> sameInstance(T target) {
+        return new IsSame<T>(target);
     }
-
+    
+    /**
+     * Creates a matcher that matches only when the examined object is the same instance as
+     * the specified target object.
+     *
+     * @param target
+     *     the target instance against which others should be assessed
+     */
+    public static <T> Matcher<T> theInstance(T target) {
+        return new IsSame<T>(target);
+    }
 }
diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/ShortcutCombination.java b/hamcrest-core/src/main/java/org/hamcrest/core/ShortcutCombination.java
new file mode 100644
index 0000000..30b33af
--- /dev/null
+++ b/hamcrest-core/src/main/java/org/hamcrest/core/ShortcutCombination.java
@@ -0,0 +1,33 @@
+package org.hamcrest.core;
+
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+
+abstract class ShortcutCombination<T> extends BaseMatcher<T> {
+
+    private final Iterable<Matcher<? super T>> matchers;
+
+    public ShortcutCombination(Iterable<Matcher<? super T>> matchers) {
+        this.matchers = matchers;
+    }
+    
+    @Override
+    public abstract boolean matches(Object o);
+    
+    @Override
+    public abstract void describeTo(Description description);
+    
+    protected boolean matches(Object o, boolean shortcut) {
+        for (Matcher<? super T> matcher : matchers) {
+            if (matcher.matches(o) == shortcut) {
+                return shortcut;
+            }
+        }
+        return !shortcut;
+    }
+    
+    public void describeTo(Description description, String operator) {
+        description.appendList("(", " " + operator + " ", ")", matchers);
+    }
+}
diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/StringContains.java b/hamcrest-core/src/main/java/org/hamcrest/core/StringContains.java
new file mode 100644
index 0000000..9e0a4ab
--- /dev/null
+++ b/hamcrest-core/src/main/java/org/hamcrest/core/StringContains.java
@@ -0,0 +1,46 @@
+package org.hamcrest.core;
+
+import org.hamcrest.Matcher;
+
+/**
+ * Tests if the argument is a string that contains a substring.
+ */
+public class StringContains extends SubstringMatcher {
+    public StringContains(boolean ignoringCase, String substring) {
+        super("containing", ignoringCase, substring);
+    }
+
+    @Override
+    protected boolean evalSubstringOf(String s) {
+        return converted(s).contains(converted(substring));
+    }
+
+    /**
+     * Creates a matcher that matches if the examined {@link String} contains the specified
+     * {@link String} anywhere.
+     * For example:
+     * <pre>assertThat("myStringOfNote", containsString("ring"))</pre>
+     * 
+     * @param substring
+     *     the substring that the returned matcher will expect to find within any examined string
+     * 
+     */
+    public static Matcher<String> containsString(String substring) {
+        return new StringContains(false, substring);
+    }
+
+    /**
+     * Creates a matcher that matches if the examined {@link String} contains the specified
+     * {@link String} anywhere, ignoring case.
+     * For example:
+     * <pre>assertThat("myStringOfNote", containsString("ring"))</pre>
+     *
+     * @param substring
+     *     the substring that the returned matcher will expect to find within any examined string
+     *
+     */
+    public static Matcher<String> containsStringIgnoringCase(String substring) {
+        return new StringContains(true, substring);
+    }
+
+}
diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/StringEndsWith.java b/hamcrest-core/src/main/java/org/hamcrest/core/StringEndsWith.java
new file mode 100644
index 0000000..6a6d1a0
--- /dev/null
+++ b/hamcrest-core/src/main/java/org/hamcrest/core/StringEndsWith.java
@@ -0,0 +1,42 @@
+package org.hamcrest.core;
+
+import org.hamcrest.Matcher;
+
+/**
+ * Tests if the argument is a string that contains a substring.
+ */
+public class StringEndsWith extends SubstringMatcher {
+    public StringEndsWith(boolean ignoringCase, String substring) { super("ending with", ignoringCase, substring); }
+
+    @Override
+    protected boolean evalSubstringOf(String s) {
+        return converted(s).endsWith(converted(substring));
+    }
+
+    /**
+     * Creates a matcher that matches if the examined {@link String} ends with the specified
+     * {@link String}.
+     * For example:
+     * <pre>assertThat("myStringOfNote", endsWith("Note"))</pre>
+     * 
+     * @param suffix
+     *      the substring that the returned matcher will expect at the end of any examined string
+     */
+    public static Matcher<String> endsWith(String suffix) {
+        return new StringEndsWith(false, suffix);
+    }
+
+    /**
+     * Creates a matcher that matches if the examined {@link String} ends with the specified
+     * {@link String}, ignoring case.
+     * For example:
+     * <pre>assertThat("myStringOfNote", endsWith("Note"))</pre>
+     *
+     * @param suffix
+     *      the substring that the returned matcher will expect at the end of any examined string
+     */
+    public static Matcher<String> endsWithIgnoringCase(String suffix) {
+        return new StringEndsWith(true, suffix);
+    }
+
+}
diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/StringStartsWith.java b/hamcrest-core/src/main/java/org/hamcrest/core/StringStartsWith.java
new file mode 100644
index 0000000..fe7b990
--- /dev/null
+++ b/hamcrest-core/src/main/java/org/hamcrest/core/StringStartsWith.java
@@ -0,0 +1,40 @@
+package org.hamcrest.core;
+
+import org.hamcrest.Matcher;
+
+/**
+ * Tests if the argument is a string that contains a substring.
+ */
+public class StringStartsWith extends SubstringMatcher {
+    public StringStartsWith(boolean ignoringCase, String substring) { super("starting with", ignoringCase, substring); }
+
+    @Override
+    protected boolean evalSubstringOf(String s) { return converted(s).startsWith(converted(substring)); }
+
+    /**
+     * <p>
+     * Creates a matcher that matches if the examined {@link String} starts with the specified
+     * {@link String}.
+     * </p>
+     * For example:
+     * <pre>assertThat("myStringOfNote", startsWith("my"))</pre>
+     * 
+     * @param prefix
+     *      the substring that the returned matcher will expect at the start of any examined string
+     */
+    public static Matcher<String> startsWith(String prefix) { return new StringStartsWith(false, prefix); }
+
+    /**
+     * <p>
+     * Creates a matcher that matches if the examined {@link String} starts with the specified
+     * {@link String}, ignoring case
+     * </p>
+     * For example:
+     * <pre>assertThat("myStringOfNote", startsWith("my"))</pre>
+     *
+     * @param prefix
+     *      the substring that the returned matcher will expect at the start of any examined string
+     */
+    public static Matcher<String> startsWithIgnoringCase(String prefix) { return new StringStartsWith(true, prefix); }
+
+}
diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/SubstringMatcher.java b/hamcrest-core/src/main/java/org/hamcrest/core/SubstringMatcher.java
new file mode 100644
index 0000000..85c6657
--- /dev/null
+++ b/hamcrest-core/src/main/java/org/hamcrest/core/SubstringMatcher.java
@@ -0,0 +1,44 @@
+package org.hamcrest.core;
+
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeMatcher;
+
+public abstract class SubstringMatcher extends TypeSafeMatcher<String> {
+
+    // TODO: Replace String with CharSequence to allow for easy interoperability between
+    //       String, StringBuffer, StringBuilder, CharBuffer, etc (joe).
+
+    private final String relationship;
+    private final boolean ignoringCase;
+    protected final String substring;
+
+    protected SubstringMatcher(String relationship, boolean ignoringCase, String substring) {
+        this.relationship = relationship;
+        this.ignoringCase = ignoringCase;
+        this.substring = substring;
+    }
+
+    @Override
+    public boolean matchesSafely(String item) {
+        return evalSubstringOf(ignoringCase ? item.toLowerCase() :item);
+    }
+    @Override
+    public void describeMismatchSafely(String item, Description mismatchDescription) {
+      mismatchDescription.appendText("was \"").appendText(item).appendText("\"");
+    }
+    
+    @Override
+    public void describeTo(Description description) {
+        description.appendText("a string ")
+                .appendText(relationship)
+                .appendText(" ")
+                .appendValue(substring);
+        if (ignoringCase) {
+            description.appendText(" ignoring case");
+        }
+    }
+
+    protected String converted(String arg) { return ignoringCase ? arg.toLowerCase() : arg; }
+    protected abstract boolean evalSubstringOf(String string);
+
+}
diff --git a/hamcrest-core/src/main/java/org/hamcrest/internal/ArrayIterator.java b/hamcrest-core/src/main/java/org/hamcrest/internal/ArrayIterator.java
index 093cdba..03e4c43 100644
--- a/hamcrest-core/src/main/java/org/hamcrest/internal/ArrayIterator.java
+++ b/hamcrest-core/src/main/java/org/hamcrest/internal/ArrayIterator.java
@@ -4,25 +4,28 @@
 import java.util.Iterator;
 
 public class ArrayIterator implements Iterator<Object> {
-	private final Object array;
-	private int currentIndex = 0;
-	
-	public ArrayIterator(Object array) {
-		if (!array.getClass().isArray()) {
-			throw new IllegalArgumentException("not an array");
-		}
-		this.array = array;
-	}
-	
-	public boolean hasNext() {
-		return currentIndex < Array.getLength(array);
-	}
+    private final Object array;
+    private int currentIndex = 0;
+    
+    public ArrayIterator(Object array) {
+        if (!array.getClass().isArray()) {
+            throw new IllegalArgumentException("not an array");
+        }
+        this.array = array;
+    }
+    
+    @Override
+    public boolean hasNext() {
+        return currentIndex < Array.getLength(array);
+    }
 
-	public Object next() {
-		return Array.get(array, currentIndex++);
-	}
-	
-	public void remove() {
-		throw new UnsupportedOperationException("cannot remove items from an array");
-	}
+    @Override
+    public Object next() {
+        return Array.get(array, currentIndex++);
+    }
+    
+    @Override
+    public void remove() {
+        throw new UnsupportedOperationException("cannot remove items from an array");
+    }
 }
diff --git a/hamcrest-core/src/main/java/org/hamcrest/internal/NullSafety.java b/hamcrest-core/src/main/java/org/hamcrest/internal/NullSafety.java
new file mode 100644
index 0000000..9310abf
--- /dev/null
+++ b/hamcrest-core/src/main/java/org/hamcrest/internal/NullSafety.java
@@ -0,0 +1,18 @@
+package org.hamcrest.internal;
+
+import org.hamcrest.Matcher;
+import org.hamcrest.core.IsNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class NullSafety {
+    @SuppressWarnings("unchecked")
+    public static <E> List<Matcher<? super E>> nullSafe(Matcher<? super E>[] itemMatchers) {
+        final List<Matcher<? super E>> matchers = new ArrayList<Matcher<? super E>>(itemMatchers.length);
+        for (final Matcher<? super E> itemMatcher : itemMatchers) {
+            matchers.add((Matcher<? super E>) (itemMatcher == null ? IsNull.nullValue() : itemMatcher));
+        }
+        return matchers;
+    }
+}
diff --git a/hamcrest-core/src/main/java/org/hamcrest/internal/ReflectiveTypeFinder.java b/hamcrest-core/src/main/java/org/hamcrest/internal/ReflectiveTypeFinder.java
new file mode 100644
index 0000000..ada74d6
--- /dev/null
+++ b/hamcrest-core/src/main/java/org/hamcrest/internal/ReflectiveTypeFinder.java
@@ -0,0 +1,70 @@
+/**
+ * The TypeSafe classes, and their descendants, need a mechanism to find out what type has been used as a parameter 
+ * for the concrete matcher. Unfortunately, this type is lost during type erasure so we need to use reflection 
+ * to get it back, by picking out the type of a known parameter to a known method. 
+ * The catch is that, with bridging methods, this type is only visible in the class that actually implements 
+ * the expected method, so the ReflectiveTypeFinder needs to be applied to that class or a subtype.
+ * 
+ * For example, the abstract <code>TypeSafeDiagnosingMatcher&lt;T&gt;</code> defines an abstract method
+ * <pre>protected abstract boolean matchesSafely(T item, Description mismatchDescription);</pre>
+ * By default it uses <code>new ReflectiveTypeFinder("matchesSafely", 2, 0); </code> to find the
+ * parameterised type. If we create a <code>TypeSafeDiagnosingMatcher&lt;String&gt;</code>, the type
+ * finder will return <code>String.class</code>.
+ * 
+ * A <code>FeatureMatcher</code> is an abstract subclass of <code>TypeSafeDiagnosingMatcher</code>. 
+ * Although it has a templated implementation of <code>matchesSafely(&lt;T&gt;, Description);</code>, the
+ * actual run-time signature of this is <code>matchesSafely(Object, Description);</code>. Instead,
+ * we must find the type by reflecting on the concrete implementation of 
+ * <pre>protected abstract U featureValueOf(T actual);</pre>
+ * a method which is declared in <code>FeatureMatcher</code>.
+ * 
+ * In short, use this to extract a type from a method in the leaf class of a templated class hierarchy. 
+ *  
+ * @author Steve Freeman
+ * @author Nat Pryce
+ */
+package org.hamcrest.internal;
+
+import java.lang.reflect.Method;
+
+public class ReflectiveTypeFinder {
+  private final String methodName;
+  private final int expectedNumberOfParameters;
+  private final int typedParameter;
+
+  public ReflectiveTypeFinder(String methodName, int expectedNumberOfParameters, int typedParameter) {
+    this.methodName = methodName;
+    this.expectedNumberOfParameters = expectedNumberOfParameters;
+    this.typedParameter = typedParameter;
+  }
+  
+  public Class<?> findExpectedType(Class<?> fromClass) {
+    for (Class<?> c = fromClass; c != Object.class; c = c.getSuperclass()) {
+        for (Method method : c.getDeclaredMethods()) {
+            if (canObtainExpectedTypeFrom(method)) {
+                return expectedTypeFrom(method);
+            }
+        }
+    }
+    throw new Error("Cannot determine correct type for " + methodName + "() method.");
+  }
+
+  /**
+   * @param method The method to examine.
+   * @return true if this method references the relevant type
+   */
+  protected boolean canObtainExpectedTypeFrom(Method method) {
+      return method.getName().equals(methodName)
+              && method.getParameterTypes().length == expectedNumberOfParameters
+              && !method.isSynthetic();
+  }
+
+
+  /**
+   * @param method The method from which to extract
+   * @return The type we're looking for
+   */
+  protected Class<?> expectedTypeFrom(Method method) {
+      return method.getParameterTypes()[typedParameter];
+  }
+}
diff --git a/hamcrest-core/src/main/java/org/hamcrest/internal/SelfDescribingValue.java b/hamcrest-core/src/main/java/org/hamcrest/internal/SelfDescribingValue.java
index 0634527..6537018 100644
--- a/hamcrest-core/src/main/java/org/hamcrest/internal/SelfDescribingValue.java
+++ b/hamcrest-core/src/main/java/org/hamcrest/internal/SelfDescribingValue.java
@@ -10,6 +10,7 @@
         this.value = value;
     }
 
+    @Override
     public void describeTo(Description description) {
         description.appendValue(value);
     }
diff --git a/hamcrest-core/src/main/java/org/hamcrest/internal/SelfDescribingValueIterator.java b/hamcrest-core/src/main/java/org/hamcrest/internal/SelfDescribingValueIterator.java
index 58bedf6..bc8f8f4 100644
--- a/hamcrest-core/src/main/java/org/hamcrest/internal/SelfDescribingValueIterator.java
+++ b/hamcrest-core/src/main/java/org/hamcrest/internal/SelfDescribingValueIterator.java
@@ -1,9 +1,9 @@
 package org.hamcrest.internal;
 
-import java.util.Iterator;
-
 import org.hamcrest.SelfDescribing;
 
+import java.util.Iterator;
+
 public class SelfDescribingValueIterator<T> implements Iterator<SelfDescribing> {
     private Iterator<T> values;
     
@@ -11,14 +11,17 @@
         this.values = values;
     }
     
+    @Override
     public boolean hasNext() {
         return values.hasNext();
     }
 
+    @Override
     public SelfDescribing next() {
         return new SelfDescribingValue<T>(values.next());
     }
 
+    @Override
     public void remove() {
         values.remove();
     }
diff --git a/hamcrest-core/src/main/java/org/hamcrest/internal/package.html b/hamcrest-core/src/main/java/org/hamcrest/internal/package.html
deleted file mode 100644
index 1c9bf9d..0000000
--- a/hamcrest-core/src/main/java/org/hamcrest/internal/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body>
-    {@hide}
-</body>
-</html>
diff --git a/hamcrest-core/src/main/java/org/hamcrest/package.html b/hamcrest-core/src/main/java/org/hamcrest/package.html
deleted file mode 100644
index 143c704..0000000
--- a/hamcrest-core/src/main/java/org/hamcrest/package.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<html>
-<head>
-</head>
-<body>
-  <p>The stable API defining Matcher and its associated interfaces and classes.
-  Hamcrest sub-projects define their convenience classes in the org.hamcrest package.
-  </p>
-</body>
-</html>
diff --git a/hamcrest-core/src/test/java/org/hamcrest/AbstractMatcherTest.java b/hamcrest-core/src/test/java/org/hamcrest/AbstractMatcherTest.java
new file mode 100644
index 0000000..22f823b
--- /dev/null
+++ b/hamcrest-core/src/test/java/org/hamcrest/AbstractMatcherTest.java
@@ -0,0 +1,77 @@
+package org.hamcrest;
+
+import junit.framework.TestCase;
+import org.junit.Assert;
+
+public abstract class AbstractMatcherTest extends TestCase {
+
+  /**
+   * Create an instance of the Matcher so some generic safety-net tests can be run on it.
+   */
+  protected abstract Matcher<?> createMatcher();
+  
+  public static <T> void assertMatches(Matcher<T> matcher, T arg) {
+      assertMatches("Expected match, but mismatched", matcher, arg);
+  }
+
+  public static <T> void assertMatches(String message, Matcher<T> matcher, T arg) {
+    if (!matcher.matches(arg)) {
+      Assert.fail(message + " because: '" + mismatchDescription(matcher, arg) + "'");
+    }
+  }
+
+  public static <T> void assertDoesNotMatch(Matcher<? super T> c, T arg) {
+      assertDoesNotMatch("Unexpected match", c, arg);
+  }
+
+  public static <T> void assertDoesNotMatch(String message, Matcher<? super T> c, T arg) {
+    Assert.assertFalse(message, c.matches(arg));
+  }
+
+  public static void assertDescription(String expected, Matcher<?> matcher) {
+    Description description = new StringDescription();
+    description.appendDescriptionOf(matcher);
+    Assert.assertEquals("Expected description", expected, description.toString().trim());
+  }
+
+  public static <T> void assertMismatchDescription(String expected, Matcher<? super T> matcher, T arg) {
+    Assert.assertFalse("Precondition: Matcher should not match item.", matcher.matches(arg));
+    Assert.assertEquals("Expected mismatch description", expected, mismatchDescription(matcher, arg));
+  }
+  
+  public static void assertNullSafe(Matcher<?> matcher) {
+      try {
+          matcher.matches(null);
+      }
+      catch (Exception e) {
+          Assert.fail("Matcher was not null safe");
+      }
+  }
+
+  public static void assertUnknownTypeSafe(Matcher<?> matcher) {
+      try {
+          matcher.matches(new UnknownType());
+      }
+      catch (Exception e) {
+          Assert.fail("Matcher was not unknown type safe");
+      }
+  }
+
+  public static <T> String mismatchDescription(Matcher<? super T> matcher, T arg) {
+    Description description = new StringDescription();
+    matcher.describeMismatch(arg, description);
+    return description.toString().trim();
+  }
+
+  public void testIsNullSafe() {
+    assertNullSafe(createMatcher());
+  }
+
+  public void testCopesWithUnknownTypes() {
+    assertUnknownTypeSafe(createMatcher());
+  }
+
+  public static class UnknownType {
+  }
+
+}
diff --git a/hamcrest-core/src/test/java/org/hamcrest/BaseDescriptionTest.java b/hamcrest-core/src/test/java/org/hamcrest/BaseDescriptionTest.java
new file mode 100644
index 0000000..8b70725
--- /dev/null
+++ b/hamcrest-core/src/test/java/org/hamcrest/BaseDescriptionTest.java
@@ -0,0 +1,78 @@
+package org.hamcrest;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public final class BaseDescriptionTest {
+
+    private final StringBuilder result = new StringBuilder();
+
+    private final BaseDescription baseDescription = new BaseDescription() {
+        @Override protected void append(char c) {
+            result.append(c);
+        }
+    };
+
+    @Test public void 
+    describesAppendedNullValue() {
+        baseDescription.appendValue(null);
+        assertEquals("null", result.toString());
+    }
+
+    @Test public void 
+    quotesAppendedStringValue() {
+        baseDescription.appendValue("foo");
+        assertEquals("\"foo\"", result.toString());
+    }
+
+    @Test public void 
+    quotesAppendedCharacterValue() {
+        baseDescription.appendValue('f');
+        assertEquals("\"f\"", result.toString());
+    }
+
+    @Test public void 
+    bracketsAppendedShortValue() {
+        baseDescription.appendValue(Short.valueOf("2"));
+        assertEquals("<2s>", result.toString());
+    }
+
+    @Test public void 
+    bracketsAppendedLongValue() {
+        baseDescription.appendValue(Long.valueOf("2"));
+        assertEquals("<2L>", result.toString());
+    }
+
+    @Test public void 
+    bracketsAppendedFloatValue() {
+        baseDescription.appendValue(Float.valueOf("1.2"));
+        assertEquals("<1.2F>", result.toString());
+    }
+
+    @Test public void 
+    describesAppendedArrayValue() {
+        baseDescription.appendValue(new String[] {"2", "3"});
+        assertEquals("[\"2\", \"3\"]", result.toString());
+    }
+
+    @Test public void 
+    bracketsAppendedObjectValue() {
+        final Object value = new Object();
+        baseDescription.appendValue(value);
+        assertEquals("<" + value.toString() + ">", result.toString());
+    }
+    
+    @Test public void 
+    safelyDescribesAppendedValueOfObjectWhoseToStringThrowsAnException() {
+        final Object value = new Object() {
+            @Override public String toString() {
+                throw new UnsupportedOperationException();
+            }
+        };
+        
+        final String expected = value.getClass().getName() + "@" + Integer.toHexString(value.hashCode());
+        baseDescription.appendValue(value);
+        assertEquals("<" + expected + ">", result.toString());
+    }
+}
diff --git a/hamcrest-core/src/test/java/org/hamcrest/BaseMatcherTest.java b/hamcrest-core/src/test/java/org/hamcrest/BaseMatcherTest.java
new file mode 100644
index 0000000..e663f04
--- /dev/null
+++ b/hamcrest-core/src/test/java/org/hamcrest/BaseMatcherTest.java
@@ -0,0 +1,26 @@
+package org.hamcrest;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public final class BaseMatcherTest {
+
+    @Test
+    public void
+    describesItselfWithToStringMethod() {
+        Matcher<Object> someMatcher = new BaseMatcher<Object>() {
+            @Override
+            public boolean matches(Object item) {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public void describeTo(Description description) {
+                description.appendText("SOME DESCRIPTION");
+            }
+        };
+
+        assertEquals("SOME DESCRIPTION", someMatcher.toString());
+    }
+}
diff --git a/hamcrest-core/src/test/java/org/hamcrest/CustomMatcherTest.java b/hamcrest-core/src/test/java/org/hamcrest/CustomMatcherTest.java
new file mode 100644
index 0000000..08649f7
--- /dev/null
+++ b/hamcrest-core/src/test/java/org/hamcrest/CustomMatcherTest.java
@@ -0,0 +1,20 @@
+package org.hamcrest;
+
+import org.junit.Test;
+
+import static org.hamcrest.AbstractMatcherTest.assertDescription;
+
+public final class CustomMatcherTest {
+
+    @Test public void
+    usesStaticDescription() throws Exception {
+        Matcher<String> matcher = new CustomMatcher<String>("I match strings") {
+            @Override
+            public boolean matches(Object item) {
+                return (item instanceof String);
+            }
+        };
+
+        assertDescription("I match strings", matcher);
+    }
+}
diff --git a/hamcrest-core/src/test/java/org/hamcrest/CustomTypeSafeMatcherTest.java b/hamcrest-core/src/test/java/org/hamcrest/CustomTypeSafeMatcherTest.java
new file mode 100644
index 0000000..2c86712
--- /dev/null
+++ b/hamcrest-core/src/test/java/org/hamcrest/CustomTypeSafeMatcherTest.java
@@ -0,0 +1,41 @@
+package org.hamcrest;
+
+import org.junit.Test;
+
+import static org.hamcrest.AbstractMatcherTest.*;
+
+public final class CustomTypeSafeMatcherTest {
+    private static final String STATIC_DESCRIPTION = "I match non empty strings";
+
+    private final Matcher<String> customMatcher = new CustomTypeSafeMatcher<String>(STATIC_DESCRIPTION) {
+        @Override
+        public boolean matchesSafely(String item) {
+            return false;
+        }
+
+        @Override
+        public void describeMismatchSafely(String item, Description mismatchDescription) {
+            mismatchDescription.appendText("an " + item);
+        }
+    };
+
+    @Test public void
+    usesStaticDescription() throws Exception {
+        assertDescription(STATIC_DESCRIPTION, customMatcher);
+    }
+
+    @Test public void
+    reportsMismatch() {
+        assertMismatchDescription("an item", customMatcher, "item");
+    }
+
+    @Test public void
+    isNullSafe() {
+        assertNullSafe(customMatcher);
+    }
+    
+    @Test public void
+    copesWithUnknownTypes() {
+        assertUnknownTypeSafe(customMatcher);
+    }
+}
diff --git a/hamcrest-core/src/test/java/org/hamcrest/FeatureMatcherTest.java b/hamcrest-core/src/test/java/org/hamcrest/FeatureMatcherTest.java
new file mode 100644
index 0000000..f0cbdd5
--- /dev/null
+++ b/hamcrest-core/src/test/java/org/hamcrest/FeatureMatcherTest.java
@@ -0,0 +1,68 @@
+package org.hamcrest;
+
+import org.hamcrest.core.IsEqual;
+import org.junit.Test;
+
+import static org.hamcrest.AbstractMatcherTest.*;
+import static org.junit.Assert.assertEquals;
+
+public final class FeatureMatcherTest {
+    private final FeatureMatcher<Thingy, String> resultMatcher = resultMatcher();
+
+    @Test public void
+    matchesPartOfAnObject() {
+        assertMatches("feature", resultMatcher, new Thingy("bar"));
+        assertDescription("Thingy with result \"bar\"", resultMatcher);
+    }
+
+    @Test public void
+    mismatchesPartOfAnObject() {
+        assertMismatchDescription("result mismatch-description", resultMatcher, new Thingy("foo"));
+    }
+
+    @Test public void
+    doesNotThrowNullPointerException() {
+        assertMismatchDescription("was null", resultMatcher, null);
+    }
+
+    @Test public void
+    doesNotThrowClassCastException() {
+        resultMatcher.matches(new ShouldNotMatch());
+        StringDescription mismatchDescription = new StringDescription(); 
+        resultMatcher.describeMismatch(new ShouldNotMatch(), mismatchDescription);
+        assertEquals("was <ShouldNotMatch>", mismatchDescription.toString());
+    }
+
+    public static class Match extends IsEqual<String> {
+        public Match(String equalArg) { super(equalArg); }
+        @Override public void describeMismatch(Object item, Description description) {
+            description.appendText("mismatch-description");
+        }
+    }
+
+    public static class Thingy {
+        private final String result;
+
+        public Thingy(String result) {
+            this.result = result;
+        }
+
+        public String getResult() {
+            return result;
+        }
+    }
+
+    public static class ShouldNotMatch {
+        @Override public String toString() { return "ShouldNotMatch"; }
+    } 
+
+    private static FeatureMatcher<Thingy, String> resultMatcher() {
+        return new FeatureMatcher<Thingy, String>(new Match("bar"), "Thingy with result", "result") {
+            @Override
+            public String featureValueOf(Thingy actual) {
+                return actual.getResult();
+            }
+        };
+    }
+
+}
diff --git a/hamcrest-core/src/test/java/org/hamcrest/MatcherAssertTest.java b/hamcrest-core/src/test/java/org/hamcrest/MatcherAssertTest.java
new file mode 100644
index 0000000..b57c4d7
--- /dev/null
+++ b/hamcrest-core/src/test/java/org/hamcrest/MatcherAssertTest.java
@@ -0,0 +1,96 @@
+package org.hamcrest;
+
+import org.junit.Test;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.*;
+
+public final class MatcherAssertTest {
+
+    @Test public void
+    includesDescriptionOfTestedValueInErrorMessage() {
+        String expected = "expected";
+        String actual = "actual";
+
+        String expectedMessage = "identifier\nExpected: \"expected\"\n     but: was \"actual\"";
+
+        try {
+            assertThat("identifier", actual, equalTo(expected));
+        }
+        catch (AssertionError e) {
+            assertTrue(e.getMessage().startsWith(expectedMessage));
+            return;
+        }
+
+        fail("should have failed");
+    }
+
+    @Test public void
+    descriptionCanBeElided() {
+        String expected = "expected";
+        String actual = "actual";
+
+        String expectedMessage = "\nExpected: \"expected\"\n     but: was \"actual\"";
+
+        try {
+            assertThat(actual, equalTo(expected));
+        }
+        catch (AssertionError e) {
+            assertTrue(e.getMessage().startsWith(expectedMessage));
+            return;
+        }
+
+        fail("should have failed");
+    }
+
+    @Test public void
+    canTestBooleanDirectly() {
+        assertThat("success reason message", true);
+
+        try {
+            assertThat("failing reason message", false);
+        }
+        catch (AssertionError e) {
+            assertEquals("failing reason message", e.getMessage());
+            return;
+        }
+
+        fail("should have failed");
+    }
+
+    @Test public void
+    includesMismatchDescription() {
+        Matcher<String> matcherWithCustomMismatchDescription = new BaseMatcher<String>() {
+            @Override
+            public boolean matches(Object item) {
+                return false;
+            }
+
+            @Override
+            public void describeTo(Description description) {
+                description.appendText("Something cool");
+            }
+
+            @Override
+            public void describeMismatch(Object item, Description mismatchDescription) {
+                mismatchDescription.appendText("Not cool");
+            }
+        };
+
+        String expectedMessage = "\nExpected: Something cool\n     but: Not cool";
+
+        try {
+            assertThat("Value", matcherWithCustomMismatchDescription);
+            fail("should have failed");
+        }
+        catch (AssertionError e) {
+            assertEquals(expectedMessage, e.getMessage());
+        }
+    }
+
+    @Test public void
+    canAssertSubtypes() {
+        assertThat(1, equalTo((Number) 1));
+    }
+}
diff --git a/hamcrest-core/src/test/java/org/hamcrest/NullDescriptionTest.java b/hamcrest-core/src/test/java/org/hamcrest/NullDescriptionTest.java
new file mode 100644
index 0000000..cccece0
--- /dev/null
+++ b/hamcrest-core/src/test/java/org/hamcrest/NullDescriptionTest.java
@@ -0,0 +1,18 @@
+package org.hamcrest;
+
+import org.hamcrest.Description.NullDescription;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public final class NullDescriptionTest {
+
+    private final NullDescription nullDescription = new Description.NullDescription();
+
+    @Test public void
+    isUnchangedByAppendedText() {
+        nullDescription.appendText("myText");
+        assertEquals("", nullDescription.toString());
+    }
+
+}
diff --git a/hamcrest-core/src/test/java/org/hamcrest/TypeSafeMatcherTest.java b/hamcrest-core/src/test/java/org/hamcrest/TypeSafeMatcherTest.java
new file mode 100644
index 0000000..e23bab8
--- /dev/null
+++ b/hamcrest-core/src/test/java/org/hamcrest/TypeSafeMatcherTest.java
@@ -0,0 +1,40 @@
+package org.hamcrest;
+
+import org.junit.Test;
+
+import static org.hamcrest.AbstractMatcherTest.assertMismatchDescription;
+import static org.junit.Assert.assertFalse;
+
+public final class TypeSafeMatcherTest {
+    private final Matcher<String> matcher = new TypeSafeMatcherSubclass();
+
+    public static class TypeSafeMatcherSubclass extends TypeSafeMatcher<String> {
+        @Override
+        public boolean matchesSafely(String item) {
+            return false;
+        }
+
+        @Override
+        public void describeMismatchSafely(String item, Description mismatchDescription) {
+          mismatchDescription.appendText("The mismatch");
+        }
+
+        @Override
+        public void describeTo(Description description) {
+        }
+    }
+
+    @Test public void
+    canDetermineMatcherTypeFromProtectedMatchesSafelyMethod() {
+        assertFalse(matcher.matches(null));
+        assertFalse(matcher.matches(10));
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    @Test public void
+    describesMismatches() {
+      assertMismatchDescription("was null", matcher, null);
+      assertMismatchDescription("was a java.lang.Integer (<3>)", (Matcher)matcher, 3);
+      assertMismatchDescription("The mismatch", matcher, "a string");
+    }
+}
diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/AllOfTest.java b/hamcrest-core/src/test/java/org/hamcrest/core/AllOfTest.java
new file mode 100644
index 0000000..4815002
--- /dev/null
+++ b/hamcrest-core/src/test/java/org/hamcrest/core/AllOfTest.java
@@ -0,0 +1,63 @@
+package org.hamcrest.core;
+
+import org.hamcrest.Matcher;
+import org.junit.Test;
+
+import static org.hamcrest.AbstractMatcherTest.*;
+import static org.hamcrest.core.AllOf.allOf;
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.hamcrest.core.StringEndsWith.endsWith;
+import static org.hamcrest.core.StringStartsWith.startsWith;
+
+public final class AllOfTest {
+
+    @Test public void
+    copesWithNullsAndUnknownTypes() {
+        Matcher<String> matcher = allOf(equalTo("irrelevant"), startsWith("irr"));
+        
+        assertNullSafe(matcher);
+        assertUnknownTypeSafe(matcher);
+    }
+    
+    @Test public void
+    evaluatesToTheTheLogicalConjunctionOfTwoOtherMatchers() {
+        Matcher<String> matcher = allOf(startsWith("goo"), endsWith("ood"));
+        
+        assertMatches("didn't pass both sub-matchers", matcher, "good");
+        assertDoesNotMatch("didn't fail first sub-matcher", matcher, "mood");
+        assertDoesNotMatch("didn't fail second sub-matcher", matcher, "goon");
+        assertDoesNotMatch("didn't fail both sub-matchers", matcher, "fred");
+    }
+
+    @Test public void
+    evaluatesToTheTheLogicalConjunctionOfManyOtherMatchers() {
+        Matcher<String> matcher = allOf(startsWith("g"), startsWith("go"), endsWith("d"), startsWith("go"), startsWith("goo"));
+        
+        assertMatches("didn't pass all sub-matchers", matcher, "good");
+        assertDoesNotMatch("didn't fail middle sub-matcher", matcher, "goon");
+    }
+    
+    @Test public void
+    supportsMixedTypes() {
+        final Matcher<SampleSubClass> matcher = allOf(
+                equalTo(new SampleBaseClass("bad")),
+                is(notNullValue()),
+                equalTo(new SampleBaseClass("good")),
+                equalTo(new SampleSubClass("ugly")));
+        
+        assertDoesNotMatch("didn't fail last sub-matcher", matcher, new SampleSubClass("good"));
+    }
+    
+    @Test public void
+    hasAReadableDescription() {
+        assertDescription("(\"good\" and \"bad\" and \"ugly\")",
+                allOf(equalTo("good"), equalTo("bad"), equalTo("ugly")));
+    }
+
+    @Test public void
+    hasAMismatchDescriptionDescribingTheFirstFailingMatch() {
+        assertMismatchDescription("\"good\" was \"bad\"", allOf(equalTo("bad"), equalTo("good")), "bad");
+    }
+}
diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/AnyOfTest.java b/hamcrest-core/src/test/java/org/hamcrest/core/AnyOfTest.java
new file mode 100644
index 0000000..11c053c
--- /dev/null
+++ b/hamcrest-core/src/test/java/org/hamcrest/core/AnyOfTest.java
@@ -0,0 +1,56 @@
+package org.hamcrest.core;
+
+import org.hamcrest.Matcher;
+import org.junit.Test;
+
+import static org.hamcrest.AbstractMatcherTest.*;
+import static org.hamcrest.core.AnyOf.anyOf;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.hamcrest.core.StringEndsWith.endsWith;
+import static org.hamcrest.core.StringStartsWith.startsWith;
+
+public final class AnyOfTest {
+
+    @Test public void
+    copesWithNullsAndUnknownTypes() {
+        Matcher<String> matcher = anyOf(equalTo("irrelevant"), startsWith("irr"));
+        
+        assertNullSafe(matcher);
+        assertUnknownTypeSafe(matcher);
+    }
+
+    @Test public void
+    evaluatesToTheTheLogicalDisjunctionOfTwoOtherMatchers() {
+        Matcher<String> matcher = anyOf(startsWith("goo"), endsWith("ood"));
+        
+        assertMatches("didn't pass both sub-matchers", matcher, "good");
+        assertMatches("didn't pass second sub-matcher", matcher, "mood");
+        assertMatches("didn't pass first sub-matcher", matcher, "goon");
+        assertDoesNotMatch("didn't fail both sub-matchers", matcher, "flan");
+    }
+
+    @Test public void
+    evaluatesToTheTheLogicalDisjunctionOfManyOtherMatchers() {
+        Matcher<String> matcher = anyOf(startsWith("g"), startsWith("go"), endsWith("d"), startsWith("go"), startsWith("goo"));
+        
+        assertMatches("didn't pass middle sub-matcher", matcher, "vlad");
+        assertDoesNotMatch("didn't fail all sub-matchers", matcher, "flan");
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test public void
+    supportsMixedTypes() {
+        final Matcher<SampleSubClass> matcher = anyOf(
+                equalTo(new SampleBaseClass("bad")),
+                equalTo(new SampleBaseClass("good")),
+                equalTo(new SampleSubClass("ugly")));
+        
+        assertMatches("didn't pass middle sub-matcher", matcher, new SampleSubClass("good"));
+    }
+
+    @Test public void
+    hasAReadableDescription() {
+        assertDescription("(\"good\" or \"bad\" or \"ugly\")",
+                anyOf(equalTo("good"), equalTo("bad"), equalTo("ugly")));
+    }
+}
diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/CombinableTest.java b/hamcrest-core/src/test/java/org/hamcrest/core/CombinableTest.java
new file mode 100644
index 0000000..e89c493
--- /dev/null
+++ b/hamcrest-core/src/test/java/org/hamcrest/core/CombinableTest.java
@@ -0,0 +1,68 @@
+package org.hamcrest.core;
+
+import org.hamcrest.Matcher;
+import org.junit.Test;
+
+import static org.hamcrest.AbstractMatcherTest.*;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.hamcrest.core.IsNot.not;
+import static org.hamcrest.core.IsNull.notNullValue;
+
+public final class CombinableTest {
+    private static final CombinableMatcher<Integer> EITHER_3_OR_4 = CombinableMatcher.<Integer>either(equalTo(3)).or(equalTo(4));
+    private static final CombinableMatcher<Integer> NOT_3_AND_NOT_4 = CombinableMatcher.<Integer>both(not(equalTo(3))).and(not(equalTo(4)));
+
+    @Test public void
+    copesWithNullsAndUnknownTypes() {
+        assertNullSafe(EITHER_3_OR_4);
+        assertNullSafe(NOT_3_AND_NOT_4);
+        assertUnknownTypeSafe(EITHER_3_OR_4);
+        assertUnknownTypeSafe(NOT_3_AND_NOT_4);
+    }
+
+    @Test public void
+    bothAcceptsAndRejects() {
+        assertMatches("both didn't pass", NOT_3_AND_NOT_4, 2);
+        assertDoesNotMatch("both didn't fail", NOT_3_AND_NOT_4, 3);
+    }
+
+    @Test public void
+    acceptsAndRejectsThreeAnds() {
+        CombinableMatcher<? super Integer> tripleAnd = NOT_3_AND_NOT_4.and(equalTo(2));
+        
+        assertMatches("tripleAnd didn't pass", tripleAnd, 2);
+        assertDoesNotMatch("tripleAnd didn't fail", tripleAnd, 3);
+    }
+
+    @Test public void
+    bothDescribesItself() {
+        assertDescription("(not <3> and not <4>)", NOT_3_AND_NOT_4);
+        assertMismatchDescription("not <3> was <3>", NOT_3_AND_NOT_4, 3);
+    }
+
+    @Test public void
+    eitherAcceptsAndRejects() {
+        assertMatches("either didn't pass", EITHER_3_OR_4, 3);
+        assertDoesNotMatch("either didn't fail", EITHER_3_OR_4, 6);
+    }
+
+    @Test public void
+    acceptsAndRejectsThreeOrs() {
+        final CombinableMatcher<Integer> tripleOr = EITHER_3_OR_4.or(equalTo(11));
+        
+        assertMatches("tripleOr didn't pass", tripleOr, 11);
+        assertDoesNotMatch("tripleOr didn't fail", tripleOr, 9);
+    }
+
+    @Test public void
+    eitherDescribesItself() {
+        assertDescription("(<3> or <4>)", EITHER_3_OR_4);
+        assertMismatchDescription("was <6>", EITHER_3_OR_4, 6);
+    }
+
+    @Test public void
+    picksUpTypeFromLeftHandSideOfExpression() {
+        @SuppressWarnings("unused")
+        Matcher<String> matcher = CombinableMatcher.both(equalTo("yellow")).and(notNullValue(String.class));
+    }
+}
diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/DescribedAsTest.java b/hamcrest-core/src/test/java/org/hamcrest/core/DescribedAsTest.java
new file mode 100644
index 0000000..5c76af9
--- /dev/null
+++ b/hamcrest-core/src/test/java/org/hamcrest/core/DescribedAsTest.java
@@ -0,0 +1,49 @@
+package org.hamcrest.core;
+
+import org.hamcrest.Matcher;
+import org.junit.Test;
+
+import static org.hamcrest.AbstractMatcherTest.*;
+import static org.hamcrest.core.DescribedAs.describedAs;
+import static org.hamcrest.core.IsAnything.anything;
+import static org.hamcrest.core.IsEqual.equalTo;
+
+public final class DescribedAsTest {
+
+    @Test public void
+    copesWithNullsAndUnknownTypes() {
+        Matcher<Object> matcher = describedAs("irrelevant", anything());
+
+        assertNullSafe(matcher);
+        assertUnknownTypeSafe(matcher);
+    }
+
+    @Test public void
+    overridesDescriptionOfOtherMatcherWithThatPassedToConstructor() {
+        Matcher<?> matcher = describedAs("my description", anything());
+
+        assertDescription("my description", matcher);
+    }
+
+    @Test public void
+    appendsValuesToDescription() {
+        Matcher<?> matcher = describedAs("value 1 = %0, value 2 = %1", anything(), 33, 97);
+
+        assertDescription("value 1 = <33>, value 2 = <97>", matcher);
+    }
+
+    @Test public void
+    celegatesMatchingToAnotherMatcher() {
+        Matcher<String> matcher = describedAs("irrelevant", equalTo("hi"));
+
+        assertMatches(matcher, "hi");
+        assertDoesNotMatch("matched", matcher, "oi");
+    }
+
+    @Test public void
+    delegatesMismatchDescriptionToAnotherMatcher() {
+        Matcher<Integer> matcher = describedAs("irrelevant", equalTo(2));
+
+        assertMismatchDescription("was <1>", matcher, 1);
+    }
+}
diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/EveryTest.java b/hamcrest-core/src/test/java/org/hamcrest/core/EveryTest.java
new file mode 100644
index 0000000..e45e881
--- /dev/null
+++ b/hamcrest-core/src/test/java/org/hamcrest/core/EveryTest.java
@@ -0,0 +1,43 @@
+package org.hamcrest.core;
+
+import org.hamcrest.Matcher;
+import org.junit.Test;
+
+import java.util.ArrayList;
+
+import static java.util.Arrays.asList;
+import static org.hamcrest.AbstractMatcherTest.*;
+import static org.hamcrest.core.StringContains.containsString;
+
+public final class EveryTest {
+
+    private final Matcher<Iterable<? extends String>> matcher = Every.everyItem(containsString("a"));
+
+    @Test public void
+    copesWithNullsAndUnknownTypes() {
+        assertNullSafe(matcher);
+        assertUnknownTypeSafe(matcher);
+    }
+
+    @Test public void
+    matchesOnlyWhenEveryItemMatches() {
+        assertMatches(matcher, asList("AaA", "BaB", "CaC"));
+        assertDoesNotMatch(matcher, asList("AaA", "BXB", "CaC"));
+    }
+
+    @Test public void
+    matchesEmptyLists() {
+        assertMatches("didn't match empty list", matcher, new ArrayList<String>());
+    }
+
+    @Test public void
+    describesItself() {
+        assertDescription("every item is a string containing \"a\"", matcher);
+    }
+
+    @Test public void
+    describesAMismatch() {
+        assertMismatchDescription("an item was \"BXB\"", matcher, asList("BXB"));
+    }
+}
+
diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/IsAnythingTest.java b/hamcrest-core/src/test/java/org/hamcrest/core/IsAnythingTest.java
new file mode 100644
index 0000000..4983bf7
--- /dev/null
+++ b/hamcrest-core/src/test/java/org/hamcrest/core/IsAnythingTest.java
@@ -0,0 +1,35 @@
+package org.hamcrest.core;
+
+import org.hamcrest.Matcher;
+import org.junit.Test;
+
+import static org.hamcrest.AbstractMatcherTest.assertDescription;
+import static org.hamcrest.AbstractMatcherTest.assertMatches;
+import static org.hamcrest.core.IsAnything.anything;
+
+public final class IsAnythingTest {
+
+    private final Matcher<Object> matcher = anything();
+
+    private static class CustomThing { }
+    
+    @Test public void
+    alwaysEvaluatesToTrue() {
+        assertMatches("didn't match null", matcher, null);
+        assertMatches("didn't match Object", matcher, new Object());
+        assertMatches("didn't match custom object", matcher, new CustomThing());
+        assertMatches("didn't match String", matcher, "hi");
+    }
+
+    @Test public void
+    hasUsefulDefaultDescription() {
+        assertDescription("ANYTHING", matcher);
+    }
+
+    @Test public void
+    canOverrideDescription() {
+        String description = "description";
+        assertDescription(description, anything(description));
+    }
+
+}
diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/IsCollectionContainingTest.java b/hamcrest-core/src/test/java/org/hamcrest/core/IsCollectionContainingTest.java
new file mode 100644
index 0000000..a9007cd
--- /dev/null
+++ b/hamcrest-core/src/test/java/org/hamcrest/core/IsCollectionContainingTest.java
@@ -0,0 +1,107 @@
+package org.hamcrest.core;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeDiagnosingMatcher;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+
+import static java.util.Arrays.asList;
+import static org.hamcrest.AbstractMatcherTest.*;
+import static org.hamcrest.core.IsCollectionContaining.hasItem;
+import static org.hamcrest.core.IsCollectionContaining.hasItems;
+import static org.hamcrest.core.IsEqual.equalTo;
+
+public final class IsCollectionContainingTest {
+    
+    @Test public void
+    copesWithNullsAndUnknownTypes() {
+        Matcher<?> matcher = hasItem(equalTo("irrelevant"));
+        
+        assertNullSafe(matcher);
+        assertUnknownTypeSafe(matcher);
+    }
+
+    @Test public void
+    matchesACollectionThatContainsAnElementForTheGivenMatcher() {
+        final Matcher<Iterable<? super String>> itemMatcher = hasItem(equalTo("a"));
+
+        assertMatches("list containing 'a'", itemMatcher, asList("a", "b", "c"));
+    }
+
+    @Test public void
+    doesNotMatchCollectionWithoutAnElementForGivenMatcher() {
+        final Matcher<Iterable<? super String>> matcher = hasItem(mismatchable("a"));
+        
+        assertMismatchDescription("mismatches were: [mismatched: b, mismatched: c]", matcher, asList("b", "c"));
+        assertMismatchDescription("was empty", matcher, new ArrayList<String>());
+    }
+
+    @Test public void
+    doesNotMatchNull() {
+        assertDoesNotMatch("doesn't match null", hasItem(equalTo("a")), null);
+    }
+
+    @Test public void
+    hasAReadableDescription() {
+        assertDescription("a collection containing mismatchable: a", hasItem(mismatchable("a")));
+    }
+    
+    @Test public void
+    canMatchItemWhenCollectionHoldsSuperclass() { // Issue 24
+        final Set<Number> s = new HashSet<Number>();
+        s.add(2);
+
+        assertMatches(new IsCollectionContaining<Number>(new IsEqual<Number>(2)), s);
+        assertMatches(IsCollectionContaining.hasItem(2), s);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test public void
+    matchesMultipleItemsInCollection() {
+        final Matcher<Iterable<String>> matcher1 = hasItems(equalTo("a"), equalTo("b"), equalTo("c"));
+        assertMatches("list containing all items", matcher1, asList("a", "b", "c"));
+        
+        final Matcher<Iterable<String>> matcher2 = hasItems("a", "b", "c");
+        assertMatches("list containing all items (without matchers)", matcher2, asList("a", "b", "c"));
+        
+        final Matcher<Iterable<String>> matcher3 = hasItems(equalTo("a"), equalTo("b"), equalTo("c"));
+        assertMatches("list containing all items in any order", matcher3, asList("c", "b", "a"));
+        
+        final Matcher<Iterable<String>> matcher4 = hasItems(equalTo("a"), equalTo("b"), equalTo("c"));
+        assertMatches("list containing all items plus others", matcher4, asList("e", "c", "b", "a", "d"));
+        
+        final Matcher<Iterable<String>> matcher5 = hasItems(equalTo("a"), equalTo("b"), equalTo("c"));
+        assertDoesNotMatch("not match list unless it contains all items", matcher5, asList("e", "c", "b", "d")); // 'a' missing
+    }
+    
+    @Test public void
+    reportsMismatchWithAReadableDescriptionForMultipleItems() {
+        final Matcher<Iterable<Integer>> matcher = hasItems(3, 4);
+        
+        assertMismatchDescription("a collection containing <4> mismatches were: [was <1>, was <2>, was <3>]",
+                                  matcher, asList(1, 2, 3));
+    }
+
+    private static Matcher<? super String> mismatchable(final String string) {
+        return new TypeSafeDiagnosingMatcher<String>() {
+            @Override
+            protected boolean matchesSafely(String item, Description mismatchDescription) {
+                if (string.equals(item)) 
+                    return true;
+
+                mismatchDescription.appendText("mismatched: " + item);
+                return false;
+            }
+
+            @Override
+            public void describeTo(Description description) {
+                description.appendText("mismatchable: " + string);
+            }
+        };
+    }
+}
+
diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/IsEqualTest.java b/hamcrest-core/src/test/java/org/hamcrest/core/IsEqualTest.java
new file mode 100644
index 0000000..9df73e4
--- /dev/null
+++ b/hamcrest-core/src/test/java/org/hamcrest/core/IsEqualTest.java
@@ -0,0 +1,143 @@
+package org.hamcrest.core;
+
+import org.hamcrest.Matcher;
+import org.junit.Test;
+
+import static org.hamcrest.AbstractMatcherTest.*;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.hamcrest.core.IsEqual.equalToObject;
+
+public final class IsEqualTest {
+
+    @Test public void
+    copesWithNullsAndUnknownTypes() {
+        Matcher<?> matcher = equalTo("irrelevant");
+
+        assertNullSafe(matcher);
+        assertUnknownTypeSafe(matcher);
+    }
+
+    @Test public void
+    comparesObjectsUsingEqualsMethod() {
+        final Matcher<String> matcher1 = equalTo("hi");
+        assertMatches(matcher1, "hi");
+        assertDoesNotMatch(matcher1, "bye");
+        assertDoesNotMatch(matcher1, null);
+
+        final Matcher<Integer> matcher2 = equalTo(1);
+        assertMatches(matcher2, 1);
+        assertDoesNotMatch(matcher2, 2);
+        assertDoesNotMatch(matcher2, null);
+    }
+
+    @Test public void
+    canCompareNullValues() {
+        final Matcher<Object> matcher = equalTo(null);
+        
+        assertMatches(matcher, null);
+        assertDoesNotMatch(matcher, 2);
+        assertDoesNotMatch(matcher, "hi");
+        assertDoesNotMatch(matcher, new String[] {"a", "b"});
+    }
+
+    @SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
+    @Test public void
+    honoursIsEqualImplementationEvenWithNullValues() {
+        Object alwaysEqual = new Object() {
+            @Override
+            public boolean equals(Object obj) {
+                return true;
+            }
+        };
+        Object neverEqual = new Object() {
+            @Override
+            public boolean equals(Object obj) {
+                return false;
+            }
+        };
+
+        Matcher<Object> matcher = equalTo(null);
+
+        assertMatches(matcher, alwaysEqual);
+        assertDoesNotMatch(matcher, neverEqual);
+    }
+
+    @Test public void
+    comparesTheElementsOfAnObjectArray() {
+        String[] s1 = {"a", "b"};
+        String[] s2 = {"a", "b"};
+        String[] s3 = {"c", "d"};
+        String[] s4 = {"a", "b", "c", "d"};
+
+        final Matcher<String[]> matcher = equalTo(s1);
+        assertMatches(matcher, s1);
+        assertMatches(matcher, s2);
+        assertDoesNotMatch(matcher, s3);
+        assertDoesNotMatch(matcher, s4);
+        assertDoesNotMatch(matcher, null);
+    }
+
+    @Test public void
+    comparesTheElementsOfAnArrayOfPrimitiveTypes() {
+        int[] i1 = new int[]{1, 2};
+        int[] i2 = new int[]{1, 2};
+        int[] i3 = new int[]{3, 4};
+        int[] i4 = new int[]{1, 2, 3, 4};
+
+        final Matcher<int[]> matcher = equalTo(i1);
+        assertMatches(matcher, i1);
+        assertMatches(matcher, i2);
+        assertDoesNotMatch(matcher, i3);
+        assertDoesNotMatch(matcher, i4);
+        assertDoesNotMatch(matcher, null);
+    }
+
+    @Test public void
+    recursivelyTestsElementsOfArrays() {
+        int[][] i1 = new int[][]{{1, 2}, {3, 4}};
+        int[][] i2 = new int[][]{{1, 2}, {3, 4}};
+        int[][] i3 = new int[][]{{5, 6}, {7, 8}};
+        int[][] i4 = new int[][]{{1, 2, 3, 4}, {3, 4}};
+
+        final Matcher<int[][]> matcher = equalTo(i1);
+        assertMatches(matcher, i1);
+        assertMatches(matcher, i2);
+        assertDoesNotMatch(matcher, i3);
+        assertDoesNotMatch(matcher, i4);
+        assertDoesNotMatch(matcher, null);
+    }
+
+    @Test public void
+    hasUntypedVariant() {
+        Object original = 10;
+
+        assertMatches(equalToObject(10), original);
+        assertDoesNotMatch(equalToObject(0), original);
+        assertDoesNotMatch(equalToObject("10"), original);
+        assertDoesNotMatch(equalToObject(10), "10");
+    }
+
+    @Test public void
+    includesTheResultOfCallingToStringOnItsArgumentInTheDescription() {
+        final String argumentDescription = "ARGUMENT DESCRIPTION";
+        Object argument = new Object() {
+            @Override
+            public String toString() {
+                return argumentDescription;
+            }
+        };
+        assertDescription("<" + argumentDescription + ">", equalTo(argument));
+    }
+
+    @Test public void
+    returnsAnObviousDescriptionIfCreatedWithANestedMatcherByMistake() {
+        Matcher<? super String> innerMatcher = equalTo("NestedMatcher");
+        assertDescription("<" + innerMatcher.toString() + ">", equalTo(innerMatcher));
+    }
+
+    @Test public void
+    returnsGoodDescriptionIfCreatedWithNullReference() {
+        assertDescription("null", equalTo(null));
+    }
+}
+
diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/IsInstanceOfTest.java b/hamcrest-core/src/test/java/org/hamcrest/core/IsInstanceOfTest.java
new file mode 100644
index 0000000..8dd85af
--- /dev/null
+++ b/hamcrest-core/src/test/java/org/hamcrest/core/IsInstanceOfTest.java
@@ -0,0 +1,69 @@
+package org.hamcrest.core;
+
+import org.hamcrest.Matcher;
+import org.junit.Test;
+
+import static org.hamcrest.AbstractMatcherTest.*;
+import static org.hamcrest.core.IsInstanceOf.any;
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
+
+public final class IsInstanceOfTest {
+
+    @Test public void
+    copesWithNullsAndUnknownTypes() {
+        Matcher<?> matcher = instanceOf(Number.class);
+
+        assertNullSafe(matcher);
+        assertUnknownTypeSafe(matcher);
+    }
+
+    @Test public void
+    evaluatesToTrueIfArgumentIsInstanceOfASpecificClass() {
+        final Matcher<Object> matcher = instanceOf(Number.class);
+
+        assertMatches(matcher, 1);
+        assertMatches(matcher, 1.1);
+        assertDoesNotMatch(matcher, null);
+        assertDoesNotMatch(matcher, new Object());
+    }
+
+    @Test public void
+    hasAReadableDescription() {
+        assertDescription("an instance of java.lang.Number", instanceOf(Number.class));
+    }
+
+    @Test public void
+    describesActualClassInMismatchMessage() {
+        assertMismatchDescription("\"some text\" is a java.lang.String", instanceOf(Number.class), "some text");
+    }
+
+    @Test public void
+    matchesPrimitiveTypes() {
+        assertMatches(any(boolean.class), true);
+        assertMatches(any(byte.class), (byte)1);
+        assertMatches(any(char.class), 'x');
+        assertMatches(any(double.class), 5.0);
+        assertMatches(any(float.class), 5.0f);
+        assertMatches(any(int.class), 2);
+        assertMatches(any(long.class), 4L);
+        assertMatches(any(short.class), (short)1);
+    }
+
+    @Test public void
+    instanceOfRequiresACastToReturnTheCorrectTypeForUseInJMock() {
+        @SuppressWarnings("unused")
+        Integer anInteger = (Integer)with(instanceOf(Integer.class));
+    }
+
+    @Test public void
+    anyWillReturnTheCorrectTypeForUseInJMock() {
+        @SuppressWarnings("unused")
+        Integer anInteger = with(any(Integer.class));
+    }
+
+
+    private static <T> T with(@SuppressWarnings("unused") Matcher<T> matcher) {
+        return null;
+    }
+}
+
diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/IsNotTest.java b/hamcrest-core/src/test/java/org/hamcrest/core/IsNotTest.java
new file mode 100644
index 0000000..79f4683
--- /dev/null
+++ b/hamcrest-core/src/test/java/org/hamcrest/core/IsNotTest.java
@@ -0,0 +1,42 @@
+package org.hamcrest.core;
+
+import org.hamcrest.Matcher;
+import org.junit.Test;
+
+import static org.hamcrest.AbstractMatcherTest.*;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
+import static org.hamcrest.core.IsNot.not;
+
+public final class IsNotTest {
+
+    @Test public void
+    copesWithNullsAndUnknownTypes() {
+        Matcher<String> matcher = not("something");
+
+        assertNullSafe(matcher);
+        assertUnknownTypeSafe(matcher);
+    }
+
+    @Test public void
+    evaluatesToTheTheLogicalNegationOfAnotherMatcher() {
+        final Matcher<String> matcher = not(equalTo("A"));
+
+        assertMatches(matcher, "B");
+        assertDoesNotMatch(matcher, "A");
+    }
+
+    @Test public void
+    providesConvenientShortcutForNotEqualTo() {
+        final Matcher<String> matcher = not("A");
+
+        assertMatches(matcher, "B");
+        assertDoesNotMatch(matcher, "A");
+    }
+
+    @Test public void
+    usesDescriptionOfNegatedMatcherWithPrefix() {
+        assertDescription("not an instance of java.lang.String", not(instanceOf(String.class)));
+        assertDescription("not \"A\"", not("A"));
+    }
+}
diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/IsNullTest.java b/hamcrest-core/src/test/java/org/hamcrest/core/IsNullTest.java
new file mode 100644
index 0000000..74b046b
--- /dev/null
+++ b/hamcrest-core/src/test/java/org/hamcrest/core/IsNullTest.java
@@ -0,0 +1,43 @@
+package org.hamcrest.core;
+
+import org.hamcrest.Matcher;
+import org.junit.Test;
+
+import static org.hamcrest.AbstractMatcherTest.*;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.hamcrest.core.IsNull.nullValue;
+
+
+public final class IsNullTest {
+
+    private final Matcher<Object> nullMatcher = nullValue();
+    private final Matcher<Object> notNullMatcher = notNullValue();
+
+    @Test public void
+    copesWithNullsAndUnknownTypes() {
+        assertNullSafe(nullMatcher);
+        assertUnknownTypeSafe(nullMatcher);
+        
+        assertNullSafe(notNullMatcher);
+        assertUnknownTypeSafe(notNullMatcher);
+    }
+
+    @Test public void
+    evaluatesToTrueIfArgumentIsNull() {
+        assertMatches(nullMatcher, null);
+        assertDoesNotMatch(nullMatcher, new Object());
+        
+        assertMatches(notNullMatcher, new Object());
+        assertDoesNotMatch(notNullMatcher, null);
+    }
+    
+    @Test public void
+    supportsStaticTyping() {
+        requiresStringMatcher(nullValue(String.class));
+        requiresStringMatcher(notNullValue(String.class));
+    }
+
+    private void requiresStringMatcher(@SuppressWarnings("unused") Matcher<String> arg) {
+        // no-op
+    }
+}
diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/IsSameTest.java b/hamcrest-core/src/test/java/org/hamcrest/core/IsSameTest.java
new file mode 100644
index 0000000..a4a2010
--- /dev/null
+++ b/hamcrest-core/src/test/java/org/hamcrest/core/IsSameTest.java
@@ -0,0 +1,48 @@
+package org.hamcrest.core;
+
+import org.hamcrest.Matcher;
+import org.junit.Test;
+
+import static org.hamcrest.AbstractMatcherTest.*;
+import static org.hamcrest.core.IsSame.sameInstance;
+import static org.hamcrest.core.IsSame.theInstance;
+
+
+public final class IsSameTest {
+
+    @Test public void
+    copesWithNullsAndUnknownTypes() {
+        Matcher<String> matcher = sameInstance("irrelevant");
+        
+        assertNullSafe(matcher);
+        assertUnknownTypeSafe(matcher);
+    }
+
+    @Test public void
+    evaluatesToTrueIfArgumentIsReferenceToASpecifiedObject() {
+        Object o1 = new Object();
+        Matcher<Object> matcher = sameInstance(o1);
+
+        assertMatches(matcher, o1);
+        assertDoesNotMatch(matcher, new Object());
+    }
+
+    @Test public void
+    alternativeFactoryMethodAlsoMatchesOnlyIfArgumentIsReferenceToASpecifiedObject() {
+        Object o1 = new Object();
+        Matcher<Object> matcher = theInstance(o1);
+
+        assertMatches(matcher, o1);
+        assertDoesNotMatch(matcher, new Object());
+    }
+
+    @Test public void
+    returnsReadableDescriptionFromToString() {
+        assertDescription("sameInstance(\"ARG\")", sameInstance("ARG"));
+    }
+
+    @Test public void
+    returnsReadableDescriptionFromToStringWhenInitialisedWithNull() {
+        assertDescription("sameInstance(null)", sameInstance(null));
+    }
+}
diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/IsTest.java b/hamcrest-core/src/test/java/org/hamcrest/core/IsTest.java
new file mode 100644
index 0000000..6656e6d
--- /dev/null
+++ b/hamcrest-core/src/test/java/org/hamcrest/core/IsTest.java
@@ -0,0 +1,51 @@
+package org.hamcrest.core;
+
+import org.hamcrest.Matcher;
+import org.junit.Test;
+
+import static org.hamcrest.AbstractMatcherTest.*;
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.Is.isA;
+import static org.hamcrest.core.IsEqual.equalTo;
+
+public final class IsTest {
+
+    @Test public void
+    copesWithNullsAndUnknownTypes() {
+        Matcher<String> matcher = is("something");
+        
+        assertNullSafe(matcher);
+        assertUnknownTypeSafe(matcher);
+    }
+
+    @Test public void
+    matchesTheSameWayTheUnderlyingMatcherDoes() {
+        final Matcher<Boolean> matcher = is(equalTo(true));
+
+        assertMatches(matcher, true);
+        assertDoesNotMatch(matcher, false);
+    }
+
+    @Test public void
+    generatesIsPrefixInDescription() {
+        assertDescription("is <true>", is(equalTo(true)));
+        assertDescription("is \"A\"", is("A"));
+    }
+
+    @Test public void
+    providesConvenientShortcutForIsEqualTo() {
+        final Matcher<String> matcher = is("A");
+        
+        assertMatches(matcher, "A");
+        assertDoesNotMatch(is("A"), "B");
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    @Test public void
+    providesConvenientShortcutForIsInstanceOf() {
+        final Matcher matcher = isA(Integer.class);
+        assertMatches(matcher, 1);
+        assertDoesNotMatch(matcher, new Object());
+        assertDoesNotMatch(matcher, null);
+    }
+}
diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/SampleBaseClass.java b/hamcrest-core/src/test/java/org/hamcrest/core/SampleBaseClass.java
new file mode 100644
index 0000000..baf4d8e
--- /dev/null
+++ b/hamcrest-core/src/test/java/org/hamcrest/core/SampleBaseClass.java
@@ -0,0 +1,24 @@
+package org.hamcrest.core;
+
+public class SampleBaseClass {
+    String value;
+
+    public SampleBaseClass(String value) {
+        this.value = value;
+    }
+
+    @Override
+    public String toString() {
+        return value;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        return obj instanceof SampleBaseClass && value.equals(((SampleBaseClass) obj).value);
+    }
+
+    @Override
+    public int hashCode() {
+      return value.hashCode();
+    }
+}
diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/SampleSubClass.java b/hamcrest-core/src/test/java/org/hamcrest/core/SampleSubClass.java
new file mode 100644
index 0000000..bdaa160
--- /dev/null
+++ b/hamcrest-core/src/test/java/org/hamcrest/core/SampleSubClass.java
@@ -0,0 +1,9 @@
+package org.hamcrest.core;
+
+public class SampleSubClass extends SampleBaseClass {
+    
+    public SampleSubClass(String value) {
+        super(value);
+    }
+
+}
diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/StringContainsTest.java b/hamcrest-core/src/test/java/org/hamcrest/core/StringContainsTest.java
new file mode 100644
index 0000000..93dd05c
--- /dev/null
+++ b/hamcrest-core/src/test/java/org/hamcrest/core/StringContainsTest.java
@@ -0,0 +1,43 @@
+package org.hamcrest.core;
+
+import org.hamcrest.AbstractMatcherTest;
+import org.hamcrest.Matcher;
+
+import static org.hamcrest.core.StringContains.containsString;
+import static org.hamcrest.core.StringContains.containsStringIgnoringCase;
+
+
+public class StringContainsTest extends AbstractMatcherTest {
+    static final String EXCERPT = "EXCERPT";
+    final Matcher<String> stringContains = containsString(EXCERPT);
+
+    @Override
+    protected Matcher<?> createMatcher() {
+        return stringContains;
+    }
+
+    public void testMatchesSubstrings() {
+        assertMatches(stringContains, EXCERPT + "END");
+        assertMatches(stringContains, "START" + EXCERPT);
+        assertMatches(stringContains, "START" + EXCERPT + "END");
+        assertMatches(stringContains, EXCERPT);
+        assertDoesNotMatch(stringContains, EXCERPT.toLowerCase());
+        assertMatches(stringContains, EXCERPT + EXCERPT);
+        assertDoesNotMatch(stringContains, "XC");
+
+        assertMismatchDescription("was \"Something else\"", stringContains, "Something else");
+        assertDescription("a string containing \"EXCERPT\"", stringContains);
+    }
+
+    public void testMatchesSubstringsIgnoringCase() {
+        final Matcher<String> ignoringCase = containsStringIgnoringCase("ExCert");
+        assertMatches(ignoringCase, "eXcERT" + "END");
+        assertMatches(ignoringCase, "START" + "EXCert");
+        assertMatches(ignoringCase, "START" + "excERT" + "END");
+        assertMatches(ignoringCase, "eXCert" + "excErt");
+        assertDoesNotMatch(ignoringCase, "xc");
+
+        assertMismatchDescription("was \"Something else\"", ignoringCase, "Something else");
+        assertDescription("a string containing \"ExCert\" ignoring case", ignoringCase);
+    }
+}
diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/StringEndsWithTest.java b/hamcrest-core/src/test/java/org/hamcrest/core/StringEndsWithTest.java
new file mode 100644
index 0000000..f482cbf
--- /dev/null
+++ b/hamcrest-core/src/test/java/org/hamcrest/core/StringEndsWithTest.java
@@ -0,0 +1,45 @@
+package org.hamcrest.core;
+
+import org.hamcrest.AbstractMatcherTest;
+import org.hamcrest.Matcher;
+
+import static org.hamcrest.core.StringEndsWith.endsWith;
+import static org.hamcrest.core.StringEndsWith.endsWithIgnoringCase;
+
+
+public class StringEndsWithTest extends AbstractMatcherTest {
+    static final String EXCERPT = "EXCERPT";
+    final Matcher<String> stringEndsWith = endsWith(EXCERPT);
+
+    @Override
+    protected Matcher<?> createMatcher() {
+        return stringEndsWith;
+    }
+
+    public void testMatchesSubstringAtEnd() {
+        assertDoesNotMatch(stringEndsWith, EXCERPT + "END");
+        assertMatches(stringEndsWith, "START" + EXCERPT);
+        assertMatches(stringEndsWith, EXCERPT);
+        assertDoesNotMatch(stringEndsWith, EXCERPT.toLowerCase());
+        assertDoesNotMatch(stringEndsWith, "START" + EXCERPT + "END");
+        assertMatches(stringEndsWith, EXCERPT + EXCERPT);
+        assertDoesNotMatch(stringEndsWith, "EXCER");
+
+        assertMismatchDescription("was \"Something else\"", stringEndsWith, "Something else");
+        assertDescription("a string ending with \"EXCERPT\"", stringEndsWith);
+    }
+
+    public void testMatchesSubstringAtEndIngoringCase() {
+        final Matcher<String> ignoringCase = endsWithIgnoringCase("EXCERpt");
+        assertDoesNotMatch(ignoringCase, "eXCErpt" + "END");
+        assertMatches(ignoringCase, "START" + "EXceRpt");
+        assertMatches(ignoringCase, "EXcerPT");
+        assertDoesNotMatch(ignoringCase, "START" + "ExcERpt" + "END");
+        assertMatches(ignoringCase, "exCERpt" + "EXCerPt");
+        assertDoesNotMatch(ignoringCase, "ExcER");
+
+        assertMismatchDescription("was \"Something else\"", ignoringCase, "Something else");
+        assertDescription("a string ending with \"EXCERpt\" ignoring case", ignoringCase);
+    }
+
+}
diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/StringStartsWithTest.java b/hamcrest-core/src/test/java/org/hamcrest/core/StringStartsWithTest.java
new file mode 100644
index 0000000..f093acb
--- /dev/null
+++ b/hamcrest-core/src/test/java/org/hamcrest/core/StringStartsWithTest.java
@@ -0,0 +1,46 @@
+package org.hamcrest.core;
+
+import org.hamcrest.AbstractMatcherTest;
+import org.hamcrest.Matcher;
+
+import static org.hamcrest.core.StringStartsWith.startsWith;
+import static org.hamcrest.core.StringStartsWith.startsWithIgnoringCase;
+
+
+public class StringStartsWithTest extends AbstractMatcherTest {
+    static final String EXCERPT = "EXCERPT";
+    final Matcher<String> stringStartsWith = startsWith(EXCERPT);
+
+    @Override
+    protected Matcher<?> createMatcher() {
+        return stringStartsWith;
+    }
+
+    public void testMatchesStringAtStart() {
+        assertMatches(stringStartsWith, EXCERPT + "END");
+        assertDoesNotMatch(stringStartsWith, "START" + EXCERPT);
+        assertDoesNotMatch(stringStartsWith, "START" + EXCERPT + "END");
+        assertMatches(stringStartsWith, EXCERPT);
+        assertDoesNotMatch(stringStartsWith, EXCERPT.toLowerCase());
+        assertMatches(stringStartsWith, EXCERPT + EXCERPT);
+        assertDoesNotMatch(stringStartsWith, "EXCER");
+
+        assertDescription("a string starting with \"EXCERPT\"", stringStartsWith);
+        assertMismatchDescription("was \"Something else\"", stringStartsWith, "Something else");
+    }
+
+    public void testMatchesStringAtStartIgnoringCase() {
+        final Matcher<String> ignoreCase = startsWithIgnoringCase("EXCerPT");
+
+        assertMatches(ignoreCase, "exCerPT" + "END");
+        assertDoesNotMatch(ignoreCase, "START" + "EXCerpt");
+        assertDoesNotMatch(ignoreCase, "START" + "EXcerpT" + "END");
+        assertMatches(ignoreCase, "excERPT");
+        assertMatches(ignoreCase, "ExcerPT" + "EXCerpt");
+        assertDoesNotMatch(ignoreCase, "ExcER");
+
+        assertDescription("a string starting with \"EXCerPT\" ignoring case", ignoreCase);
+        assertMismatchDescription("was \"Something else\"", ignoreCase, "Something else");
+    }
+
+}
diff --git a/hamcrest-library/LICENSE.txt b/hamcrest-library/LICENSE.txt
deleted file mode 100644
index 5ebe92c..0000000
--- a/hamcrest-library/LICENSE.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-BSD License

-

-Copyright (c) 2000-2006, www.hamcrest.org

-All rights reserved.

-

-Redistribution and use in source and binary forms, with or without

-modification, are permitted provided that the following conditions are met:

-

-Redistributions of source code must retain the above copyright notice, this list of

-conditions and the following disclaimer. Redistributions in binary form must reproduce

-the above copyright notice, this list of conditions and the following disclaimer in

-the documentation and/or other materials provided with the distribution.

-

-Neither the name of Hamcrest nor the names of its contributors may be used to endorse

-or promote products derived from this software without specific prior written

-permission.

-

-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY

-EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES

-OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT

-SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,

-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED

-TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR

-BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY

-WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH

-DAMAGE.

diff --git a/hamcrest-library/README.android b/hamcrest-library/README.android
deleted file mode 100644
index dd099ed..0000000
--- a/hamcrest-library/README.android
+++ /dev/null
@@ -1 +0,0 @@
-Ssource obtained from https://hamcrest.googlecode.com/files/hamcrest-library-1.1.jar, with org.hamcrest.beans removed
diff --git a/hamcrest-library/build.gradle b/hamcrest-library/build.gradle
deleted file mode 100644
index 54ab15f..0000000
--- a/hamcrest-library/build.gradle
+++ /dev/null
@@ -1,13 +0,0 @@
-apply plugin: 'java'
-
-sourceSets {
-    main {
-        java {
-            srcDirs = ['src']
-        }
-    }
-}
-
-dependencies {
-    compile project(':hamcrest')
-}
diff --git a/hamcrest-library/src/main/java/org/hamcrest/Matchers.java b/hamcrest-library/src/main/java/org/hamcrest/Matchers.java
index 2e82aa0..b04c45d 100644
--- a/hamcrest-library/src/main/java/org/hamcrest/Matchers.java
+++ b/hamcrest-library/src/main/java/org/hamcrest/Matchers.java
@@ -1,28 +1,204 @@
-// Generated source.
 package org.hamcrest;
 
 public class Matchers {
 
-    /**
-     * Decorates another Matcher, retaining the behavior but allowing tests
-     * to be slightly more expressive.
-     * 
-     * eg. assertThat(cheese, equalTo(smelly))
-     * vs assertThat(cheese, is(equalTo(smelly)))
-     */
-    public static <T> org.hamcrest.Matcher<T> is(org.hamcrest.Matcher<T> matcher) {
-        return org.hamcrest.core.Is.is(matcher);
-    }
+  /**
+   * Creates a matcher that matches if the examined object matches <b>ALL</b> of the specified matchers.
+   * For example:
+   * <pre>assertThat("myValue", allOf(startsWith("my"), containsString("Val")))</pre>
+   */
+  public static <T> org.hamcrest.Matcher<T> allOf(java.lang.Iterable<org.hamcrest.Matcher<? super T>> matchers) {
+    return org.hamcrest.core.AllOf.<T>allOf(matchers);
+  }
 
-    /**
-     * This is a shortcut to the frequently used is(equalTo(x)).
-     * 
-     * eg. assertThat(cheese, is(equalTo(smelly)))
-     * vs assertThat(cheese, is(smelly))
-     */
-    public static <T> org.hamcrest.Matcher<T> is(T value) {
-        return org.hamcrest.core.Is.is(value);
-    }
+  /**
+   * Creates a matcher that matches if the examined object matches <b>ALL</b> of the specified matchers.
+   * For example:
+   * <pre>assertThat("myValue", allOf(startsWith("my"), containsString("Val")))</pre>
+   */
+  public static <T> org.hamcrest.Matcher<T> allOf(org.hamcrest.Matcher<? super T>... matchers) {
+    return org.hamcrest.core.AllOf.<T>allOf(matchers);
+  }
+
+  /**
+   * Creates a matcher that matches if the examined object matches <b>ALL</b> of the specified matchers.
+   * For example:
+   * <pre>assertThat("myValue", allOf(startsWith("my"), containsString("Val")))</pre>
+   */
+  public static <T> org.hamcrest.Matcher<T> allOf(org.hamcrest.Matcher<? super T> first, org.hamcrest.Matcher<? super T> second) {
+    return org.hamcrest.core.AllOf.<T>allOf(first, second);
+  }
+
+  /**
+   * Creates a matcher that matches if the examined object matches <b>ALL</b> of the specified matchers.
+   * For example:
+   * <pre>assertThat("myValue", allOf(startsWith("my"), containsString("Val")))</pre>
+   */
+  public static <T> org.hamcrest.Matcher<T> allOf(org.hamcrest.Matcher<? super T> first, org.hamcrest.Matcher<? super T> second, org.hamcrest.Matcher<? super T> third) {
+    return org.hamcrest.core.AllOf.<T>allOf(first, second, third);
+  }
+
+  /**
+   * Creates a matcher that matches if the examined object matches <b>ALL</b> of the specified matchers.
+   * For example:
+   * <pre>assertThat("myValue", allOf(startsWith("my"), containsString("Val")))</pre>
+   */
+  public static <T> org.hamcrest.Matcher<T> allOf(org.hamcrest.Matcher<? super T> first, org.hamcrest.Matcher<? super T> second, org.hamcrest.Matcher<? super T> third, org.hamcrest.Matcher<? super T> fourth) {
+    return org.hamcrest.core.AllOf.<T>allOf(first, second, third, fourth);
+  }
+
+  /**
+   * Creates a matcher that matches if the examined object matches <b>ALL</b> of the specified matchers.
+   * For example:
+   * <pre>assertThat("myValue", allOf(startsWith("my"), containsString("Val")))</pre>
+   */
+  public static <T> org.hamcrest.Matcher<T> allOf(org.hamcrest.Matcher<? super T> first, org.hamcrest.Matcher<? super T> second, org.hamcrest.Matcher<? super T> third, org.hamcrest.Matcher<? super T> fourth, org.hamcrest.Matcher<? super T> fifth) {
+    return org.hamcrest.core.AllOf.<T>allOf(first, second, third, fourth, fifth);
+  }
+
+  /**
+   * Creates a matcher that matches if the examined object matches <b>ALL</b> of the specified matchers.
+   * For example:
+   * <pre>assertThat("myValue", allOf(startsWith("my"), containsString("Val")))</pre>
+   */
+  public static <T> org.hamcrest.Matcher<T> allOf(org.hamcrest.Matcher<? super T> first, org.hamcrest.Matcher<? super T> second, org.hamcrest.Matcher<? super T> third, org.hamcrest.Matcher<? super T> fourth, org.hamcrest.Matcher<? super T> fifth, org.hamcrest.Matcher<? super T> sixth) {
+    return org.hamcrest.core.AllOf.<T>allOf(first, second, third, fourth, fifth, sixth);
+  }
+
+  /**
+   * Creates a matcher that matches if the examined object matches <b>ANY</b> of the specified matchers.
+   * For example:
+   * <pre>assertThat("myValue", anyOf(startsWith("foo"), containsString("Val")))</pre>
+   */
+  public static <T> org.hamcrest.core.AnyOf<T> anyOf(java.lang.Iterable<org.hamcrest.Matcher<? super T>> matchers) {
+    return org.hamcrest.core.AnyOf.<T>anyOf(matchers);
+  }
+
+  /**
+   * Creates a matcher that matches if the examined object matches <b>ANY</b> of the specified matchers.
+   * For example:
+   * <pre>assertThat("myValue", anyOf(startsWith("foo"), containsString("Val")))</pre>
+   */
+  public static <T> org.hamcrest.core.AnyOf<T> anyOf(org.hamcrest.Matcher<? super T>... matchers) {
+    return org.hamcrest.core.AnyOf.<T>anyOf(matchers);
+  }
+
+  /**
+   * Creates a matcher that matches if the examined object matches <b>ANY</b> of the specified matchers.
+   * For example:
+   * <pre>assertThat("myValue", anyOf(startsWith("foo"), containsString("Val")))</pre>
+   */
+  public static <T> org.hamcrest.core.AnyOf<T> anyOf(org.hamcrest.Matcher<T> first, org.hamcrest.Matcher<? super T> second) {
+    return org.hamcrest.core.AnyOf.<T>anyOf(first, second);
+  }
+
+  /**
+   * Creates a matcher that matches if the examined object matches <b>ANY</b> of the specified matchers.
+   * For example:
+   * <pre>assertThat("myValue", anyOf(startsWith("foo"), containsString("Val")))</pre>
+   */
+  public static <T> org.hamcrest.core.AnyOf<T> anyOf(org.hamcrest.Matcher<T> first, org.hamcrest.Matcher<? super T> second, org.hamcrest.Matcher<? super T> third) {
+    return org.hamcrest.core.AnyOf.<T>anyOf(first, second, third);
+  }
+
+  /**
+   * Creates a matcher that matches if the examined object matches <b>ANY</b> of the specified matchers.
+   * For example:
+   * <pre>assertThat("myValue", anyOf(startsWith("foo"), containsString("Val")))</pre>
+   */
+  public static <T> org.hamcrest.core.AnyOf<T> anyOf(org.hamcrest.Matcher<T> first, org.hamcrest.Matcher<? super T> second, org.hamcrest.Matcher<? super T> third, org.hamcrest.Matcher<? super T> fourth) {
+    return org.hamcrest.core.AnyOf.<T>anyOf(first, second, third, fourth);
+  }
+
+  /**
+   * Creates a matcher that matches if the examined object matches <b>ANY</b> of the specified matchers.
+   * For example:
+   * <pre>assertThat("myValue", anyOf(startsWith("foo"), containsString("Val")))</pre>
+   */
+  public static <T> org.hamcrest.core.AnyOf<T> anyOf(org.hamcrest.Matcher<T> first, org.hamcrest.Matcher<? super T> second, org.hamcrest.Matcher<? super T> third, org.hamcrest.Matcher<? super T> fourth, org.hamcrest.Matcher<? super T> fifth) {
+    return org.hamcrest.core.AnyOf.<T>anyOf(first, second, third, fourth, fifth);
+  }
+
+  /**
+   * Creates a matcher that matches if the examined object matches <b>ANY</b> of the specified matchers.
+   * For example:
+   * <pre>assertThat("myValue", anyOf(startsWith("foo"), containsString("Val")))</pre>
+   */
+  public static <T> org.hamcrest.core.AnyOf<T> anyOf(org.hamcrest.Matcher<T> first, org.hamcrest.Matcher<? super T> second, org.hamcrest.Matcher<? super T> third, org.hamcrest.Matcher<? super T> fourth, org.hamcrest.Matcher<? super T> fifth, org.hamcrest.Matcher<? super T> sixth) {
+    return org.hamcrest.core.AnyOf.<T>anyOf(first, second, third, fourth, fifth, sixth);
+  }
+
+  /**
+   * Creates a matcher that matches when both of the specified matchers match the examined object.
+   * For example:
+   * <pre>assertThat("fab", both(containsString("a")).and(containsString("b")))</pre>
+   */
+  public static <LHS> org.hamcrest.core.CombinableMatcher.CombinableBothMatcher<LHS> both(org.hamcrest.Matcher<? super LHS> matcher) {
+    return org.hamcrest.core.CombinableMatcher.<LHS>both(matcher);
+  }
+
+  /**
+   * Creates a matcher that matches when either of the specified matchers match the examined object.
+   * For example:
+   * <pre>assertThat("fan", either(containsString("a")).or(containsString("b")))</pre>
+   */
+  public static <LHS> org.hamcrest.core.CombinableMatcher.CombinableEitherMatcher<LHS> either(org.hamcrest.Matcher<? super LHS> matcher) {
+    return org.hamcrest.core.CombinableMatcher.<LHS>either(matcher);
+  }
+
+  /**
+   * Wraps an existing matcher, overriding its description with that specified.  All other functions are
+   * delegated to the decorated matcher, including its mismatch description.
+   * For example:
+   * <pre>describedAs("a big decimal equal to %0", equalTo(myBigDecimal), myBigDecimal.toPlainString())</pre>
+   * 
+   * @param description
+   *     the new description for the wrapped matcher
+   * @param matcher
+   *     the matcher to wrap
+   * @param values
+   *     optional values to insert into the tokenised description
+   */
+  public static <T> org.hamcrest.Matcher<T> describedAs(java.lang.String description, org.hamcrest.Matcher<T> matcher, java.lang.Object... values) {
+    return org.hamcrest.core.DescribedAs.<T>describedAs(description, matcher, values);
+  }
+
+  /**
+   * Creates a matcher for {@link Iterable}s that only matches when a single pass over the
+   * examined {@link Iterable} yields items that are all matched by the specified
+   * <code>itemMatcher</code>.
+   * For example:
+   * <pre>assertThat(Arrays.asList("bar", "baz"), everyItem(startsWith("ba")))</pre>
+   * 
+   * @param itemMatcher
+   *     the matcher to apply to every item provided by the examined {@link Iterable}
+   */
+  public static <U> org.hamcrest.Matcher<java.lang.Iterable<? extends U>> everyItem(org.hamcrest.Matcher<U> itemMatcher) {
+    return org.hamcrest.core.Every.<U>everyItem(itemMatcher);
+  }
+
+  /**
+   * Decorates another Matcher, retaining its behaviour, but allowing tests
+   * to be slightly more expressive.
+   * For example:
+   * <pre>assertThat(cheese, is(equalTo(smelly)))</pre>
+   * instead of:
+   * <pre>assertThat(cheese, equalTo(smelly))</pre>
+   */
+  public static <T> org.hamcrest.Matcher<T> is(org.hamcrest.Matcher<T> matcher) {
+    return org.hamcrest.core.Is.<T>is(matcher);
+  }
+
+  /**
+   * A shortcut to the frequently used <code>is(equalTo(x))</code>.
+   * For example:
+   * <pre>assertThat(cheese, is(smelly))</pre>
+   * instead of:
+   * <pre>assertThat(cheese, is(equalTo(smelly)))</pre>
+   */
+  public static <T> org.hamcrest.Matcher<T> is(T value) {
+    return org.hamcrest.core.Is.<T>is(value);
+  }
 
   /**
    * Provided to cause compile time error when used in preference to a possible runtime error if
@@ -40,275 +216,1370 @@
   public static void is(java.lang.Class<?> type) {
   }
 
-    /**
-     * Inverts the rule.
-     */
-    public static <T> org.hamcrest.Matcher<T> not(org.hamcrest.Matcher<T> matcher) {
-        return org.hamcrest.core.IsNot.not(matcher);
-    }
-
-    /**
-     * This is a shortcut to the frequently used not(equalTo(x)).
-     * 
-     * eg. assertThat(cheese, is(not(equalTo(smelly))))
-     * vs assertThat(cheese, is(not(smelly)))
-     */
-    public static <T> org.hamcrest.Matcher<T> not(T value) {
-        return org.hamcrest.core.IsNot.not(value);
-    }
-
-    /**
-     * Is the value equal to another value, as tested by the
-     * {@link java.lang.Object#equals} invokedMethod?
-     */
-    public static <T> org.hamcrest.Matcher<T> equalTo(T operand) {
-        return org.hamcrest.core.IsEqual.equalTo(operand);
-    }
-
-    /**
-     * Is the value an instance of a particular type?
-     */
-    public static org.hamcrest.Matcher<java.lang.Object> instanceOf(java.lang.Class<?> type) {
-        return org.hamcrest.core.IsInstanceOf.instanceOf(type);
-    }
-
-    /**
-     * Evaluates to true only if ALL of the passed in matchers evaluate to true.
-     */
-    public static <T> org.hamcrest.Matcher<T> allOf(org.hamcrest.Matcher<? extends T>... matchers) {
-        return org.hamcrest.core.AllOf.<T>allOf(matchers);
-    }
-
-    /**
-     * Evaluates to true only if ALL of the passed in matchers evaluate to true.
-     */
-    public static <T> org.hamcrest.Matcher<T> allOf(java.lang.Iterable<org.hamcrest.Matcher<? extends T>> matchers) {
-        return org.hamcrest.core.AllOf.allOf(matchers);
-    }
-
-    /**
-     * Evaluates to true if ANY of the passed in matchers evaluate to true.
-     */
-    public static <T> org.hamcrest.Matcher<T> anyOf(org.hamcrest.Matcher<? extends T>... matchers) {
-        return org.hamcrest.core.AnyOf.<T>anyOf(matchers);
-    }
-
-    /**
-     * Evaluates to true if ANY of the passed in matchers evaluate to true.
-     */
-    public static <T> org.hamcrest.Matcher<T> anyOf(java.lang.Iterable<org.hamcrest.Matcher<? extends T>> matchers) {
-        return org.hamcrest.core.AnyOf.anyOf(matchers);
-    }
-
-    /**
-     * Creates a new instance of IsSame
-     * 
-     * @param object The predicate evaluates to true only when the argument is
-     * this object.
-     */
-    public static <T> org.hamcrest.Matcher<T> sameInstance(T object) {
-        return org.hamcrest.core.IsSame.sameInstance(object);
-    }
-
-    /**
-     * This matcher always evaluates to true.
-     */
-    public static <T> org.hamcrest.Matcher<T> anything() {
-        return org.hamcrest.core.IsAnything.anything();
-    }
-
-    /**
-     * This matcher always evaluates to true.
-     * 
-     * @param description A meaningful string used when describing itself.
-     */
-    public static <T> org.hamcrest.Matcher<T> anything(java.lang.String description) {
-        return org.hamcrest.core.IsAnything.anything(description);
-    }
-
-    /**
-     * This matcher always evaluates to true. With type inference.
-     */
-    public static <T> org.hamcrest.Matcher<T> any(java.lang.Class<T> type) {
-        return org.hamcrest.core.IsAnything.any(type);
-    }
-
-    /**
-     * Matches if value is null.
-     */
-    public static <T> org.hamcrest.Matcher<T> nullValue() {
-        return org.hamcrest.core.IsNull.nullValue();
-    }
-
-    /**
-     * Matches if value is null. With type inference.
-     */
-    public static <T> org.hamcrest.Matcher<T> nullValue(java.lang.Class<T> type) {
-        return org.hamcrest.core.IsNull.nullValue(type);
-    }
-
-    /**
-     * Matches if value is not null.
-     */
-    public static <T> org.hamcrest.Matcher<T> notNullValue() {
-        return org.hamcrest.core.IsNull.notNullValue();
-    }
-
-    /**
-     * Matches if value is not null. With type inference.
-     */
-    public static <T> org.hamcrest.Matcher<T> notNullValue(java.lang.Class<T> type) {
-        return org.hamcrest.core.IsNull.notNullValue(type);
-    }
-
-    /**
-     * Wraps an existing matcher and overrides the description when it fails.
-     */
-    public static <T> org.hamcrest.Matcher<T> describedAs(java.lang.String description, org.hamcrest.Matcher<T> matcher, java.lang.Object... values) {
-        return org.hamcrest.core.DescribedAs.describedAs(description, matcher, values);
-    }
-
-    public static <T> org.hamcrest.Matcher<T[]> hasItemInArray(org.hamcrest.Matcher<T> elementMatcher) {
-        return org.hamcrest.collection.IsArrayContaining.hasItemInArray(elementMatcher);
-    }
-
-    public static <T> org.hamcrest.Matcher<T[]> hasItemInArray(T element) {
-        return org.hamcrest.collection.IsArrayContaining.hasItemInArray(element);
-    }
-
-    public static <T> org.hamcrest.Matcher<java.lang.Iterable<T>> hasItem(T element) {
-        return org.hamcrest.collection.IsCollectionContaining.hasItem(element);
-    }
-
-    public static <T> org.hamcrest.Matcher<java.lang.Iterable<T>> hasItem(org.hamcrest.Matcher<? extends T> elementMatcher) {
-        return org.hamcrest.collection.IsCollectionContaining.<T>hasItem(elementMatcher);
-    }
-
-    public static <T> org.hamcrest.Matcher<java.lang.Iterable<T>> hasItems(org.hamcrest.Matcher<? extends T>... elementMatchers) {
-        return org.hamcrest.collection.IsCollectionContaining.<T>hasItems(elementMatchers);
-    }
-
-    public static <T> org.hamcrest.Matcher<java.lang.Iterable<T>> hasItems(T... elements) {
-        return org.hamcrest.collection.IsCollectionContaining.hasItems(elements);
-    }
-
-    public static <K, V> org.hamcrest.Matcher<java.util.Map<K, V>> hasEntry(org.hamcrest.Matcher<K> keyMatcher, org.hamcrest.Matcher<V> valueMatcher) {
-        return org.hamcrest.collection.IsMapContaining.hasEntry(keyMatcher, valueMatcher);
-    }
-
-    public static <K, V> org.hamcrest.Matcher<java.util.Map<K, V>> hasEntry(K key, V value) {
-        return org.hamcrest.collection.IsMapContaining.hasEntry(key, value);
-    }
-
-    public static <K, V> org.hamcrest.Matcher<java.util.Map<K, V>> hasKey(org.hamcrest.Matcher<K> keyMatcher) {
-        return org.hamcrest.collection.IsMapContaining.hasKey(keyMatcher);
-    }
-
-    public static <K, V> org.hamcrest.Matcher<java.util.Map<K, V>> hasKey(K key) {
-        return org.hamcrest.collection.IsMapContaining.hasKey(key);
-    }
-
-    public static <K, V> org.hamcrest.Matcher<java.util.Map<K, V>> hasValue(org.hamcrest.Matcher<V> valueMatcher) {
-        return org.hamcrest.collection.IsMapContaining.hasValue(valueMatcher);
-    }
-
-    public static <K, V> org.hamcrest.Matcher<java.util.Map<K, V>> hasValue(V value) {
-        return org.hamcrest.collection.IsMapContaining.hasValue(value);
-    }
-
-    public static <T> org.hamcrest.Matcher<T> isIn(java.util.Collection<T> collection) {
-        return org.hamcrest.collection.IsIn.isIn(collection);
-    }
-
-    public static <T> org.hamcrest.Matcher<T> isIn(T[] param1) {
-        return org.hamcrest.collection.IsIn.isIn(param1);
-    }
-
-    public static <T> org.hamcrest.Matcher<T> isOneOf(T... elements) {
-        return org.hamcrest.collection.IsIn.isOneOf(elements);
-    }
-
-    public static org.hamcrest.Matcher<java.lang.Double> closeTo(double operand, double error) {
-        return org.hamcrest.number.IsCloseTo.closeTo(operand, error);
-    }
-
-    public static <T extends java.lang.Comparable<T>> org.hamcrest.Matcher<T> greaterThan(T value) {
-        return org.hamcrest.number.OrderingComparisons.greaterThan(value);
-    }
-
-    public static <T extends java.lang.Comparable<T>> org.hamcrest.Matcher<T> greaterThanOrEqualTo(T value) {
-        return org.hamcrest.number.OrderingComparisons.greaterThanOrEqualTo(value);
-    }
-
-    public static <T extends java.lang.Comparable<T>> org.hamcrest.Matcher<T> lessThan(T value) {
-        return org.hamcrest.number.OrderingComparisons.lessThan(value);
-    }
-
-    public static <T extends java.lang.Comparable<T>> org.hamcrest.Matcher<T> lessThanOrEqualTo(T value) {
-        return org.hamcrest.number.OrderingComparisons.lessThanOrEqualTo(value);
-    }
-
-    public static org.hamcrest.Matcher<java.lang.String> equalToIgnoringCase(java.lang.String string) {
-        return org.hamcrest.text.IsEqualIgnoringCase.equalToIgnoringCase(string);
-    }
-
-    public static org.hamcrest.Matcher<java.lang.String> equalToIgnoringWhiteSpace(java.lang.String string) {
-        return org.hamcrest.text.IsEqualIgnoringWhiteSpace.equalToIgnoringWhiteSpace(string);
-    }
-
-    public static org.hamcrest.Matcher<java.lang.String> containsString(java.lang.String substring) {
-        return org.hamcrest.text.StringContains.containsString(substring);
-    }
-
-    public static org.hamcrest.Matcher<java.lang.String> endsWith(java.lang.String substring) {
-        return org.hamcrest.text.StringEndsWith.endsWith(substring);
-    }
-
-    public static org.hamcrest.Matcher<java.lang.String> startsWith(java.lang.String substring) {
-        return org.hamcrest.text.StringStartsWith.startsWith(substring);
-    }
-
-    public static <T> org.hamcrest.Matcher<T> hasToString(org.hamcrest.Matcher<java.lang.String> toStringMatcher) {
-        return org.hamcrest.object.HasToString.hasToString(toStringMatcher);
-    }
-
-    public static <T> org.hamcrest.Matcher<java.lang.Class<?>> typeCompatibleWith(java.lang.Class<T> baseType) {
-        return org.hamcrest.object.IsCompatibleType.typeCompatibleWith(baseType);
-    }
-
-    /**
-     * Constructs an IsEventFrom Matcher that returns true for any object
-     * derived from <var>eventClass</var> announced by <var>source</var>.
-     */
-    public static org.hamcrest.Matcher<java.util.EventObject> eventFrom(java.lang.Class<? extends java.util.EventObject> eventClass, java.lang.Object source) {
-        return org.hamcrest.object.IsEventFrom.eventFrom(eventClass, source);
-    }
-
-    /**
-     * Constructs an IsEventFrom Matcher that returns true for any object
-     * derived from {@link java.util.EventObject} announced by <var>source
-     * </var>.
-     */
-    public static org.hamcrest.Matcher<java.util.EventObject> eventFrom(java.lang.Object source) {
-        return org.hamcrest.object.IsEventFrom.eventFrom(source);
-    }
-
-    /* android-changed REMOVE
-  public static <T> org.hamcrest.Matcher<T> hasProperty(java.lang.String propertyName) {
-    return org.hamcrest.beans.HasProperty.hasProperty(propertyName);
+  /**
+   * A shortcut to the frequently used <code>is(instanceOf(SomeClass.class))</code>.
+   * For example:
+   * <pre>assertThat(cheese, isA(Cheddar.class))</pre>
+   * instead of:
+   * <pre>assertThat(cheese, is(instanceOf(Cheddar.class)))</pre>
+   */
+  public static <T> org.hamcrest.Matcher<T> isA(java.lang.Class<T> type) {
+    return org.hamcrest.core.Is.<T>isA(type);
   }
 
-  public static <T> org.hamcrest.Matcher<T> hasProperty(java.lang.String propertyName, org.hamcrest.Matcher value) {
-    return org.hamcrest.beans.HasPropertyWithValue.hasProperty(propertyName, value);
+  /**
+   * Creates a matcher that always matches, regardless of the examined object.
+   */
+  public static org.hamcrest.Matcher<java.lang.Object> anything() {
+    return org.hamcrest.core.IsAnything.anything();
   }
-     */
 
-    public static org.hamcrest.Matcher<org.w3c.dom.Node> hasXPath(java.lang.String xPath, org.hamcrest.Matcher<java.lang.String> valueMatcher) {
-        return org.hamcrest.xml.HasXPath.hasXPath(xPath, valueMatcher);
-    }
+  /**
+   * Creates a matcher that always matches, regardless of the examined object, but describes
+   * itself with the specified {@link String}.
+   * 
+   * @param description
+   *     a meaningful {@link String} used when describing itself
+   */
+  public static org.hamcrest.Matcher<java.lang.Object> anything(java.lang.String description) {
+    return org.hamcrest.core.IsAnything.anything(description);
+  }
 
-    public static org.hamcrest.Matcher<org.w3c.dom.Node> hasXPath(java.lang.String xPath) {
-        return org.hamcrest.xml.HasXPath.hasXPath(xPath);
-    }
+  /**
+   * Creates a matcher for {@link Iterable}s that only matches when a single pass over the
+   * examined {@link Iterable} yields at least one item that is matched by the specified
+   * <code>itemMatcher</code>.  Whilst matching, the traversal of the examined {@link Iterable}
+   * will stop as soon as a matching item is found.
+   * For example:
+   * <pre>assertThat(Arrays.asList("foo", "bar"), hasItem(startsWith("ba")))</pre>
+   * 
+   * @param itemMatcher
+   *     the matcher to apply to items provided by the examined {@link Iterable}
+   */
+  public static <T> org.hamcrest.Matcher<java.lang.Iterable<? super T>> hasItem(org.hamcrest.Matcher<? super T> itemMatcher) {
+    return org.hamcrest.core.IsCollectionContaining.<T>hasItem(itemMatcher);
+  }
+
+  /**
+   * Creates a matcher for {@link Iterable}s that only matches when a single pass over the
+   * examined {@link Iterable} yields at least one item that is equal to the specified
+   * <code>item</code>.  Whilst matching, the traversal of the examined {@link Iterable}
+   * will stop as soon as a matching item is found.
+   * For example:
+   * <pre>assertThat(Arrays.asList("foo", "bar"), hasItem("bar"))</pre>
+   * 
+   * @param item
+   *     the item to compare against the items provided by the examined {@link Iterable}
+   */
+  public static <T> org.hamcrest.Matcher<java.lang.Iterable<? super T>> hasItem(T item) {
+    return org.hamcrest.core.IsCollectionContaining.<T>hasItem(item);
+  }
+
+  /**
+   * Creates a matcher for {@link Iterable}s that matches when consecutive passes over the
+   * examined {@link Iterable} yield at least one item that is matched by the corresponding
+   * matcher from the specified <code>itemMatchers</code>.  Whilst matching, each traversal of
+   * the examined {@link Iterable} will stop as soon as a matching item is found.
+   * For example:
+   * <pre>assertThat(Arrays.asList("foo", "bar", "baz"), hasItems(endsWith("z"), endsWith("o")))</pre>
+   * 
+   * @param itemMatchers
+   *     the matchers to apply to items provided by the examined {@link Iterable}
+   */
+  public static <T> org.hamcrest.Matcher<java.lang.Iterable<T>> hasItems(org.hamcrest.Matcher<? super T>... itemMatchers) {
+    return org.hamcrest.core.IsCollectionContaining.<T>hasItems(itemMatchers);
+  }
+
+  /**
+   * Creates a matcher for {@link Iterable}s that matches when consecutive passes over the
+   * examined {@link Iterable} yield at least one item that is equal to the corresponding
+   * item from the specified <code>items</code>.  Whilst matching, each traversal of the
+   * examined {@link Iterable} will stop as soon as a matching item is found.
+   * For example:
+   * <pre>assertThat(Arrays.asList("foo", "bar", "baz"), hasItems("baz", "foo"))</pre>
+   * 
+   * @param items
+   *     the items to compare against the items provided by the examined {@link Iterable}
+   */
+  public static <T> org.hamcrest.Matcher<java.lang.Iterable<T>> hasItems(T... items) {
+    return org.hamcrest.core.IsCollectionContaining.<T>hasItems(items);
+  }
+
+  /**
+   * Creates a matcher that matches when the examined object is logically equal to the specified
+   * <code>operand</code>, as determined by calling the {@link java.lang.Object#equals} method on
+   * the <b>examined</b> object.
+   * 
+   * <p>If the specified operand is <code>null</code> then the created matcher will only match if
+   * the examined object's <code>equals</code> method returns <code>true</code> when passed a
+   * <code>null</code> (which would be a violation of the <code>equals</code> contract), unless the
+   * examined object itself is <code>null</code>, in which case the matcher will return a positive
+   * match.</p>
+   * 
+   * <p>The created matcher provides a special behaviour when examining <code>Array</code>s, whereby
+   * it will match if both the operand and the examined object are arrays of the same length and
+   * contain items that are equal to each other (according to the above rules) <b>in the same
+   * indexes</b>.</p> 
+   * For example:
+   * <pre>
+   * assertThat("foo", equalTo("foo"));
+   * assertThat(new String[] {"foo", "bar"}, equalTo(new String[] {"foo", "bar"}));
+   * </pre>
+   */
+  public static <T> org.hamcrest.Matcher<T> equalTo(T operand) {
+    return org.hamcrest.core.IsEqual.<T>equalTo(operand);
+  }
+
+  /**
+   * Creates an {@link org.hamcrest.core.IsEqual} matcher that does not enforce the values being
+   * compared to be of the same static type.
+   */
+  public static org.hamcrest.Matcher<java.lang.Object> equalToObject(java.lang.Object operand) {
+    return org.hamcrest.core.IsEqual.equalToObject(operand);
+  }
+
+  /**
+   * Creates a matcher that matches when the examined object is an instance of the specified <code>type</code>,
+   * as determined by calling the {@link java.lang.Class#isInstance(Object)} method on that type, passing the
+   * the examined object.
+   * 
+   * <p>The created matcher forces a relationship between specified type and the examined object, and should be
+   * used when it is necessary to make generics conform, for example in the JMock clause
+   * <code>with(any(Thing.class))</code></p>
+   * For example:
+   * <pre>assertThat(new Canoe(), instanceOf(Canoe.class));</pre>
+   */
+  public static <T> org.hamcrest.Matcher<T> any(java.lang.Class<T> type) {
+    return org.hamcrest.core.IsInstanceOf.<T>any(type);
+  }
+
+  /**
+   * Creates a matcher that matches when the examined object is an instance of the specified <code>type</code>,
+   * as determined by calling the {@link java.lang.Class#isInstance(Object)} method on that type, passing the
+   * the examined object.
+   * 
+   * <p>The created matcher assumes no relationship between specified type and the examined object.</p>
+   * For example:
+   * <pre>assertThat(new Canoe(), instanceOf(Paddlable.class));</pre>
+   */
+  public static <T> org.hamcrest.Matcher<T> instanceOf(java.lang.Class<?> type) {
+    return org.hamcrest.core.IsInstanceOf.<T>instanceOf(type);
+  }
+
+  /**
+   * Creates a matcher that wraps an existing matcher, but inverts the logic by which
+   * it will match.
+   * For example:
+   * <pre>assertThat(cheese, is(not(equalTo(smelly))))</pre>
+   * 
+   * @param matcher
+   *     the matcher whose sense should be inverted
+   */
+  public static <T> org.hamcrest.Matcher<T> not(org.hamcrest.Matcher<T> matcher) {
+    return org.hamcrest.core.IsNot.<T>not(matcher);
+  }
+
+  /**
+   * A shortcut to the frequently used <code>not(equalTo(x))</code>.
+   * For example:
+   * <pre>assertThat(cheese, is(not(smelly)))</pre>
+   * instead of:
+   * <pre>assertThat(cheese, is(not(equalTo(smelly))))</pre>
+   * 
+   * @param value
+   *     the value that any examined object should <b>not</b> equal
+   */
+  public static <T> org.hamcrest.Matcher<T> not(T value) {
+    return org.hamcrest.core.IsNot.<T>not(value);
+  }
+
+  /**
+   * A shortcut to the frequently used <code>not(nullValue())</code>.
+   * For example:
+   * <pre>assertThat(cheese, is(notNullValue()))</pre>
+   * instead of:
+   * <pre>assertThat(cheese, is(not(nullValue())))</pre>
+   */
+  public static org.hamcrest.Matcher<java.lang.Object> notNullValue() {
+    return org.hamcrest.core.IsNull.notNullValue();
+  }
+
+  /**
+   * A shortcut to the frequently used <code>not(nullValue(X.class)). Accepts a
+   * single dummy argument to facilitate type inference.</code>.
+   * For example:
+   * <pre>assertThat(cheese, is(notNullValue(X.class)))</pre>
+   * instead of:
+   * <pre>assertThat(cheese, is(not(nullValue(X.class))))</pre>
+   * 
+   * @param type
+   *     dummy parameter used to infer the generic type of the returned matcher
+   */
+  public static <T> org.hamcrest.Matcher<T> notNullValue(java.lang.Class<T> type) {
+    return org.hamcrest.core.IsNull.<T>notNullValue(type);
+  }
+
+  /**
+   * Creates a matcher that matches if examined object is <code>null</code>.
+   * For example:
+   * <pre>assertThat(cheese, is(nullValue())</pre>
+   */
+  public static org.hamcrest.Matcher<java.lang.Object> nullValue() {
+    return org.hamcrest.core.IsNull.nullValue();
+  }
+
+  /**
+   * Creates a matcher that matches if examined object is <code>null</code>. Accepts a
+   * single dummy argument to facilitate type inference.
+   * For example:
+   * <pre>assertThat(cheese, is(nullValue(Cheese.class))</pre>
+   * 
+   * @param type
+   *     dummy parameter used to infer the generic type of the returned matcher
+   */
+  public static <T> org.hamcrest.Matcher<T> nullValue(java.lang.Class<T> type) {
+    return org.hamcrest.core.IsNull.<T>nullValue(type);
+  }
+
+  /**
+   * Creates a matcher that matches only when the examined object is the same instance as
+   * the specified target object.
+   * 
+   * @param target
+   *     the target instance against which others should be assessed
+   */
+  public static <T> org.hamcrest.Matcher<T> sameInstance(T target) {
+    return org.hamcrest.core.IsSame.<T>sameInstance(target);
+  }
+
+  /**
+   * Creates a matcher that matches only when the examined object is the same instance as
+   * the specified target object.
+   * 
+   * @param target
+   *     the target instance against which others should be assessed
+   */
+  public static <T> org.hamcrest.Matcher<T> theInstance(T target) {
+    return org.hamcrest.core.IsSame.<T>theInstance(target);
+  }
+
+  /**
+   * Creates a matcher that matches if the examined {@link String} contains the specified
+   * {@link String} anywhere.
+   * For example:
+   * <pre>assertThat("myStringOfNote", containsString("ring"))</pre>
+   * 
+   * @param substring
+   *     the substring that the returned matcher will expect to find within any examined string
+   */
+  public static org.hamcrest.Matcher<java.lang.String> containsString(java.lang.String substring) {
+    return org.hamcrest.core.StringContains.containsString(substring);
+  }
+
+  /**
+   * Creates a matcher that matches if the examined {@link String} contains the specified
+   * {@link String} anywhere, ignoring case.
+   * For example:
+   * <pre>assertThat("myStringOfNote", containsString("ring"))</pre>
+   * 
+   * @param substring
+   *     the substring that the returned matcher will expect to find within any examined string
+   */
+  public static org.hamcrest.Matcher<java.lang.String> containsStringIgnoringCase(java.lang.String substring) {
+    return org.hamcrest.core.StringContains.containsStringIgnoringCase(substring);
+  }
+
+  /**
+   * <p>
+   * Creates a matcher that matches if the examined {@link String} starts with the specified
+   * {@link String}.
+   * </p>
+   * For example:
+   * <pre>assertThat("myStringOfNote", startsWith("my"))</pre>
+   * 
+   * @param prefix
+   *      the substring that the returned matcher will expect at the start of any examined string
+   */
+  public static org.hamcrest.Matcher<java.lang.String> startsWith(java.lang.String prefix) {
+    return org.hamcrest.core.StringStartsWith.startsWith(prefix);
+  }
+
+  /**
+   * <p>
+   * Creates a matcher that matches if the examined {@link String} starts with the specified
+   * {@link String}, ignoring case
+   * </p>
+   * For example:
+   * <pre>assertThat("myStringOfNote", startsWith("my"))</pre>
+   * 
+   * @param prefix
+   *      the substring that the returned matcher will expect at the start of any examined string
+   */
+  public static org.hamcrest.Matcher<java.lang.String> startsWithIgnoringCase(java.lang.String prefix) {
+    return org.hamcrest.core.StringStartsWith.startsWithIgnoringCase(prefix);
+  }
+
+  /**
+   * Creates a matcher that matches if the examined {@link String} ends with the specified
+   * {@link String}.
+   * For example:
+   * <pre>assertThat("myStringOfNote", endsWith("Note"))</pre>
+   * 
+   * @param suffix
+   *      the substring that the returned matcher will expect at the end of any examined string
+   */
+  public static org.hamcrest.Matcher<java.lang.String> endsWith(java.lang.String suffix) {
+    return org.hamcrest.core.StringEndsWith.endsWith(suffix);
+  }
+
+  /**
+   * Creates a matcher that matches if the examined {@link String} ends with the specified
+   * {@link String}, ignoring case.
+   * For example:
+   * <pre>assertThat("myStringOfNote", endsWith("Note"))</pre>
+   * 
+   * @param suffix
+   *      the substring that the returned matcher will expect at the end of any examined string
+   */
+  public static org.hamcrest.Matcher<java.lang.String> endsWithIgnoringCase(java.lang.String suffix) {
+    return org.hamcrest.core.StringEndsWith.endsWithIgnoringCase(suffix);
+  }
+
+  /**
+   * Creates a matcher that matches arrays whose elements are satisfied by the specified matchers.  Matches
+   * positively only if the number of matchers specified is equal to the length of the examined array and
+   * each matcher[i] is satisfied by array[i].
+   * For example:
+   * <pre>assertThat(new Integer[]{1,2,3}, is(array(equalTo(1), equalTo(2), equalTo(3))))</pre>
+   * 
+   * @param elementMatchers
+   *     the matchers that the elements of examined arrays should satisfy
+   */
+  public static <T> org.hamcrest.collection.IsArray<T> array(org.hamcrest.Matcher<? super T>... elementMatchers) {
+    return org.hamcrest.collection.IsArray.<T>array(elementMatchers);
+  }
+
+  /**
+   * Creates a matcher for arrays that matches when the examined array contains at least one item
+   * that is matched by the specified <code>elementMatcher</code>.  Whilst matching, the traversal
+   * of the examined array will stop as soon as a matching element is found.
+   * For example:
+   * <pre>assertThat(new String[] {"foo", "bar"}, hasItemInArray(startsWith("ba")))</pre>
+   * 
+   * @param elementMatcher
+   *     the matcher to apply to elements in examined arrays
+   */
+  public static <T> org.hamcrest.Matcher<T[]> hasItemInArray(org.hamcrest.Matcher<? super T> elementMatcher) {
+    return org.hamcrest.collection.IsArrayContaining.<T>hasItemInArray(elementMatcher);
+  }
+
+  /**
+   * A shortcut to the frequently used <code>hasItemInArray(equalTo(x))</code>.
+   * For example:
+   * <pre>assertThat(hasItemInArray(x))</pre>
+   * instead of:
+   * <pre>assertThat(hasItemInArray(equalTo(x)))</pre>
+   * 
+   * @param element
+   *     the element that should be present in examined arrays
+   */
+  public static <T> org.hamcrest.Matcher<T[]> hasItemInArray(T element) {
+    return org.hamcrest.collection.IsArrayContaining.<T>hasItemInArray(element);
+  }
+
+  /**
+   * Creates a matcher for arrays that matches when each item in the examined array is
+   * logically equal to the corresponding item in the specified items.  For a positive match,
+   * the examined array must be of the same length as the number of specified items.
+   * For example:
+   * <pre>assertThat(new String[]{"foo", "bar"}, contains("foo", "bar"))</pre>
+   * 
+   * @param items
+   *     the items that must equal the items within an examined array
+   */
+  public static <E> org.hamcrest.Matcher<E[]> arrayContaining(E... items) {
+    return org.hamcrest.collection.IsArrayContainingInOrder.<E>arrayContaining(items);
+  }
+
+  /**
+   * Creates a matcher for arrays that matches when each item in the examined array satisfies the
+   * corresponding matcher in the specified matchers.  For a positive match, the examined array
+   * must be of the same length as the number of specified matchers.
+   * For example:
+   * <pre>assertThat(new String[]{"foo", "bar"}, contains(equalTo("foo"), equalTo("bar")))</pre>
+   * 
+   * @param itemMatchers
+   *     the matchers that must be satisfied by the items in the examined array
+   */
+  public static <E> org.hamcrest.Matcher<E[]> arrayContaining(org.hamcrest.Matcher<? super E>... itemMatchers) {
+    return org.hamcrest.collection.IsArrayContainingInOrder.<E>arrayContaining(itemMatchers);
+  }
+
+  /**
+   * Creates a matcher for arrays that matches when each item in the examined array satisfies the
+   * corresponding matcher in the specified list of matchers.  For a positive match, the examined array
+   * must be of the same length as the specified list of matchers.
+   * For example:
+   * <pre>assertThat(new String[]{"foo", "bar"}, contains(Arrays.asList(equalTo("foo"), equalTo("bar"))))</pre>
+   * 
+   * @param itemMatchers
+   *     a list of matchers, each of which must be satisfied by the corresponding item in an examined array
+   */
+  public static <E> org.hamcrest.Matcher<E[]> arrayContaining(java.util.List<org.hamcrest.Matcher<? super E>> itemMatchers) {
+    return org.hamcrest.collection.IsArrayContainingInOrder.<E>arrayContaining(itemMatchers);
+  }
+
+  /**
+   * <p>
+   * Creates an order agnostic matcher for arrays that matches when each item in the
+   * examined array satisfies one matcher anywhere in the specified matchers.
+   * For a positive match, the examined array must be of the same length as the number of
+   * specified matchers.
+   * </p>
+   * <p>
+   * N.B. each of the specified matchers will only be used once during a given examination, so be
+   * careful when specifying matchers that may be satisfied by more than one entry in an examined
+   * array.
+   * </p>
+   * <p>
+   * For example:
+   * </p>
+   * <pre>assertThat(new String[]{"foo", "bar"}, arrayContainingInAnyOrder(equalTo("bar"), equalTo("foo")))</pre>
+   * 
+   * @param itemMatchers
+   *     a list of matchers, each of which must be satisfied by an entry in an examined array
+   */
+  public static <E> org.hamcrest.Matcher<E[]> arrayContainingInAnyOrder(org.hamcrest.Matcher<? super E>... itemMatchers) {
+    return org.hamcrest.collection.IsArrayContainingInAnyOrder.<E>arrayContainingInAnyOrder(itemMatchers);
+  }
+
+  /**
+   * <p>
+   * Creates an order agnostic matcher for arrays that matches when each item in the
+   * examined array satisfies one matcher anywhere in the specified collection of matchers.
+   * For a positive match, the examined array must be of the same length as the specified collection
+   * of matchers.
+   * </p>
+   * <p>
+   * N.B. each matcher in the specified collection will only be used once during a given
+   * examination, so be careful when specifying matchers that may be satisfied by more than
+   * one entry in an examined array.
+   * </p>
+   * <p>
+   * For example:
+   * </p>
+   * <pre>assertThat(new String[]{"foo", "bar"}, arrayContainingInAnyOrder(Arrays.asList(equalTo("bar"), equalTo("foo"))))</pre>
+   * 
+   * @param itemMatchers
+   *     a list of matchers, each of which must be satisfied by an item provided by an examined array
+   */
+  public static <E> org.hamcrest.Matcher<E[]> arrayContainingInAnyOrder(java.util.Collection<org.hamcrest.Matcher<? super E>> itemMatchers) {
+    return org.hamcrest.collection.IsArrayContainingInAnyOrder.<E>arrayContainingInAnyOrder(itemMatchers);
+  }
+
+  /**
+   * <p>Creates an order agnostic matcher for arrays that matches when each item in the
+   * examined array is logically equal to one item anywhere in the specified items.
+   * For a positive match, the examined array must be of the same length as the number of
+   * specified items.
+   * </p>
+   * <p>N.B. each of the specified items will only be used once during a given examination, so be
+   * careful when specifying items that may be equal to more than one entry in an examined
+   * array.
+   * </p>
+   * <p>
+   * For example:
+   * </p>
+   * <pre>assertThat(new String[]{"foo", "bar"}, containsInAnyOrder("bar", "foo"))</pre>
+   * 
+   * @param items
+   *     the items that must equal the entries of an examined array, in any order
+   */
+  public static <E> org.hamcrest.Matcher<E[]> arrayContainingInAnyOrder(E... items) {
+    return org.hamcrest.collection.IsArrayContainingInAnyOrder.<E>arrayContainingInAnyOrder(items);
+  }
+
+  /**
+   * Creates a matcher for arrays that matches when the <code>length</code> of the array
+   * satisfies the specified matcher.
+   * For example:
+   * <pre>assertThat(new String[]{"foo", "bar"}, arrayWithSize(equalTo(2)))</pre>
+   * 
+   * @param sizeMatcher
+   *     a matcher for the length of an examined array
+   */
+  public static <E> org.hamcrest.Matcher<E[]> arrayWithSize(org.hamcrest.Matcher<? super java.lang.Integer> sizeMatcher) {
+    return org.hamcrest.collection.IsArrayWithSize.<E>arrayWithSize(sizeMatcher);
+  }
+
+  /**
+   * Creates a matcher for arrays that matches when the <code>length</code> of the array
+   * equals the specified <code>size</code>.
+   * For example:
+   * <pre>assertThat(new String[]{"foo", "bar"}, arrayWithSize(2))</pre>
+   * 
+   * @param size
+   *     the length that an examined array must have for a positive match
+   */
+  public static <E> org.hamcrest.Matcher<E[]> arrayWithSize(int size) {
+    return org.hamcrest.collection.IsArrayWithSize.<E>arrayWithSize(size);
+  }
+
+  /**
+   * Creates a matcher for arrays that matches when the <code>length</code> of the array
+   * is zero.
+   * For example:
+   * <pre>assertThat(new String[0], emptyArray())</pre>
+   */
+  public static <E> org.hamcrest.Matcher<E[]> emptyArray() {
+    return org.hamcrest.collection.IsArrayWithSize.<E>emptyArray();
+  }
+
+  /**
+   * Creates a matcher for {@link java.util.Map}s that matches when the <code>size()</code> method returns
+   * a value that satisfies the specified matcher.
+   * For example:
+   * <pre>assertThat(myMap, is(aMapWithSize(equalTo(2))))</pre>
+   * 
+   * @param sizeMatcher
+   *     a matcher for the size of an examined {@link java.util.Map}
+   */
+  public static <K, V> org.hamcrest.Matcher<java.util.Map<? extends K,? extends V>> aMapWithSize(org.hamcrest.Matcher<? super java.lang.Integer> sizeMatcher) {
+    return org.hamcrest.collection.IsMapWithSize.<K,V>aMapWithSize(sizeMatcher);
+  }
+
+  /**
+   * Creates a matcher for {@link java.util.Map}s that matches when the <code>size()</code> method returns
+   * a value equal to the specified <code>size</code>.
+   * For example:
+   * <pre>assertThat(myMap, is(aMapWithSize(2)))</pre>
+   * 
+   * @param size
+   *     the expected size of an examined {@link java.util.Map}
+   */
+  public static <K, V> org.hamcrest.Matcher<java.util.Map<? extends K,? extends V>> aMapWithSize(int size) {
+    return org.hamcrest.collection.IsMapWithSize.<K,V>aMapWithSize(size);
+  }
+
+  /**
+   * Creates a matcher for {@link java.util.Map}s that matches when the <code>size()</code> method returns
+   * zero.
+   * For example:
+   * <pre>assertThat(myMap, is(anEmptyMap()))</pre>
+   */
+  public static <K, V> org.hamcrest.Matcher<java.util.Map<? extends K,? extends V>> anEmptyMap() {
+    return org.hamcrest.collection.IsMapWithSize.<K,V>anEmptyMap();
+  }
+
+  /**
+   * Creates a matcher for {@link java.util.Collection}s that matches when the <code>size()</code> method returns
+   * a value that satisfies the specified matcher.
+   * For example:
+   * <pre>assertThat(Arrays.asList("foo", "bar"), hasSize(equalTo(2)))</pre>
+   * 
+   * @param sizeMatcher
+   *     a matcher for the size of an examined {@link java.util.Collection}
+   */
+  public static <E> org.hamcrest.Matcher<java.util.Collection<? extends E>> hasSize(org.hamcrest.Matcher<? super java.lang.Integer> sizeMatcher) {
+    return org.hamcrest.collection.IsCollectionWithSize.<E>hasSize(sizeMatcher);
+  }
+
+  /**
+   * Creates a matcher for {@link java.util.Collection}s that matches when the <code>size()</code> method returns
+   * a value equal to the specified <code>size</code>.
+   * For example:
+   * <pre>assertThat(Arrays.asList("foo", "bar"), hasSize(2))</pre>
+   * 
+   * @param size
+   *     the expected size of an examined {@link java.util.Collection}
+   */
+  public static <E> org.hamcrest.Matcher<java.util.Collection<? extends E>> hasSize(int size) {
+    return org.hamcrest.collection.IsCollectionWithSize.<E>hasSize(size);
+  }
+
+  /**
+   * Creates a matcher for {@link java.util.Collection}s matching examined collections whose <code>isEmpty</code>
+   * method returns <code>true</code>.
+   * For example:
+   * <pre>assertThat(new ArrayList&lt;String&gt;(), is(empty()))</pre>
+   */
+  public static <E> org.hamcrest.Matcher<java.util.Collection<? extends E>> empty() {
+    return org.hamcrest.collection.IsEmptyCollection.<E>empty();
+  }
+
+  /**
+   * Creates a matcher for {@link java.util.Collection}s matching examined collections whose <code>isEmpty</code>
+   * method returns <code>true</code>.
+   * For example:
+   * <pre>assertThat(new ArrayList&lt;String&gt;(), is(emptyCollectionOf(String.class)))</pre>
+   * 
+   * @param unusedToForceReturnType
+   *     the type of the collection's content
+   */
+  public static <E> org.hamcrest.Matcher<java.util.Collection<E>> emptyCollectionOf(java.lang.Class<E> unusedToForceReturnType) {
+    return org.hamcrest.collection.IsEmptyCollection.<E>emptyCollectionOf(unusedToForceReturnType);
+  }
+
+  /**
+   * Creates a matcher for {@link Iterable}s matching examined iterables that yield no items.
+   * For example:
+   * <pre>assertThat(new ArrayList&lt;String&gt;(), is(emptyIterable()))</pre>
+   */
+  public static <E> org.hamcrest.Matcher<java.lang.Iterable<? extends E>> emptyIterable() {
+    return org.hamcrest.collection.IsEmptyIterable.<E>emptyIterable();
+  }
+
+  /**
+   * Creates a matcher for {@link Iterable}s matching examined iterables that yield no items.
+   * For example:
+   * <pre>assertThat(new ArrayList&lt;String&gt;(), is(emptyIterableOf(String.class)))</pre>
+   * 
+   * @param unusedToForceReturnType
+   *     the type of the iterable's content
+   */
+  public static <E> org.hamcrest.Matcher<java.lang.Iterable<E>> emptyIterableOf(java.lang.Class<E> unusedToForceReturnType) {
+    return org.hamcrest.collection.IsEmptyIterable.<E>emptyIterableOf(unusedToForceReturnType);
+  }
+
+  /**
+   * Creates a matcher for {@link Iterable}s that matches when a single pass over the
+   * examined {@link Iterable} yields a series of items, each logically equal to the
+   * corresponding item in the specified items.  For a positive match, the examined iterable
+   * must be of the same length as the number of specified items.
+   * For example:
+   * <pre>assertThat(Arrays.asList("foo", "bar"), contains("foo", "bar"))</pre>
+   * 
+   * @param items
+   *     the items that must equal the items provided by an examined {@link Iterable}
+   */
+  public static <E> org.hamcrest.Matcher<java.lang.Iterable<? extends E>> contains(E... items) {
+    return org.hamcrest.collection.IsIterableContainingInOrder.<E>contains(items);
+  }
+
+  /**
+   * Creates a matcher for {@link Iterable}s that matches when a single pass over the
+   * examined {@link Iterable} yields a single item that satisfies the specified matcher.
+   * For a positive match, the examined iterable must only yield one item.
+   * For example:
+   * <pre>assertThat(Arrays.asList("foo"), contains(equalTo("foo")))</pre>
+   * 
+   * @param itemMatcher
+   *     the matcher that must be satisfied by the single item provided by an
+   *     examined {@link Iterable}
+   */
+  public static <E> org.hamcrest.Matcher<java.lang.Iterable<? extends E>> contains(org.hamcrest.Matcher<? super E> itemMatcher) {
+    return org.hamcrest.collection.IsIterableContainingInOrder.<E>contains(itemMatcher);
+  }
+
+  /**
+   * Creates a matcher for {@link Iterable}s that matches when a single pass over the
+   * examined {@link Iterable} yields a series of items, each satisfying the corresponding
+   * matcher in the specified matchers.  For a positive match, the examined iterable
+   * must be of the same length as the number of specified matchers.
+   * For example:
+   * <pre>assertThat(Arrays.asList("foo", "bar"), contains(equalTo("foo"), equalTo("bar")))</pre>
+   * 
+   * @param itemMatchers
+   *     the matchers that must be satisfied by the items provided by an examined {@link Iterable}
+   */
+  public static <E> org.hamcrest.Matcher<java.lang.Iterable<? extends E>> contains(org.hamcrest.Matcher<? super E>... itemMatchers) {
+    return org.hamcrest.collection.IsIterableContainingInOrder.<E>contains(itemMatchers);
+  }
+
+  /**
+   * Creates a matcher for {@link Iterable}s that matches when a single pass over the
+   * examined {@link Iterable} yields a series of items, each satisfying the corresponding
+   * matcher in the specified list of matchers.  For a positive match, the examined iterable
+   * must be of the same length as the specified list of matchers.
+   * For example:
+   * <pre>assertThat(Arrays.asList("foo", "bar"), contains(Arrays.asList(equalTo("foo"), equalTo("bar"))))</pre>
+   * 
+   * @param itemMatchers
+   *     a list of matchers, each of which must be satisfied by the corresponding item provided by
+   *     an examined {@link Iterable}
+   */
+  public static <E> org.hamcrest.Matcher<java.lang.Iterable<? extends E>> contains(java.util.List<org.hamcrest.Matcher<? super E>> itemMatchers) {
+    return org.hamcrest.collection.IsIterableContainingInOrder.<E>contains(itemMatchers);
+  }
+
+  /**
+   * <p>
+   * Creates an order agnostic matcher for {@link Iterable}s that matches when a single pass over
+   * the examined {@link Iterable} yields a series of items, each satisfying one matcher anywhere
+   * in the specified matchers.  For a positive match, the examined iterable must be of the same
+   * length as the number of specified matchers.
+   * </p>
+   * <p>
+   * N.B. each of the specified matchers will only be used once during a given examination, so be
+   * careful when specifying matchers that may be satisfied by more than one entry in an examined
+   * iterable.
+   * </p>
+   * <p>
+   * For example:
+   * </p>
+   * <pre>assertThat(Arrays.asList("foo", "bar"), containsInAnyOrder(equalTo("bar"), equalTo("foo")))</pre>
+   * 
+   * @param itemMatchers
+   *     a list of matchers, each of which must be satisfied by an item provided by an examined {@link Iterable}
+   */
+  public static <T> org.hamcrest.Matcher<java.lang.Iterable<? extends T>> containsInAnyOrder(org.hamcrest.Matcher<? super T>... itemMatchers) {
+    return org.hamcrest.collection.IsIterableContainingInAnyOrder.<T>containsInAnyOrder(itemMatchers);
+  }
+
+  /**
+   * <p>
+   * Creates an order agnostic matcher for {@link Iterable}s that matches when a single pass over
+   * the examined {@link Iterable} yields a series of items, each logically equal to one item
+   * anywhere in the specified items. For a positive match, the examined iterable
+   * must be of the same length as the number of specified items.
+   * </p>
+   * <p>
+   * N.B. each of the specified items will only be used once during a given examination, so be
+   * careful when specifying items that may be equal to more than one entry in an examined
+   * iterable.
+   * </p>
+   * <p>
+   * For example:
+   * </p>
+   * <pre>assertThat(Arrays.asList("foo", "bar"), containsInAnyOrder("bar", "foo"))</pre>
+   * 
+   * @param items
+   *     the items that must equal the items provided by an examined {@link Iterable} in any order
+   */
+  public static <T> org.hamcrest.Matcher<java.lang.Iterable<? extends T>> containsInAnyOrder(T... items) {
+    return org.hamcrest.collection.IsIterableContainingInAnyOrder.<T>containsInAnyOrder(items);
+  }
+
+  /**
+   * <p>
+   * Creates an order agnostic matcher for {@link Iterable}s that matches when a single pass over
+   * the examined {@link Iterable} yields a series of items, each satisfying one matcher anywhere
+   * in the specified collection of matchers.  For a positive match, the examined iterable
+   * must be of the same length as the specified collection of matchers.
+   * </p>
+   * <p>
+   * N.B. each matcher in the specified collection will only be used once during a given
+   * examination, so be careful when specifying matchers that may be satisfied by more than
+   * one entry in an examined iterable.
+   * </p>
+   * <p>For example:</p>
+   * <pre>assertThat(Arrays.asList("foo", "bar"), containsInAnyOrder(Arrays.asList(equalTo("bar"), equalTo("foo"))))</pre>
+   * 
+   * @param itemMatchers
+   *     a list of matchers, each of which must be satisfied by an item provided by an examined {@link Iterable}
+   */
+  public static <T> org.hamcrest.Matcher<java.lang.Iterable<? extends T>> containsInAnyOrder(java.util.Collection<org.hamcrest.Matcher<? super T>> itemMatchers) {
+    return org.hamcrest.collection.IsIterableContainingInAnyOrder.<T>containsInAnyOrder(itemMatchers);
+  }
+
+  /**
+   * Creates a matcher for {@link Iterable}s that matches when a single pass over the
+   * examined {@link Iterable} yields a series of items, that contains items logically equal to the
+   * corresponding item in the specified items, in the same relative order
+   * For example:
+   * <pre>assertThat(Arrays.asList("a", "b", "c", "d", "e"), containsInRelativeOrder("b", "d"))</pre>
+   * 
+   * @param items
+   *     the items that must be contained within items provided by an examined {@link Iterable} in the same relative order
+   */
+  public static <E> org.hamcrest.Matcher<java.lang.Iterable<? extends E>> containsInRelativeOrder(E... items) {
+    return org.hamcrest.collection.IsIterableContainingInRelativeOrder.<E>containsInRelativeOrder(items);
+  }
+
+  /**
+   * Creates a matcher for {@link Iterable}s that matches when a single pass over the
+   * examined {@link Iterable} yields a series of items, that each satisfying the corresponding
+   * matcher in the specified matchers, in the same relative order.
+   * For example:
+   * <pre>assertThat(Arrays.asList("a", "b", "c", "d", "e"), containsInRelativeOrder(equalTo("b"), equalTo("d")))</pre>
+   * 
+   * @param itemMatchers
+   *     the matchers that must be satisfied by the items provided by an examined {@link Iterable} in the same relative order
+   */
+  public static <E> org.hamcrest.Matcher<java.lang.Iterable<? extends E>> containsInRelativeOrder(org.hamcrest.Matcher<? super E>... itemMatchers) {
+    return org.hamcrest.collection.IsIterableContainingInRelativeOrder.<E>containsInRelativeOrder(itemMatchers);
+  }
+
+  /**
+   * Creates a matcher for {@link Iterable}s that matches when a single pass over the
+   * examined {@link Iterable} yields a series of items, that contains items satisfying the corresponding
+   * matcher in the specified list of matchers, in the same relative order.
+   * For example:
+   * <pre>assertThat(Arrays.asList("a", "b", "c", "d", "e"), contains(Arrays.asList(equalTo("b"), equalTo("d"))))</pre>
+   * 
+   * @param itemMatchers
+   *     a list of matchers, each of which must be satisfied by the items provided by
+   *     an examined {@link Iterable} in the same relative order
+   */
+  public static <E> org.hamcrest.Matcher<java.lang.Iterable<? extends E>> containsInRelativeOrder(java.util.List<org.hamcrest.Matcher<? super E>> itemMatchers) {
+    return org.hamcrest.collection.IsIterableContainingInRelativeOrder.<E>containsInRelativeOrder(itemMatchers);
+  }
+
+  /**
+   * Creates a matcher for {@link Iterable}s that matches when a single pass over the
+   * examined {@link Iterable} yields an item count that satisfies the specified
+   * matcher.
+   * For example:
+   * <pre>assertThat(Arrays.asList("foo", "bar"), iterableWithSize(equalTo(2)))</pre>
+   * 
+   * @param sizeMatcher
+   *     a matcher for the number of items that should be yielded by an examined {@link Iterable}
+   */
+  public static <E> org.hamcrest.Matcher<java.lang.Iterable<E>> iterableWithSize(org.hamcrest.Matcher<? super java.lang.Integer> sizeMatcher) {
+    return org.hamcrest.collection.IsIterableWithSize.<E>iterableWithSize(sizeMatcher);
+  }
+
+  /**
+   * Creates a matcher for {@link Iterable}s that matches when a single pass over the
+   * examined {@link Iterable} yields an item count that is equal to the specified
+   * <code>size</code> argument.
+   * For example:
+   * <pre>assertThat(Arrays.asList("foo", "bar"), iterableWithSize(2))</pre>
+   * 
+   * @param size
+   *     the number of items that should be yielded by an examined {@link Iterable}
+   */
+  public static <E> org.hamcrest.Matcher<java.lang.Iterable<E>> iterableWithSize(int size) {
+    return org.hamcrest.collection.IsIterableWithSize.<E>iterableWithSize(size);
+  }
+
+  /**
+   * Creates a matcher for {@link java.util.Map}s matching when the examined {@link java.util.Map} contains
+   * at least one entry whose key satisfies the specified <code>keyMatcher</code> <b>and</b> whose
+   * value satisfies the specified <code>valueMatcher</code>.
+   * For example:
+   * <pre>assertThat(myMap, hasEntry(equalTo("bar"), equalTo("foo")))</pre>
+   * 
+   * @param keyMatcher
+   *     the key matcher that, in combination with the valueMatcher, must be satisfied by at least one entry
+   * @param valueMatcher
+   *     the value matcher that, in combination with the keyMatcher, must be satisfied by at least one entry
+   */
+  public static <K, V> org.hamcrest.Matcher<java.util.Map<? extends K,? extends V>> hasEntry(org.hamcrest.Matcher<? super K> keyMatcher, org.hamcrest.Matcher<? super V> valueMatcher) {
+    return org.hamcrest.collection.IsMapContaining.<K,V>hasEntry(keyMatcher, valueMatcher);
+  }
+
+  /**
+   * Creates a matcher for {@link java.util.Map}s matching when the examined {@link java.util.Map} contains
+   * at least one entry whose key equals the specified <code>key</code> <b>and</b> whose value equals the
+   * specified <code>value</code>.
+   * For example:
+   * <pre>assertThat(myMap, hasEntry("bar", "foo"))</pre>
+   * 
+   * @param key
+   *     the key that, in combination with the value, must be describe at least one entry
+   * @param value
+   *     the value that, in combination with the key, must be describe at least one entry
+   */
+  public static <K, V> org.hamcrest.Matcher<java.util.Map<? extends K,? extends V>> hasEntry(K key, V value) {
+    return org.hamcrest.collection.IsMapContaining.<K,V>hasEntry(key, value);
+  }
+
+  /**
+   * Creates a matcher for {@link java.util.Map}s matching when the examined {@link java.util.Map} contains
+   * at least one key that satisfies the specified matcher.
+   * For example:
+   * <pre>assertThat(myMap, hasKey(equalTo("bar")))</pre>
+   * 
+   * @param keyMatcher
+   *     the matcher that must be satisfied by at least one key
+   */
+  public static <K> org.hamcrest.Matcher<java.util.Map<? extends K,?>> hasKey(org.hamcrest.Matcher<? super K> keyMatcher) {
+    return org.hamcrest.collection.IsMapContaining.<K>hasKey(keyMatcher);
+  }
+
+  /**
+   * Creates a matcher for {@link java.util.Map}s matching when the examined {@link java.util.Map} contains
+   * at least one key that is equal to the specified key.
+   * For example:
+   * <pre>assertThat(myMap, hasKey("bar"))</pre>
+   * 
+   * @param key
+   *     the key that satisfying maps must contain
+   */
+  public static <K> org.hamcrest.Matcher<java.util.Map<? extends K,?>> hasKey(K key) {
+    return org.hamcrest.collection.IsMapContaining.<K>hasKey(key);
+  }
+
+  /**
+   * Creates a matcher for {@link java.util.Map}s matching when the examined {@link java.util.Map} contains
+   * at least one value that satisfies the specified valueMatcher.
+   * For example:
+   * <pre>assertThat(myMap, hasValue(equalTo("foo")))</pre>
+   * 
+   * @param valueMatcher
+   *     the matcher that must be satisfied by at least one value
+   */
+  public static <V> org.hamcrest.Matcher<java.util.Map<?,? extends V>> hasValue(org.hamcrest.Matcher<? super V> valueMatcher) {
+    return org.hamcrest.collection.IsMapContaining.<V>hasValue(valueMatcher);
+  }
+
+  /**
+   * Creates a matcher for {@link java.util.Map}s matching when the examined {@link java.util.Map} contains
+   * at least one value that is equal to the specified value.
+   * For example:
+   * <pre>assertThat(myMap, hasValue("foo"))</pre>
+   * 
+   * @param value
+   *     the value that satisfying maps must contain
+   */
+  public static <V> org.hamcrest.Matcher<java.util.Map<?,? extends V>> hasValue(V value) {
+    return org.hamcrest.collection.IsMapContaining.<V>hasValue(value);
+  }
+
+  /**
+   * Creates a matcher that matches when the examined object is found within the
+   * specified collection.
+   * For example:
+   * <pre>assertThat("foo", is(in(Arrays.asList("bar", "foo"))))</pre>
+   * 
+   * @param collection
+   *     the collection in which matching items must be found
+   */
+  public static <T> org.hamcrest.Matcher<T> in(java.util.Collection<T> collection) {
+    return org.hamcrest.collection.IsIn.<T>in(collection);
+  }
+
+  /**
+   * Creates a matcher that matches when the examined object is found within the
+   * specified array.
+   * For example:
+   * <pre>assertThat("foo", is(in(new String[]{"bar", "foo"})))</pre>
+   * 
+   * @param elements
+   *     the array in which matching items must be found
+   */
+  public static <T> org.hamcrest.Matcher<T> in(T[] elements) {
+    return org.hamcrest.collection.IsIn.<T>in(elements);
+  }
+
+  /**
+   * Creates a matcher that matches when the examined object is found within the
+   * specified collection.
+   * For example:
+   * <pre>assertThat("foo", isIn(Arrays.asList("bar", "foo")))</pre>
+   * 
+   * @deprecated use is(in(...)) instead
+   * @param collection
+   *     the collection in which matching items must be found
+   */
+  public static <T> org.hamcrest.Matcher<T> isIn(java.util.Collection<T> collection) {
+    return org.hamcrest.collection.IsIn.<T>isIn(collection);
+  }
+
+  /**
+   * Creates a matcher that matches when the examined object is found within the
+   * specified array.
+   * For example:
+   * <pre>assertThat("foo", isIn(new String[]{"bar", "foo"}))</pre>
+   * 
+   * @deprecated use is(in(...)) instead
+   * @param elements
+   *     the array in which matching items must be found
+   */
+  public static <T> org.hamcrest.Matcher<T> isIn(T[] elements) {
+    return org.hamcrest.collection.IsIn.<T>isIn(elements);
+  }
+
+  /**
+   * Creates a matcher that matches when the examined object is equal to one of the
+   * specified elements.
+   * For example:
+   * <pre>assertThat("foo", isOneOf("bar", "foo"))</pre>
+   * 
+   * @deprecated use is(oneOf(...)) instead
+   * @param elements
+   *     the elements amongst which matching items will be found
+   */
+  public static <T> org.hamcrest.Matcher<T> isOneOf(T... elements) {
+    return org.hamcrest.collection.IsIn.<T>isOneOf(elements);
+  }
+
+  /**
+   * Creates a matcher that matches when the examined object is equal to one of the
+   * specified elements.
+   * For example:
+   * <pre>assertThat("foo", is(oneOf("bar", "foo")))</pre>
+   * 
+   * @param elements
+   *     the elements amongst which matching items will be found
+   */
+  public static <T> org.hamcrest.Matcher<T> oneOf(T... elements) {
+    return org.hamcrest.collection.IsIn.<T>oneOf(elements);
+  }
+
+  /**
+   * Creates a matcher of {@link Double}s that matches when an examined double is equal
+   * to the specified <code>operand</code>, within a range of +/- <code>error</code>.
+   * For example:
+   * <pre>assertThat(1.03, is(closeTo(1.0, 0.03)))</pre>
+   * 
+   * @param operand
+   *     the expected value of matching doubles
+   * @param error
+   *     the delta (+/-) within which matches will be allowed
+   */
+  public static org.hamcrest.Matcher<java.lang.Double> closeTo(double operand, double error) {
+    return org.hamcrest.number.IsCloseTo.closeTo(operand, error);
+  }
+
+  /**
+   * Creates a matcher of {@link Double}s that matches when an examined double is not a number.
+   * For example:
+   * <pre>assertThat(Double.NaN, is(notANumber()))</pre>
+   */
+  public static org.hamcrest.Matcher<java.lang.Double> notANumber() {
+    return org.hamcrest.number.IsNaN.notANumber();
+  }
+
+  /**
+   * Creates a matcher of {@link java.math.BigDecimal}s that matches when an examined BigDecimal is equal
+   * to the specified <code>operand</code>, within a range of +/- <code>error</code>. The comparison for equality
+   * is done by BigDecimals {@link java.math.BigDecimal#compareTo(java.math.BigDecimal)} method.
+   * For example:
+   * <pre>assertThat(new BigDecimal("1.03"), is(closeTo(new BigDecimal("1.0"), new BigDecimal("0.03"))))</pre>
+   * 
+   * @param operand
+   *     the expected value of matching BigDecimals
+   * @param error
+   *     the delta (+/-) within which matches will be allowed
+   */
+  public static org.hamcrest.Matcher<java.math.BigDecimal> closeTo(java.math.BigDecimal operand, java.math.BigDecimal error) {
+    return org.hamcrest.number.BigDecimalCloseTo.closeTo(operand, error);
+  }
+
+  /**
+   * Creates a matcher of {@link Comparable} object that matches when the examined object is
+   * equal to the specified value, as reported by the <code>compareTo</code> method of the
+   * <b>examined</b> object.
+   * For example:
+   * <pre>assertThat(1, comparesEqualTo(1))</pre>
+   * 
+   * @param value the value which, when passed to the compareTo method of the examined object, should return zero
+   */
+  public static <T extends java.lang.Comparable<T>> org.hamcrest.Matcher<T> comparesEqualTo(T value) {
+    return org.hamcrest.number.OrderingComparison.<T>comparesEqualTo(value);
+  }
+
+  /**
+   * Creates a matcher of {@link Comparable} object that matches when the examined object is
+   * greater than the specified value, as reported by the <code>compareTo</code> method of the
+   * <b>examined</b> object.
+   * For example:
+   * <pre>assertThat(2, greaterThan(1))</pre>
+   * 
+   * @param value the value which, when passed to the compareTo method of the examined object, should return greater
+   *              than zero
+   */
+  public static <T extends java.lang.Comparable<T>> org.hamcrest.Matcher<T> greaterThan(T value) {
+    return org.hamcrest.number.OrderingComparison.<T>greaterThan(value);
+  }
+
+  /**
+   * Creates a matcher of {@link Comparable} object that matches when the examined object is
+   * greater than or equal to the specified value, as reported by the <code>compareTo</code> method
+   * of the <b>examined</b> object.
+   * For example:
+   * <pre>assertThat(1, greaterThanOrEqualTo(1))</pre>
+   * 
+   * @param value the value which, when passed to the compareTo method of the examined object, should return greater
+   *              than or equal to zero
+   */
+  public static <T extends java.lang.Comparable<T>> org.hamcrest.Matcher<T> greaterThanOrEqualTo(T value) {
+    return org.hamcrest.number.OrderingComparison.<T>greaterThanOrEqualTo(value);
+  }
+
+  /**
+   * Creates a matcher of {@link Comparable} object that matches when the examined object is
+   * less than the specified value, as reported by the <code>compareTo</code> method of the
+   * <b>examined</b> object.
+   * For example:
+   * <pre>assertThat(1, lessThan(2))</pre>
+   * 
+   * @param value the value which, when passed to the compareTo method of the examined object, should return less
+   *              than zero
+   */
+  public static <T extends java.lang.Comparable<T>> org.hamcrest.Matcher<T> lessThan(T value) {
+    return org.hamcrest.number.OrderingComparison.<T>lessThan(value);
+  }
+
+  /**
+   * Creates a matcher of {@link Comparable} object that matches when the examined object is
+   * less than or equal to the specified value, as reported by the <code>compareTo</code> method
+   * of the <b>examined</b> object.
+   * For example:
+   * <pre>assertThat(1, lessThanOrEqualTo(1))</pre>
+   * 
+   * @param value the value which, when passed to the compareTo method of the examined object, should return less
+   *              than or equal to zero
+   */
+  public static <T extends java.lang.Comparable<T>> org.hamcrest.Matcher<T> lessThanOrEqualTo(T value) {
+    return org.hamcrest.number.OrderingComparison.<T>lessThanOrEqualTo(value);
+  }
+
+  /**
+   * Creates a matcher of {@link String} that matches when the examined string is equal to
+   * the specified expectedString, ignoring case.
+   * For example:
+   * <pre>assertThat("Foo", equalToIgnoringCase("FOO"))</pre>
+   * 
+   * @param expectedString
+   *     the expected value of matched strings
+   */
+  public static org.hamcrest.Matcher<java.lang.String> equalToIgnoringCase(java.lang.String expectedString) {
+    return org.hamcrest.text.IsEqualIgnoringCase.equalToIgnoringCase(expectedString);
+  }
+
+  /**
+   * Creates a matcher of {@link String} that matches when the examined string is equal to
+   * the specified expectedString, when whitespace differences are (mostly) ignored.  To be
+   * exact, the following whitespace rules are applied:
+   * <ul>
+   *   <li>all leading and trailing whitespace of both the expectedString and the examined string are ignored</li>
+   *   <li>any remaining whitespace, appearing within either string, is collapsed to a single space before comparison</li>
+   * </ul>
+   * For example:
+   * <pre>assertThat("   my\tfoo  bar ", equalToIgnoringWhiteSpace(" my  foo bar"))</pre>
+   * 
+   * @param expectedString
+   *     the expected value of matched strings
+   */
+  public static org.hamcrest.Matcher<java.lang.String> equalToIgnoringWhiteSpace(java.lang.String expectedString) {
+    return org.hamcrest.text.IsEqualIgnoringWhiteSpace.equalToIgnoringWhiteSpace(expectedString);
+  }
+
+  /**
+   * Creates a matcher of {@link String} that matches when the examined string is <code>null</code>, or
+   * has zero length.
+   * For example:
+   * <pre>assertThat(((String)null), is(emptyOrNullString()))</pre>
+   */
+  public static org.hamcrest.Matcher<java.lang.String> emptyOrNullString() {
+    return org.hamcrest.text.IsEmptyString.emptyOrNullString();
+  }
+
+  /**
+   * Creates a matcher of {@link String} that matches when the examined string has zero length.
+   * For example:
+   * <pre>assertThat("", is(emptyString()))</pre>
+   */
+  public static org.hamcrest.Matcher<java.lang.String> emptyString() {
+    return org.hamcrest.text.IsEmptyString.emptyString();
+  }
+
+  /**
+   * Creates a matcher of {@link String} that matches when the examined string is <code>null</code>, or
+   * has zero length.
+   * For example:
+   * <pre>assertThat(((String)null), isEmptyOrNullString())</pre>
+   * 
+   * @deprecated use is(emptyOrNullString()) instead
+   */
+  public static org.hamcrest.Matcher<java.lang.String> isEmptyOrNullString() {
+    return org.hamcrest.text.IsEmptyString.isEmptyOrNullString();
+  }
+
+  /**
+   * Creates a matcher of {@link String} that matches when the examined string has zero length.
+   * For example:
+   * <pre>assertThat("", isEmptyString())</pre>
+   * 
+   * @deprecated use is(emptyString()) instead
+   */
+  public static org.hamcrest.Matcher<java.lang.String> isEmptyString() {
+    return org.hamcrest.text.IsEmptyString.isEmptyString();
+  }
+
+  /**
+   * Creates a matcher of {@link String} that matches when the examined string is <code>null</code>, or
+   * contains zero or more whitespace characters and nothing else.
+   * For example:
+   * <pre>assertThat(((String)null), is(blankOrNullString()))</pre>
+   */
+  public static org.hamcrest.Matcher<java.lang.String> blankOrNullString() {
+    return org.hamcrest.text.IsBlankString.blankOrNullString();
+  }
+
+  /**
+   * Creates a matcher of {@link String} that matches when the examined string contains
+   * zero or more whitespace characters and nothing else.
+   * For example:
+   * <pre>assertThat("  ", is(blankString()))</pre>
+   */
+  public static org.hamcrest.Matcher<java.lang.String> blankString() {
+    return org.hamcrest.text.IsBlankString.blankString();
+  }
+
+  /**
+   * Creates a matcher of {@link java.lang.String} that matches when the examined string
+   * exactly matches the given {@link java.util.regex.Pattern}.
+   */
+  public static org.hamcrest.Matcher<java.lang.String> matchesPattern(java.util.regex.Pattern pattern) {
+    return org.hamcrest.text.MatchesPattern.matchesPattern(pattern);
+  }
+
+  /**
+   * Creates a matcher of {@link java.lang.String} that matches when the examined string
+   * exactly matches the given regular expression, treated as a {@link java.util.regex.Pattern}.
+   */
+  public static org.hamcrest.Matcher<java.lang.String> matchesPattern(java.lang.String regex) {
+    return org.hamcrest.text.MatchesPattern.matchesPattern(regex);
+  }
+
+  /**
+   * Creates a matcher of {@link String} that matches when the examined string contains all of
+   * the specified substrings, considering the order of their appearance.
+   * For example:
+   * <pre>assertThat("myfoobarbaz", stringContainsInOrder(Arrays.asList("bar", "foo")))</pre>
+   * fails as "foo" occurs before "bar" in the string "myfoobarbaz"
+   * 
+   * @param substrings
+   *     the substrings that must be contained within matching strings
+   */
+  public static org.hamcrest.Matcher<java.lang.String> stringContainsInOrder(java.lang.Iterable<java.lang.String> substrings) {
+    return org.hamcrest.text.StringContainsInOrder.stringContainsInOrder(substrings);
+  }
+
+  /**
+   * Creates a matcher of {@link String} that matches when the examined string contains all of
+   * the specified substrings, considering the order of their appearance.
+   * For example:
+   * <pre>assertThat("myfoobarbaz", stringContainsInOrder("bar", "foo"))</pre>
+   * fails as "foo" occurs before "bar" in the string "myfoobarbaz"
+   * 
+   * @param substrings
+   *     the substrings that must be contained within matching strings
+   */
+  public static org.hamcrest.Matcher<java.lang.String> stringContainsInOrder(java.lang.String... substrings) {
+    return org.hamcrest.text.StringContainsInOrder.stringContainsInOrder(substrings);
+  }
+
+  /**
+   * Creates a matcher that matches any examined object whose <code>toString</code> method
+   * returns a value that satisfies the specified matcher.
+   * For example:
+   * <pre>assertThat(true, hasToString(equalTo("TRUE")))</pre>
+   * 
+   * @param toStringMatcher
+   *     the matcher used to verify the toString result
+   */
+  public static <T> org.hamcrest.Matcher<T> hasToString(org.hamcrest.Matcher<? super java.lang.String> toStringMatcher) {
+    return org.hamcrest.object.HasToString.<T>hasToString(toStringMatcher);
+  }
+
+  /**
+   * Creates a matcher that matches any examined object whose <code>toString</code> method
+   * returns a value equalTo the specified string.
+   * For example:
+   * <pre>assertThat(true, hasToString("TRUE"))</pre>
+   * 
+   * @param expectedToString
+   *     the expected toString result
+   */
+  public static <T> org.hamcrest.Matcher<T> hasToString(java.lang.String expectedToString) {
+    return org.hamcrest.object.HasToString.<T>hasToString(expectedToString);
+  }
+
+  /**
+   * Creates a matcher of {@link Class} that matches when the specified baseType is
+   * assignable from the examined class.
+   * For example:
+   * <pre>assertThat(Integer.class, typeCompatibleWith(Number.class))</pre>
+   * 
+   * @param baseType
+   *     the base class to examine classes against
+   */
+  public static <T> org.hamcrest.Matcher<java.lang.Class<?>> typeCompatibleWith(java.lang.Class<T> baseType) {
+    return org.hamcrest.object.IsCompatibleType.<T>typeCompatibleWith(baseType);
+  }
+
+  /**
+   * Creates a matcher of {@link java.util.EventObject} that matches any object
+   * derived from <var>eventClass</var> announced by <var>source</var>.
+   * For example:
+   * <pre>assertThat(myEvent, is(eventFrom(PropertyChangeEvent.class, myBean)))</pre>
+   * 
+   * @param eventClass
+   *     the class of the event to match on
+   * @param source
+   *     the source of the event
+   */
+  public static org.hamcrest.Matcher<java.util.EventObject> eventFrom(java.lang.Class<? extends java.util.EventObject> eventClass, java.lang.Object source) {
+    return org.hamcrest.object.IsEventFrom.eventFrom(eventClass, source);
+  }
+
+  /**
+   * Creates a matcher of {@link java.util.EventObject} that matches any EventObject
+   * announced by <var>source</var>.
+   * For example:
+   * <pre>assertThat(myEvent, is(eventFrom(myBean)))</pre>
+   * 
+   * @param source
+   *     the source of the event
+   */
+  public static org.hamcrest.Matcher<java.util.EventObject> eventFrom(java.lang.Object source) {
+    return org.hamcrest.object.IsEventFrom.eventFrom(source);
+  }
+
+  /**
+   * Creates a matcher of {@link org.w3c.dom.Node}s that matches when the examined node has a value at the
+   * specified <code>xPath</code> that satisfies the specified <code>valueMatcher</code>.
+   * For example:
+   * <pre>assertThat(xml, hasXPath("/root/something[2]/cheese", equalTo("Cheddar")))</pre>
+   * 
+   * @param xPath
+   *     the target xpath
+   * @param valueMatcher
+   *     matcher for the value at the specified xpath
+   */
+  public static org.hamcrest.Matcher<org.w3c.dom.Node> hasXPath(java.lang.String xPath, org.hamcrest.Matcher<java.lang.String> valueMatcher) {
+    return org.hamcrest.xml.HasXPath.hasXPath(xPath, valueMatcher);
+  }
+
+  /**
+   * Creates a matcher of {@link org.w3c.dom.Node}s that matches when the examined node has a value at the
+   * specified <code>xPath</code>, within the specified <code>namespaceContext</code>, that satisfies
+   * the specified <code>valueMatcher</code>.
+   * For example:
+   * <pre>assertThat(xml, hasXPath("/root/something[2]/cheese", myNs, equalTo("Cheddar")))</pre>
+   * 
+   * @param xPath
+   *     the target xpath
+   * @param namespaceContext
+   *     the namespace for matching nodes
+   * @param valueMatcher
+   *     matcher for the value at the specified xpath
+   */
+  public static org.hamcrest.Matcher<org.w3c.dom.Node> hasXPath(java.lang.String xPath, javax.xml.namespace.NamespaceContext namespaceContext, org.hamcrest.Matcher<java.lang.String> valueMatcher) {
+    return org.hamcrest.xml.HasXPath.hasXPath(xPath, namespaceContext, valueMatcher);
+  }
+
+  /**
+   * Creates a matcher of {@link org.w3c.dom.Node}s that matches when the examined node contains a node
+   * at the specified <code>xPath</code>, with any content.
+   * For example:
+   * <pre>assertThat(xml, hasXPath("/root/something[2]/cheese"))</pre>
+   * 
+   * @param xPath
+   *     the target xpath
+   */
+  public static org.hamcrest.Matcher<org.w3c.dom.Node> hasXPath(java.lang.String xPath) {
+    return org.hamcrest.xml.HasXPath.hasXPath(xPath);
+  }
+
+  /**
+   * Creates a matcher of {@link org.w3c.dom.Node}s that matches when the examined node contains a node
+   * at the specified <code>xPath</code> within the specified namespace context, with any content.
+   * For example:
+   * <pre>assertThat(xml, hasXPath("/root/something[2]/cheese", myNs))</pre>
+   * 
+   * @param xPath
+   *     the target xpath
+   * @param namespaceContext
+   *     the namespace for matching nodes
+   */
+  public static org.hamcrest.Matcher<org.w3c.dom.Node> hasXPath(java.lang.String xPath, javax.xml.namespace.NamespaceContext namespaceContext) {
+    return org.hamcrest.xml.HasXPath.hasXPath(xPath, namespaceContext);
+  }
 
 }
diff --git a/hamcrest-library/src/main/java/org/hamcrest/collection/IsArray.java b/hamcrest-library/src/main/java/org/hamcrest/collection/IsArray.java
index 6a26ef1..38f5d91 100644
--- a/hamcrest-library/src/main/java/org/hamcrest/collection/IsArray.java
+++ b/hamcrest-library/src/main/java/org/hamcrest/collection/IsArray.java
@@ -1,18 +1,23 @@
 package org.hamcrest.collection;
 
-import java.util.Arrays;
-
 import org.hamcrest.Description;
 import org.hamcrest.Matcher;
 import org.hamcrest.TypeSafeMatcher;
 
+import java.util.Arrays;
+
+/**
+ * Matcher for array whose elements satisfy a sequence of matchers.
+ * The array size must equal the number of element matchers.
+ */
 public class IsArray<T> extends TypeSafeMatcher<T[]> {
-    private final Matcher<T>[] elementMatchers;
+    private final Matcher<? super T>[] elementMatchers;
     
-    public IsArray(Matcher<T>[] elementMatchers) {
+    public IsArray(Matcher<? super T>[] elementMatchers) {
         this.elementMatchers = elementMatchers.clone();
     }
     
+    @Override
     public boolean matchesSafely(T[] array) {
         if (array.length != elementMatchers.length) return false;
         
@@ -22,7 +27,24 @@
         
         return true;
     }
-    
+
+    @Override
+    public void describeMismatchSafely(T[] actual, Description mismatchDescription) {
+        if (actual.length != elementMatchers.length) {
+            mismatchDescription.appendText("array length was ").appendValue(actual.length);
+            return;
+        }
+        for (int i = 0; i < actual.length; i++) {
+            if (!elementMatchers[i].matches(actual[i])) {
+                mismatchDescription.appendText("element ").appendValue(i).appendText(" ");
+                elementMatchers[i].describeMismatch(actual[i], mismatchDescription);
+                return;
+            }
+        }
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
     public void describeTo(Description description) {
         description.appendList(descriptionStart(), descriptionSeparator(), descriptionEnd(), 
                                Arrays.asList(elementMatchers));
@@ -58,7 +80,18 @@
         return "]";
     }
     
-    public static <T> IsArray<T> array(Matcher<T>... elementMatchers) {
+    /**
+     * Creates a matcher that matches arrays whose elements are satisfied by the specified matchers.  Matches
+     * positively only if the number of matchers specified is equal to the length of the examined array and
+     * each matcher[i] is satisfied by array[i].
+     * For example:
+     * <pre>assertThat(new Integer[]{1,2,3}, is(array(equalTo(1), equalTo(2), equalTo(3))))</pre>
+     * 
+     * @param elementMatchers
+     *     the matchers that the elements of examined arrays should satisfy
+     */
+    public static <T> IsArray<T> array(Matcher<? super T>... elementMatchers) {
         return new IsArray<T>(elementMatchers);
     }
+
 }
diff --git a/hamcrest-library/src/main/java/org/hamcrest/collection/IsArrayContaining.java b/hamcrest-library/src/main/java/org/hamcrest/collection/IsArrayContaining.java
index 76ddf9d..749c7c6 100644
--- a/hamcrest-library/src/main/java/org/hamcrest/collection/IsArrayContaining.java
+++ b/hamcrest-library/src/main/java/org/hamcrest/collection/IsArrayContaining.java
@@ -2,18 +2,23 @@
 
 import org.hamcrest.Description;
 import org.hamcrest.Matcher;
-import org.hamcrest.Factory;
 import org.hamcrest.TypeSafeMatcher;
+
+import java.util.Arrays;
+
 import static org.hamcrest.core.IsEqual.equalTo;
 
+/**
+ * Matches if an array contains an item satisfying a nested matcher.
+ */
 public class IsArrayContaining<T> extends TypeSafeMatcher<T[]> {
+    private final Matcher<? super T> elementMatcher;
 
-    private final Matcher<T> elementMatcher;
-
-    public IsArrayContaining(Matcher<T> elementMatcher) {
+    public IsArrayContaining(Matcher<? super T> elementMatcher) {
         this.elementMatcher = elementMatcher;
     }
 
+    @Override
     public boolean matchesSafely(T[] array) {
         for (T item : array) {
             if (elementMatcher.matches(item)) {
@@ -22,21 +27,45 @@
         }
         return false;
     }
-
-    public void describeTo(Description description) {
-        description
-        	.appendText("an array containing ")
-        	.appendDescriptionOf(elementMatcher);
+    
+    @Override
+    public void describeMismatchSafely(T[] item, Description mismatchDescription) {
+        super.describeMismatch(Arrays.asList(item), mismatchDescription);
     }
 
-    @Factory
-    public static <T> Matcher<T[]> hasItemInArray(Matcher<T> elementMatcher) {
+    @Override
+    public void describeTo(Description description) {
+        description
+            .appendText("an array containing ")
+            .appendDescriptionOf(elementMatcher);
+    }
+
+    /**
+     * Creates a matcher for arrays that matches when the examined array contains at least one item
+     * that is matched by the specified <code>elementMatcher</code>.  Whilst matching, the traversal
+     * of the examined array will stop as soon as a matching element is found.
+     * For example:
+     * <pre>assertThat(new String[] {"foo", "bar"}, hasItemInArray(startsWith("ba")))</pre>
+     * 
+     * @param elementMatcher
+     *     the matcher to apply to elements in examined arrays
+     */
+    public static <T> Matcher<T[]> hasItemInArray(Matcher<? super T> elementMatcher) {
         return new IsArrayContaining<T>(elementMatcher);
     }
 
-    @Factory
+    /**
+     * A shortcut to the frequently used <code>hasItemInArray(equalTo(x))</code>.
+     * For example:
+     * <pre>assertThat(hasItemInArray(x))</pre>
+     * instead of:
+     * <pre>assertThat(hasItemInArray(equalTo(x)))</pre>
+     * 
+     * @param element
+     *     the element that should be present in examined arrays
+     */
     public static <T> Matcher<T[]> hasItemInArray(T element) {
-        return hasItemInArray(equalTo(element));
+        Matcher<? super T> matcher = equalTo(element);
+        return IsArrayContaining.<T>hasItemInArray(matcher);
     }
-
 }
diff --git a/hamcrest-library/src/main/java/org/hamcrest/collection/IsArrayContainingInAnyOrder.java b/hamcrest-library/src/main/java/org/hamcrest/collection/IsArrayContainingInAnyOrder.java
new file mode 100644
index 0000000..a3a93c1
--- /dev/null
+++ b/hamcrest-library/src/main/java/org/hamcrest/collection/IsArrayContainingInAnyOrder.java
@@ -0,0 +1,112 @@
+package org.hamcrest.collection;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+
+public class IsArrayContainingInAnyOrder<E> extends TypeSafeMatcher<E[]> {
+    private final IsIterableContainingInAnyOrder<E> iterableMatcher;
+    private final Collection<Matcher<? super E>> matchers;
+
+    public IsArrayContainingInAnyOrder(Collection<Matcher<? super E>> matchers) {
+        this.iterableMatcher = new IsIterableContainingInAnyOrder<E>(matchers);
+        this.matchers = matchers;
+    }
+
+    @Override
+    public boolean matchesSafely(E[] item) {
+        return iterableMatcher.matches(Arrays.asList(item));
+    }
+    
+    @Override
+    public void describeMismatchSafely(E[] item, Description mismatchDescription) {
+      iterableMatcher.describeMismatch(Arrays.asList(item), mismatchDescription);
+    }
+
+    @Override
+    public void describeTo(Description description) {
+        description.appendList("[", ", ", "]", matchers)
+            .appendText(" in any order");
+    }
+
+    /**
+     * <p>
+     * Creates an order agnostic matcher for arrays that matches when each item in the
+     * examined array satisfies one matcher anywhere in the specified matchers.
+     * For a positive match, the examined array must be of the same length as the number of
+     * specified matchers.
+     * </p>
+     * <p>
+     * N.B. each of the specified matchers will only be used once during a given examination, so be
+     * careful when specifying matchers that may be satisfied by more than one entry in an examined
+     * array.
+     * </p>
+     * <p>
+     * For example:
+     * </p>
+     * <pre>assertThat(new String[]{"foo", "bar"}, arrayContainingInAnyOrder(equalTo("bar"), equalTo("foo")))</pre>
+     * 
+     * @param itemMatchers
+     *     a list of matchers, each of which must be satisfied by an entry in an examined array
+     */
+    public static <E> Matcher<E[]> arrayContainingInAnyOrder(Matcher<? super E>... itemMatchers) {
+        return arrayContainingInAnyOrder((List) Arrays.asList(itemMatchers));
+    }
+
+    /**
+     * <p>
+     * Creates an order agnostic matcher for arrays that matches when each item in the
+     * examined array satisfies one matcher anywhere in the specified collection of matchers.
+     * For a positive match, the examined array must be of the same length as the specified collection
+     * of matchers.
+     * </p>
+     * <p>
+     * N.B. each matcher in the specified collection will only be used once during a given
+     * examination, so be careful when specifying matchers that may be satisfied by more than
+     * one entry in an examined array.
+     * </p>
+     * <p>
+     * For example:
+     * </p>
+     * <pre>assertThat(new String[]{"foo", "bar"}, arrayContainingInAnyOrder(Arrays.asList(equalTo("bar"), equalTo("foo"))))</pre>
+     * 
+     * @param itemMatchers
+     *     a list of matchers, each of which must be satisfied by an item provided by an examined array
+     */
+    public static <E> Matcher<E[]> arrayContainingInAnyOrder(Collection<Matcher<? super E>> itemMatchers) {
+        return new IsArrayContainingInAnyOrder<E>(itemMatchers);
+    }
+
+    /**
+     * <p>Creates an order agnostic matcher for arrays that matches when each item in the
+     * examined array is logically equal to one item anywhere in the specified items.
+     * For a positive match, the examined array must be of the same length as the number of
+     * specified items.
+     * </p>
+     * <p>N.B. each of the specified items will only be used once during a given examination, so be
+     * careful when specifying items that may be equal to more than one entry in an examined
+     * array.
+     * </p>
+     * <p>
+     * For example:
+     * </p>
+     * <pre>assertThat(new String[]{"foo", "bar"}, containsInAnyOrder("bar", "foo"))</pre>
+     * 
+     * @param items
+     *     the items that must equal the entries of an examined array, in any order
+     */
+    public static <E> Matcher<E[]> arrayContainingInAnyOrder(E... items) {
+      List<Matcher<? super E>> matchers = new ArrayList<Matcher<? super E>>();
+      for (E item : items) {
+          matchers.add(equalTo(item));
+      }
+      return new IsArrayContainingInAnyOrder<E>(matchers);
+    }
+}
diff --git a/hamcrest-library/src/main/java/org/hamcrest/collection/IsArrayContainingInOrder.java b/hamcrest-library/src/main/java/org/hamcrest/collection/IsArrayContainingInOrder.java
new file mode 100644
index 0000000..849920a
--- /dev/null
+++ b/hamcrest-library/src/main/java/org/hamcrest/collection/IsArrayContainingInOrder.java
@@ -0,0 +1,89 @@
+package org.hamcrest.collection;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+import org.hamcrest.internal.NullSafety;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import static java.util.Arrays.asList;
+import static org.hamcrest.core.IsEqual.equalTo;
+
+public class IsArrayContainingInOrder<E> extends TypeSafeMatcher<E[]> {
+    private final Collection<Matcher<? super E>> matchers;
+    private final IsIterableContainingInOrder<E> iterableMatcher;
+
+    public IsArrayContainingInOrder(List<Matcher<? super E>> matchers) {
+        this.iterableMatcher = new IsIterableContainingInOrder<E>(matchers);
+        this.matchers = matchers;
+    }
+
+    @Override
+    public boolean matchesSafely(E[] item) {
+        return iterableMatcher.matches(asList(item));
+    }
+    
+    @Override
+    public void describeMismatchSafely(E[] item, Description mismatchDescription) {
+      iterableMatcher.describeMismatch(asList(item), mismatchDescription);
+    }
+
+    @Override
+    public void describeTo(Description description) {
+        description.appendList("[", ", ", "]", matchers);
+    }
+
+    /**
+     * Creates a matcher for arrays that matches when each item in the examined array is
+     * logically equal to the corresponding item in the specified items.  For a positive match,
+     * the examined array must be of the same length as the number of specified items.
+     * For example:
+     * <pre>assertThat(new String[]{"foo", "bar"}, contains("foo", "bar"))</pre>
+     * 
+     * @param items
+     *     the items that must equal the items within an examined array
+     */
+    public static <E> Matcher<E[]> arrayContaining(E... items) {
+        List<Matcher<? super E>> matchers = new ArrayList<Matcher<? super E>>();
+        for (E item : items) {
+            matchers.add(equalTo(item));
+        }
+        return arrayContaining(matchers);
+    }
+
+    /**
+     * Creates a matcher for arrays that matches when each item in the examined array satisfies the
+     * corresponding matcher in the specified matchers.  For a positive match, the examined array
+     * must be of the same length as the number of specified matchers.
+     * For example:
+     * <pre>assertThat(new String[]{"foo", "bar"}, contains(equalTo("foo"), equalTo("bar")))</pre>
+     * 
+     * @param itemMatchers
+     *     the matchers that must be satisfied by the items in the examined array
+     */
+    public static <E> Matcher<E[]> arrayContaining(Matcher<? super E>... itemMatchers) {
+        //required for JDK 1.6
+        //noinspection RedundantTypeArguments
+        final List<Matcher<? super E>> nullSafeWithExplicitTypeMatchers = NullSafety.<E>nullSafe(itemMatchers);
+
+        return arrayContaining(nullSafeWithExplicitTypeMatchers);
+    }
+
+    /**
+     * Creates a matcher for arrays that matches when each item in the examined array satisfies the
+     * corresponding matcher in the specified list of matchers.  For a positive match, the examined array
+     * must be of the same length as the specified list of matchers.
+     * For example:
+     * <pre>assertThat(new String[]{"foo", "bar"}, contains(Arrays.asList(equalTo("foo"), equalTo("bar"))))</pre>
+     * 
+     * @param itemMatchers
+     *     a list of matchers, each of which must be satisfied by the corresponding item in an examined array
+     */
+    public static <E> Matcher<E[]> arrayContaining(List<Matcher<? super E>> itemMatchers) {
+        return new IsArrayContainingInOrder<E>(itemMatchers);
+    }
+
+}
diff --git a/hamcrest-library/src/main/java/org/hamcrest/collection/IsArrayWithSize.java b/hamcrest-library/src/main/java/org/hamcrest/collection/IsArrayWithSize.java
new file mode 100644
index 0000000..b3a0b1f
--- /dev/null
+++ b/hamcrest-library/src/main/java/org/hamcrest/collection/IsArrayWithSize.java
@@ -0,0 +1,59 @@
+package org.hamcrest.collection;
+
+import org.hamcrest.FeatureMatcher;
+import org.hamcrest.Matcher;
+
+import static org.hamcrest.core.DescribedAs.describedAs;
+import static org.hamcrest.core.IsEqual.equalTo;
+
+/**
+ * Matches if array size satisfies a nested matcher.
+ */
+public class IsArrayWithSize<E> extends FeatureMatcher<E[], Integer> {
+    public IsArrayWithSize(Matcher<? super Integer> sizeMatcher) {
+        super(sizeMatcher, "an array with size","array size");
+    }
+
+    @Override
+    protected Integer featureValueOf(E[] actual) {
+      return actual.length;
+    }
+
+    /**
+     * Creates a matcher for arrays that matches when the <code>length</code> of the array
+     * satisfies the specified matcher.
+     * For example:
+     * <pre>assertThat(new String[]{"foo", "bar"}, arrayWithSize(equalTo(2)))</pre>
+     * 
+     * @param sizeMatcher
+     *     a matcher for the length of an examined array
+     */
+    public static <E> Matcher<E[]> arrayWithSize(Matcher<? super Integer> sizeMatcher) {
+        return new IsArrayWithSize<E>(sizeMatcher);
+    }
+
+    /**
+     * Creates a matcher for arrays that matches when the <code>length</code> of the array
+     * equals the specified <code>size</code>.
+     * For example:
+     * <pre>assertThat(new String[]{"foo", "bar"}, arrayWithSize(2))</pre>
+     * 
+     * @param size
+     *     the length that an examined array must have for a positive match
+     */
+    public static <E> Matcher<E[]> arrayWithSize(int size) {
+        return arrayWithSize(equalTo(size));
+    }
+
+    /**
+     * Creates a matcher for arrays that matches when the <code>length</code> of the array
+     * is zero.
+     * For example:
+     * <pre>assertThat(new String[0], emptyArray())</pre>
+     * 
+     */
+    public static <E> Matcher<E[]> emptyArray() {
+        Matcher<E[]> isEmpty = arrayWithSize(0);
+        return describedAs("an empty array", isEmpty);
+    }
+}
diff --git a/hamcrest-library/src/main/java/org/hamcrest/collection/IsCollectionContaining.java b/hamcrest-library/src/main/java/org/hamcrest/collection/IsCollectionContaining.java
deleted file mode 100644
index ba98630..0000000
--- a/hamcrest-library/src/main/java/org/hamcrest/collection/IsCollectionContaining.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package org.hamcrest.collection;
-
-import static org.hamcrest.core.AllOf.allOf;
-import org.hamcrest.Description;
-import org.hamcrest.Matcher;
-import org.hamcrest.Factory;
-import org.hamcrest.TypeSafeMatcher;
-import static org.hamcrest.core.IsEqual.equalTo;
-
-import java.util.Collection;
-import java.util.ArrayList;
-
-public class IsCollectionContaining<T> extends TypeSafeMatcher<Iterable<T>> {
-    private final Matcher<? extends T> elementMatcher;
-
-    public IsCollectionContaining(Matcher<? extends T> elementMatcher) {
-        this.elementMatcher = elementMatcher;
-    }
-
-    public boolean matchesSafely(Iterable<T> collection) {
-        for (T item : collection) {
-            if (elementMatcher.matches(item)){
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public void describeTo(Description description) {
-        description
-        	.appendText("a collection containing ")
-        	.appendDescriptionOf(elementMatcher);
-    }
-
-    @Factory
-    public static <T> Matcher<Iterable<T>> hasItem(Matcher<? extends T> elementMatcher) {
-        return new IsCollectionContaining<T>(elementMatcher);
-    }
-
-    @Factory
-    public static <T> Matcher<Iterable<T>> hasItem(T element) {
-        return hasItem(equalTo(element));
-    }
-
-    @Factory
-    public static <T> Matcher<Iterable<T>> hasItems(Matcher<? extends T>... elementMatchers) {
-        Collection<Matcher<? extends Iterable<T>>> all
-                = new ArrayList<Matcher<? extends Iterable<T>>>(elementMatchers.length);
-        for (Matcher<? extends T> elementMatcher : elementMatchers) {
-            all.add(hasItem(elementMatcher));
-        }
-        return allOf(all);
-    }
-
-    @Factory
-    public static <T> Matcher<Iterable<T>> hasItems(T... elements) {
-        Collection<Matcher<? extends Iterable<T>>> all
-                = new ArrayList<Matcher<? extends Iterable<T>>>(elements.length);
-        for (T element : elements) {
-            all.add(hasItem(element));
-        }
-        return allOf(all);
-    }
-
-}
diff --git a/hamcrest-library/src/main/java/org/hamcrest/collection/IsCollectionWithSize.java b/hamcrest-library/src/main/java/org/hamcrest/collection/IsCollectionWithSize.java
new file mode 100644
index 0000000..f12f57c
--- /dev/null
+++ b/hamcrest-library/src/main/java/org/hamcrest/collection/IsCollectionWithSize.java
@@ -0,0 +1,50 @@
+package org.hamcrest.collection;
+
+import org.hamcrest.FeatureMatcher;
+import org.hamcrest.Matcher;
+
+import java.util.Collection;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+
+/**
+ * Matches if collection size satisfies a nested matcher.
+ */
+public class IsCollectionWithSize<E> extends FeatureMatcher<Collection<? extends E>, Integer> {
+    public IsCollectionWithSize(Matcher<? super Integer> sizeMatcher) {
+      super(sizeMatcher, "a collection with size", "collection size");
+    }
+
+    @Override
+    protected Integer featureValueOf(Collection<? extends E> actual) {
+      return actual.size();
+    }
+
+    /**
+     * Creates a matcher for {@link java.util.Collection}s that matches when the <code>size()</code> method returns
+     * a value that satisfies the specified matcher.
+     * For example:
+     * <pre>assertThat(Arrays.asList("foo", "bar"), hasSize(equalTo(2)))</pre>
+     * 
+     * @param sizeMatcher
+     *     a matcher for the size of an examined {@link java.util.Collection}
+     */
+    public static <E> Matcher<Collection<? extends E>> hasSize(Matcher<? super Integer> sizeMatcher) {
+        return new IsCollectionWithSize<E>(sizeMatcher);
+    }
+
+    /**
+     * Creates a matcher for {@link java.util.Collection}s that matches when the <code>size()</code> method returns
+     * a value equal to the specified <code>size</code>.
+     * For example:
+     * <pre>assertThat(Arrays.asList("foo", "bar"), hasSize(2))</pre>
+     * 
+     * @param size
+     *     the expected size of an examined {@link java.util.Collection}
+     */
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    public static <E> Matcher<Collection<? extends E>> hasSize(int size) {
+    	return (Matcher)IsCollectionWithSize.hasSize(equalTo(size));
+    }
+
+}
diff --git a/hamcrest-library/src/main/java/org/hamcrest/collection/IsEmptyCollection.java b/hamcrest-library/src/main/java/org/hamcrest/collection/IsEmptyCollection.java
new file mode 100644
index 0000000..481b08c
--- /dev/null
+++ b/hamcrest-library/src/main/java/org/hamcrest/collection/IsEmptyCollection.java
@@ -0,0 +1,53 @@
+package org.hamcrest.collection;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+
+import java.util.Collection;
+
+/**
+ * Tests if collection is empty.
+ */
+public class IsEmptyCollection<E> extends TypeSafeMatcher<Collection<? extends E>> {
+
+    @Override
+    public boolean matchesSafely(Collection<? extends E> item) {
+        return item.isEmpty();
+    }
+
+    @Override
+    public void describeMismatchSafely(Collection<? extends E> item, Description mismatchDescription) {
+      mismatchDescription.appendValue(item);
+    }
+
+    @Override
+    public void describeTo(Description description) {
+        description.appendText("an empty collection");
+    }
+
+    /**
+     * Creates a matcher for {@link java.util.Collection}s matching examined collections whose <code>isEmpty</code>
+     * method returns <code>true</code>.
+     * For example:
+     * <pre>assertThat(new ArrayList&lt;String&gt;(), is(empty()))</pre>
+     * 
+     */
+    public static <E> Matcher<Collection<? extends E>> empty() {
+        return new IsEmptyCollection<E>();
+    }
+
+    /**
+     * Creates a matcher for {@link java.util.Collection}s matching examined collections whose <code>isEmpty</code>
+     * method returns <code>true</code>.
+     * For example:
+     * <pre>assertThat(new ArrayList&lt;String&gt;(), is(emptyCollectionOf(String.class)))</pre>
+     * 
+     * @param unusedToForceReturnType
+     *     the type of the collection's content
+     */
+    @SuppressWarnings({"unchecked", "UnusedParameters"})
+    public static <E> Matcher<Collection<E>> emptyCollectionOf(Class<E> unusedToForceReturnType) {
+      return (Matcher)empty();
+    }
+}
diff --git a/hamcrest-library/src/main/java/org/hamcrest/collection/IsEmptyIterable.java b/hamcrest-library/src/main/java/org/hamcrest/collection/IsEmptyIterable.java
new file mode 100644
index 0000000..047e670
--- /dev/null
+++ b/hamcrest-library/src/main/java/org/hamcrest/collection/IsEmptyIterable.java
@@ -0,0 +1,48 @@
+package org.hamcrest.collection;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+
+/**
+ * Tests if collection is empty.
+ */
+public class IsEmptyIterable<E> extends TypeSafeMatcher<Iterable<? extends E>> {
+
+    @Override
+    public boolean matchesSafely(Iterable<? extends E> iterable) {
+        return !iterable.iterator().hasNext();
+    }
+    @Override
+    public void describeMismatchSafely(Iterable<? extends E> iter, Description mismatchDescription) {
+        mismatchDescription.appendValueList("[", ",", "]", iter);
+    }
+
+    @Override
+    public void describeTo(Description description) {
+        description.appendText("an empty iterable");
+    }
+
+    /**
+     * Creates a matcher for {@link Iterable}s matching examined iterables that yield no items.
+     * For example:
+     * <pre>assertThat(new ArrayList&lt;String&gt;(), is(emptyIterable()))</pre>
+     * 
+     */
+    public static <E> Matcher<Iterable<? extends E>> emptyIterable() {
+        return new IsEmptyIterable<E>();
+    }
+
+    /**
+     * Creates a matcher for {@link Iterable}s matching examined iterables that yield no items.
+     * For example:
+     * <pre>assertThat(new ArrayList&lt;String&gt;(), is(emptyIterableOf(String.class)))</pre>
+     * 
+     * @param unusedToForceReturnType
+     *     the type of the iterable's content
+     */
+    @SuppressWarnings({"unchecked", "UnusedParameters"})
+    public static <E> Matcher<Iterable<E>> emptyIterableOf(Class<E> unusedToForceReturnType) {
+      return (Matcher)emptyIterable();
+    }
+}
diff --git a/hamcrest-library/src/main/java/org/hamcrest/collection/IsIn.java b/hamcrest-library/src/main/java/org/hamcrest/collection/IsIn.java
index 0a7bbb5..f030cab 100644
--- a/hamcrest-library/src/main/java/org/hamcrest/collection/IsIn.java
+++ b/hamcrest-library/src/main/java/org/hamcrest/collection/IsIn.java
@@ -1,13 +1,12 @@
 package org.hamcrest.collection;
 
-import java.util.Arrays;
-import java.util.Collection;
-
 import org.hamcrest.BaseMatcher;
 import org.hamcrest.Description;
-import org.hamcrest.Factory;
 import org.hamcrest.Matcher;
 
+import java.util.Arrays;
+import java.util.Collection;
+
 public class IsIn<T> extends BaseMatcher<T> {
     private final Collection<T> collection;
 
@@ -19,27 +18,108 @@
         collection = Arrays.asList(elements);
     }
     
+    @SuppressWarnings("SuspiciousMethodCalls")
+    @Override
     public boolean matches(Object o) {
         return collection.contains(o);
     }
 
+    @Override
     public void describeTo(Description buffer) {
         buffer.appendText("one of ");
         buffer.appendValueList("{", ", ", "}", collection);
     }
     
-    @Factory
+    /**
+     * Creates a matcher that matches when the examined object is found within the
+     * specified collection.
+     * For example:
+     * <pre>assertThat("foo", isIn(Arrays.asList("bar", "foo")))</pre>
+     * 
+     * @deprecated use is(in(...)) instead
+     * 
+     * @param collection
+     *     the collection in which matching items must be found
+     * 
+     */
+    @Deprecated
     public static <T> Matcher<T> isIn(Collection<T> collection) {
-        return new IsIn<T>(collection);
+        return in(collection);
     }
     
-    @Factory
+    /**
+     * Creates a matcher that matches when the examined object is found within the
+     * specified collection.
+     * For example:
+     * <pre>assertThat("foo", is(in(Arrays.asList("bar", "foo"))))</pre>
+     * 
+     * @param collection
+     *     the collection in which matching items must be found
+     * 
+     */
+    public static <T> Matcher<T> in(Collection<T> collection) {
+        return new IsIn<T>(collection);
+    }
+
+    /**
+     * Creates a matcher that matches when the examined object is found within the
+     * specified array.
+     * For example:
+     * <pre>assertThat("foo", isIn(new String[]{"bar", "foo"}))</pre>
+     * 
+     * @deprecated use is(in(...)) instead
+     * 
+     * @param elements
+     *     the array in which matching items must be found
+     * 
+     */
+    @Deprecated
     public static <T> Matcher<T> isIn(T[] elements) {
+        return in(elements);
+    }
+    
+    /**
+     * Creates a matcher that matches when the examined object is found within the
+     * specified array.
+     * For example:
+     * <pre>assertThat("foo", is(in(new String[]{"bar", "foo"})))</pre>
+     * 
+     * @param elements
+     *     the array in which matching items must be found
+     * 
+     */
+    public static <T> Matcher<T> in(T[] elements) {
         return new IsIn<T>(elements);
     }
     
-    @Factory
+    /**
+     * Creates a matcher that matches when the examined object is equal to one of the
+     * specified elements.
+     * For example:
+     * <pre>assertThat("foo", isOneOf("bar", "foo"))</pre>
+     * 
+     * @deprecated use is(oneOf(...)) instead
+     * 
+     * @param elements
+     *     the elements amongst which matching items will be found 
+     * 
+     */
+    @Deprecated
     public static <T> Matcher<T> isOneOf(T... elements) {
-        return isIn(elements);
+        return oneOf(elements);
+    }
+    
+    /**
+     * Creates a matcher that matches when the examined object is equal to one of the
+     * specified elements.
+     * For example:
+     * <pre>assertThat("foo", is(oneOf("bar", "foo")))</pre>
+     *  
+     * @param elements
+     *     the elements amongst which matching items will be found 
+     * 
+     */
+    public static <T> Matcher<T> oneOf(T... elements) {
+        return in(elements);
     }
 }
diff --git a/hamcrest-library/src/main/java/org/hamcrest/collection/IsIterableContainingInAnyOrder.java b/hamcrest-library/src/main/java/org/hamcrest/collection/IsIterableContainingInAnyOrder.java
new file mode 100644
index 0000000..6f2fc47
--- /dev/null
+++ b/hamcrest-library/src/main/java/org/hamcrest/collection/IsIterableContainingInAnyOrder.java
@@ -0,0 +1,154 @@
+package org.hamcrest.collection;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeDiagnosingMatcher;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+
+public class IsIterableContainingInAnyOrder<T> extends TypeSafeDiagnosingMatcher<Iterable<? extends T>> {
+    private final Collection<Matcher<? super T>> matchers;
+
+    public IsIterableContainingInAnyOrder(Collection<Matcher<? super T>> matchers) {
+        this.matchers = matchers;
+    }
+    
+    @Override
+    protected boolean matchesSafely(Iterable<? extends T> items, Description mismatchDescription) {
+      final Matching<T> matching = new Matching<T>(matchers, mismatchDescription);
+      for (T item : items) {
+        if (! matching.matches(item)) {
+          return false;
+        }
+      }
+      
+      return matching.isFinished(items);
+    }
+    
+    @Override
+    public void describeTo(Description description) {
+      description.appendText("iterable with items ")
+          .appendList("[", ", ", "]", matchers)
+          .appendText(" in any order");
+    }
+
+    private static class Matching<S> {
+      private final Collection<Matcher<? super S>> matchers;
+      private final Description mismatchDescription;
+
+      public Matching(Collection<Matcher<? super S>> matchers, Description mismatchDescription) {
+        this.matchers = new ArrayList<Matcher<? super S>>(matchers);
+        this.mismatchDescription = mismatchDescription;
+      }
+      
+      public boolean matches(S item) {
+        if (matchers.isEmpty()) {
+          mismatchDescription.appendText("no match for: ").appendValue(item);
+          return false;
+        }
+        return isMatched(item);
+      }
+
+      public boolean isFinished(Iterable<? extends S> items) {
+        if (matchers.isEmpty()) {
+          return true;
+        }
+        mismatchDescription
+          .appendText("no item matches: ").appendList("", ", ", "", matchers)
+          .appendText(" in ").appendValueList("[", ", ", "]", items);
+        return false;
+      }
+
+      private boolean isMatched(S item) {
+        for (Matcher<? super S>  matcher : matchers) {
+          if (matcher.matches(item)) {
+            matchers.remove(matcher);
+            return true;
+          }
+        }
+        mismatchDescription.appendText("not matched: ").appendValue(item);
+        return false;
+      }
+    }
+
+    /**
+     * <p>
+     * Creates an order agnostic matcher for {@link Iterable}s that matches when a single pass over
+     * the examined {@link Iterable} yields a series of items, each satisfying one matcher anywhere
+     * in the specified matchers.  For a positive match, the examined iterable must be of the same
+     * length as the number of specified matchers.
+     * </p>
+     * <p>
+     * N.B. each of the specified matchers will only be used once during a given examination, so be
+     * careful when specifying matchers that may be satisfied by more than one entry in an examined
+     * iterable.
+     * </p>
+     * <p>
+     * For example:
+     * </p>
+     * <pre>assertThat(Arrays.asList("foo", "bar"), containsInAnyOrder(equalTo("bar"), equalTo("foo")))</pre>
+     * 
+     * @param itemMatchers
+     *     a list of matchers, each of which must be satisfied by an item provided by an examined {@link Iterable}
+     */
+    public static <T> Matcher<Iterable<? extends T>> containsInAnyOrder(Matcher<? super T>... itemMatchers) {
+        return containsInAnyOrder((List) Arrays.asList(itemMatchers));
+    }
+
+    /**
+     * <p>
+     * Creates an order agnostic matcher for {@link Iterable}s that matches when a single pass over
+     * the examined {@link Iterable} yields a series of items, each logically equal to one item
+     * anywhere in the specified items. For a positive match, the examined iterable
+     * must be of the same length as the number of specified items.
+     * </p>
+     * <p>
+     * N.B. each of the specified items will only be used once during a given examination, so be
+     * careful when specifying items that may be equal to more than one entry in an examined
+     * iterable.
+     * </p>
+     * <p>
+     * For example:
+     * </p>
+     * <pre>assertThat(Arrays.asList("foo", "bar"), containsInAnyOrder("bar", "foo"))</pre>
+     * 
+     * @param items
+     *     the items that must equal the items provided by an examined {@link Iterable} in any order
+     */
+    public static <T> Matcher<Iterable<? extends T>> containsInAnyOrder(T... items) {
+        List<Matcher<? super T>> matchers = new ArrayList<Matcher<? super T>>();
+        for (T item : items) {
+            matchers.add(equalTo(item));
+        }
+        
+        return new IsIterableContainingInAnyOrder<T>(matchers);
+    }
+
+    /**
+     * <p>
+     * Creates an order agnostic matcher for {@link Iterable}s that matches when a single pass over
+     * the examined {@link Iterable} yields a series of items, each satisfying one matcher anywhere
+     * in the specified collection of matchers.  For a positive match, the examined iterable
+     * must be of the same length as the specified collection of matchers.
+     * </p>
+     * <p>
+     * N.B. each matcher in the specified collection will only be used once during a given
+     * examination, so be careful when specifying matchers that may be satisfied by more than
+     * one entry in an examined iterable.
+     * </p>
+     * <p>For example:</p>
+     * <pre>assertThat(Arrays.asList("foo", "bar"), containsInAnyOrder(Arrays.asList(equalTo("bar"), equalTo("foo"))))</pre>
+     * 
+     * @param itemMatchers
+     *     a list of matchers, each of which must be satisfied by an item provided by an examined {@link Iterable}
+     */
+    public static <T> Matcher<Iterable<? extends T>> containsInAnyOrder(Collection<Matcher<? super T>> itemMatchers) {
+        return new IsIterableContainingInAnyOrder<T>(itemMatchers);
+    }
+}
+
diff --git a/hamcrest-library/src/main/java/org/hamcrest/collection/IsIterableContainingInOrder.java b/hamcrest-library/src/main/java/org/hamcrest/collection/IsIterableContainingInOrder.java
new file mode 100644
index 0000000..6309566
--- /dev/null
+++ b/hamcrest-library/src/main/java/org/hamcrest/collection/IsIterableContainingInOrder.java
@@ -0,0 +1,153 @@
+package org.hamcrest.collection;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeDiagnosingMatcher;
+import org.hamcrest.internal.NullSafety;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static java.util.Arrays.asList;
+import static org.hamcrest.core.IsEqual.equalTo;
+
+public class IsIterableContainingInOrder<E> extends TypeSafeDiagnosingMatcher<Iterable<? extends E>> {
+    private final List<Matcher<? super E>> matchers;
+
+    public IsIterableContainingInOrder(List<Matcher<? super E>> matchers) {
+        this.matchers = matchers;
+    }
+
+    @Override
+    protected boolean matchesSafely(Iterable<? extends E> iterable, Description mismatchDescription) {
+        final MatchSeries<E> matchSeries = new MatchSeries<E>(matchers, mismatchDescription);
+        for (E item : iterable) {
+            if (!matchSeries.matches(item)) {
+                return false;
+            }
+        }
+
+        return matchSeries.isFinished();
+    }
+
+    @Override
+    public void describeTo(Description description) {
+        description.appendText("iterable containing ").appendList("[", ", ", "]", matchers);
+    }
+
+    private static class MatchSeries<F> {
+        private final List<Matcher<? super F>> matchers;
+        private final Description mismatchDescription;
+        private int nextMatchIx = 0;
+
+        public MatchSeries(List<Matcher<? super F>> matchers, Description mismatchDescription) {
+            this.mismatchDescription = mismatchDescription;
+            if (matchers.isEmpty()) {
+                throw new IllegalArgumentException("Should specify at least one expected element");
+            }
+            this.matchers = matchers;
+        }
+
+        public boolean matches(F item) {
+          if (matchers.size() <= nextMatchIx) {
+            mismatchDescription.appendText("not matched: ").appendValue(item);
+            return false;
+          }
+
+          return isMatched(item);
+        }
+
+        public boolean isFinished() {
+            if (nextMatchIx < matchers.size()) {
+                mismatchDescription.appendText("no item was ").appendDescriptionOf(matchers.get(nextMatchIx));
+                return false;
+            }
+            return true;
+        }
+
+        private boolean isMatched(F item) {
+            final Matcher<? super F> matcher = matchers.get(nextMatchIx);
+            if (!matcher.matches(item)) {
+                describeMismatch(matcher, item);
+                return false;
+            }
+            nextMatchIx++;
+            return true;
+        }
+
+      private void describeMismatch(Matcher<? super F> matcher, F item) {
+            mismatchDescription.appendText("item " + nextMatchIx + ": ");
+            matcher.describeMismatch(item, mismatchDescription);
+        }
+    }
+
+    /**
+     * Creates a matcher for {@link Iterable}s that matches when a single pass over the
+     * examined {@link Iterable} yields a series of items, each logically equal to the
+     * corresponding item in the specified items.  For a positive match, the examined iterable
+     * must be of the same length as the number of specified items.
+     * For example:
+     * <pre>assertThat(Arrays.asList("foo", "bar"), contains("foo", "bar"))</pre>
+     * 
+     * @param items
+     *     the items that must equal the items provided by an examined {@link Iterable}
+     */
+    public static <E> Matcher<Iterable<? extends E>> contains(E... items) {
+        List<Matcher<? super E>> matchers = new ArrayList<Matcher<? super E>>();
+        for (E item : items) {
+            matchers.add(equalTo(item));
+        }
+
+        return contains(matchers);
+    }
+
+    /**
+     * Creates a matcher for {@link Iterable}s that matches when a single pass over the
+     * examined {@link Iterable} yields a single item that satisfies the specified matcher.
+     * For a positive match, the examined iterable must only yield one item.
+     * For example:
+     * <pre>assertThat(Arrays.asList("foo"), contains(equalTo("foo")))</pre>
+     * 
+     * @param itemMatcher
+     *     the matcher that must be satisfied by the single item provided by an
+     *     examined {@link Iterable}
+     */
+    @SuppressWarnings("unchecked")
+    public static <E> Matcher<Iterable<? extends E>> contains(final Matcher<? super E> itemMatcher) {
+        return contains(new ArrayList<Matcher<? super E>>(asList(itemMatcher)));
+    }
+
+    /**
+     * Creates a matcher for {@link Iterable}s that matches when a single pass over the
+     * examined {@link Iterable} yields a series of items, each satisfying the corresponding
+     * matcher in the specified matchers.  For a positive match, the examined iterable
+     * must be of the same length as the number of specified matchers.
+     * For example:
+     * <pre>assertThat(Arrays.asList("foo", "bar"), contains(equalTo("foo"), equalTo("bar")))</pre>
+     * 
+     * @param itemMatchers
+     *     the matchers that must be satisfied by the items provided by an examined {@link Iterable}
+     */
+    public static <E> Matcher<Iterable<? extends E>> contains(Matcher<? super E>... itemMatchers) {
+        // required for JDK 1.6
+        //noinspection RedundantTypeArguments
+        final List<Matcher<? super E>> nullSafeWithExplicitTypeMatchers = NullSafety.<E>nullSafe(itemMatchers);
+    	return contains(nullSafeWithExplicitTypeMatchers);
+    }
+
+    /**
+     * Creates a matcher for {@link Iterable}s that matches when a single pass over the
+     * examined {@link Iterable} yields a series of items, each satisfying the corresponding
+     * matcher in the specified list of matchers.  For a positive match, the examined iterable
+     * must be of the same length as the specified list of matchers.
+     * For example:
+     * <pre>assertThat(Arrays.asList("foo", "bar"), contains(Arrays.asList(equalTo("foo"), equalTo("bar"))))</pre>
+     * 
+     * @param itemMatchers
+     *     a list of matchers, each of which must be satisfied by the corresponding item provided by
+     *     an examined {@link Iterable}
+     */
+    public static <E> Matcher<Iterable<? extends E>> contains(List<Matcher<? super E>> itemMatchers) {
+        return new IsIterableContainingInOrder<E>(itemMatchers);
+    }
+}
diff --git a/hamcrest-library/src/main/java/org/hamcrest/collection/IsIterableContainingInRelativeOrder.java b/hamcrest-library/src/main/java/org/hamcrest/collection/IsIterableContainingInRelativeOrder.java
new file mode 100644
index 0000000..f669835
--- /dev/null
+++ b/hamcrest-library/src/main/java/org/hamcrest/collection/IsIterableContainingInRelativeOrder.java
@@ -0,0 +1,117 @@
+package org.hamcrest.collection;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeDiagnosingMatcher;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static java.util.Arrays.asList;
+import static org.hamcrest.core.IsEqual.equalTo;
+
+public class IsIterableContainingInRelativeOrder<E> extends TypeSafeDiagnosingMatcher<Iterable<? extends E>> {
+    private final List<Matcher<? super E>> matchers;
+
+    public IsIterableContainingInRelativeOrder(List<Matcher<? super E>> matchers) {
+        this.matchers = matchers;
+    }
+
+    @Override
+    protected boolean matchesSafely(Iterable<? extends E> iterable, Description mismatchDescription) {
+        MatchSeriesInRelativeOrder<E> matchSeriesInRelativeOrder = new MatchSeriesInRelativeOrder<E>(matchers, mismatchDescription);
+        matchSeriesInRelativeOrder.processItems(iterable);
+        return matchSeriesInRelativeOrder.isFinished();
+    }
+
+    public void describeTo(Description description) {
+        description.appendText("iterable containing ").appendList("[", ", ", "]", matchers).appendText(" in relative order");
+    }
+
+    private static class MatchSeriesInRelativeOrder<F> {
+        public final List<Matcher<? super F>> matchers;
+        private final Description mismatchDescription;
+        private int nextMatchIx = 0;
+        private F lastMatchedItem = null;
+
+        public MatchSeriesInRelativeOrder(List<Matcher<? super F>> matchers, Description mismatchDescription) {
+            this.mismatchDescription = mismatchDescription;
+            if (matchers.isEmpty()) {
+                throw new IllegalArgumentException("Should specify at least one expected element");
+            }
+            this.matchers = matchers;
+        }
+
+        public void processItems(Iterable<? extends F> iterable) {
+            for (F item : iterable) {
+                if (nextMatchIx < matchers.size()) {
+                    Matcher<? super F> matcher = matchers.get(nextMatchIx);
+                    if (matcher.matches(item)) {
+                        lastMatchedItem = item;
+                        nextMatchIx++;
+                    }
+                }
+            }
+        }
+
+        public boolean isFinished() {
+            if (nextMatchIx < matchers.size()) {
+                mismatchDescription.appendDescriptionOf(matchers.get(nextMatchIx)).appendText(" was not found");
+                if (lastMatchedItem != null) {
+                    mismatchDescription.appendText(" after ").appendValue(lastMatchedItem);
+                }
+                return false;
+            }
+            return true;
+        }
+
+    }
+
+    /**
+     * Creates a matcher for {@link Iterable}s that matches when a single pass over the
+     * examined {@link Iterable} yields a series of items, that contains items logically equal to the
+     * corresponding item in the specified items, in the same relative order
+     * For example:
+     * <pre>assertThat(Arrays.asList("a", "b", "c", "d", "e"), containsInRelativeOrder("b", "d"))</pre>
+     * 
+     * @param items
+     *     the items that must be contained within items provided by an examined {@link Iterable} in the same relative order
+     */
+    public static <E> Matcher<Iterable<? extends E>> containsInRelativeOrder(E... items) {
+        List<Matcher<? super E>> matchers = new ArrayList<Matcher<? super E>>();
+        for (E item : items) {
+            matchers.add(equalTo(item));
+        }
+
+        return containsInRelativeOrder(matchers);
+    }
+
+    /**
+     * Creates a matcher for {@link Iterable}s that matches when a single pass over the
+     * examined {@link Iterable} yields a series of items, that each satisfying the corresponding
+     * matcher in the specified matchers, in the same relative order.
+     * For example:
+     * <pre>assertThat(Arrays.asList("a", "b", "c", "d", "e"), containsInRelativeOrder(equalTo("b"), equalTo("d")))</pre>
+     * 
+     * @param itemMatchers
+     *     the matchers that must be satisfied by the items provided by an examined {@link Iterable} in the same relative order
+     */
+    public static <E> Matcher<Iterable<? extends E>> containsInRelativeOrder(Matcher<? super E>... itemMatchers) {
+        return containsInRelativeOrder((List) asList(itemMatchers));
+    }
+
+    /**
+     * Creates a matcher for {@link Iterable}s that matches when a single pass over the
+     * examined {@link Iterable} yields a series of items, that contains items satisfying the corresponding
+     * matcher in the specified list of matchers, in the same relative order.
+     * For example:
+     * <pre>assertThat(Arrays.asList("a", "b", "c", "d", "e"), contains(Arrays.asList(equalTo("b"), equalTo("d"))))</pre>
+     * 
+     * @param itemMatchers
+     *     a list of matchers, each of which must be satisfied by the items provided by
+     *     an examined {@link Iterable} in the same relative order
+     */
+    public static <E> Matcher<Iterable<? extends E>> containsInRelativeOrder(List<Matcher<? super E>> itemMatchers) {
+        return new IsIterableContainingInRelativeOrder<E>(itemMatchers);
+    }
+}
diff --git a/hamcrest-library/src/main/java/org/hamcrest/collection/IsIterableWithSize.java b/hamcrest-library/src/main/java/org/hamcrest/collection/IsIterableWithSize.java
new file mode 100644
index 0000000..0a1535f
--- /dev/null
+++ b/hamcrest-library/src/main/java/org/hamcrest/collection/IsIterableWithSize.java
@@ -0,0 +1,53 @@
+package org.hamcrest.collection;
+
+import org.hamcrest.FeatureMatcher;
+import org.hamcrest.Matcher;
+
+import java.util.Iterator;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+
+public class IsIterableWithSize<E> extends FeatureMatcher<Iterable<E>, Integer> {
+
+    public IsIterableWithSize(Matcher<? super Integer> sizeMatcher) {
+        super(sizeMatcher, "an iterable with size", "iterable size");
+    }
+    
+
+    @Override
+    protected Integer featureValueOf(Iterable<E> actual) {
+      int size = 0;
+      for (Iterator<E> iterator = actual.iterator(); iterator.hasNext(); iterator.next()) {
+        size++;
+      }
+      return size;
+    }
+
+    /**
+     * Creates a matcher for {@link Iterable}s that matches when a single pass over the
+     * examined {@link Iterable} yields an item count that satisfies the specified
+     * matcher.
+     * For example:
+     * <pre>assertThat(Arrays.asList("foo", "bar"), iterableWithSize(equalTo(2)))</pre>
+     * 
+     * @param sizeMatcher
+     *     a matcher for the number of items that should be yielded by an examined {@link Iterable}
+     */
+    public static <E> Matcher<Iterable<E>> iterableWithSize(Matcher<? super Integer> sizeMatcher) {
+        return new IsIterableWithSize<E>(sizeMatcher);
+    }
+
+    /**
+     * Creates a matcher for {@link Iterable}s that matches when a single pass over the
+     * examined {@link Iterable} yields an item count that is equal to the specified
+     * <code>size</code> argument.
+     * For example:
+     * <pre>assertThat(Arrays.asList("foo", "bar"), iterableWithSize(2))</pre>
+     * 
+     * @param size
+     *     the number of items that should be yielded by an examined {@link Iterable}
+     */
+    public static <E> Matcher<Iterable<E>> iterableWithSize(int size) {
+        return iterableWithSize(equalTo(size));
+    }
+}
diff --git a/hamcrest-library/src/main/java/org/hamcrest/collection/IsMapContaining.java b/hamcrest-library/src/main/java/org/hamcrest/collection/IsMapContaining.java
index 74572dd..c29801e 100644
--- a/hamcrest-library/src/main/java/org/hamcrest/collection/IsMapContaining.java
+++ b/hamcrest-library/src/main/java/org/hamcrest/collection/IsMapContaining.java
@@ -1,28 +1,27 @@
 package org.hamcrest.collection;
 
 import org.hamcrest.Description;
-import org.hamcrest.Factory;
 import org.hamcrest.Matcher;
 import org.hamcrest.TypeSafeMatcher;
-import org.hamcrest.core.IsAnything;
-
-import static org.hamcrest.core.IsEqual.equalTo;
 
 import java.util.Map;
 import java.util.Map.Entry;
 
-public class IsMapContaining<K,V> extends TypeSafeMatcher<Map<K, V>> {
+import static org.hamcrest.core.IsAnything.anything;
+import static org.hamcrest.core.IsEqual.equalTo;
 
-    private final Matcher<K> keyMatcher;
-    private final Matcher<V> valueMatcher;
+public class IsMapContaining<K,V> extends TypeSafeMatcher<Map<? extends K, ? extends V>> {
+    private final Matcher<? super K> keyMatcher;
+    private final Matcher<? super V> valueMatcher;
 
-    public IsMapContaining(Matcher<K> keyMatcher, Matcher<V> valueMatcher) {
+    public IsMapContaining(Matcher<? super K> keyMatcher, Matcher<? super V> valueMatcher) {
         this.keyMatcher = keyMatcher;
         this.valueMatcher = valueMatcher;
     }
 
-    public boolean matchesSafely(Map<K, V> map) {
-        for (Entry<K, V> entry : map.entrySet()) {
+    @Override
+    public boolean matchesSafely(Map<? extends K, ? extends V> map) {
+        for (Entry<? extends K, ? extends V> entry : map.entrySet()) {
             if (keyMatcher.matches(entry.getKey()) && valueMatcher.matches(entry.getValue())) {
                 return true;
             }
@@ -30,41 +29,101 @@
         return false;
     }
 
+    @Override
+    public void describeMismatchSafely(Map<? extends K, ? extends V> map, Description mismatchDescription) {
+      mismatchDescription.appendText("map was ").appendValueList("[", ", ", "]", map.entrySet());
+    }
+
+    @Override
     public void describeTo(Description description) {
         description.appendText("map containing [")
                    .appendDescriptionOf(keyMatcher)
                    .appendText("->")
-			       .appendDescriptionOf(valueMatcher)
-			       .appendText("]");
+                   .appendDescriptionOf(valueMatcher)
+                   .appendText("]");
     }
 
-    @Factory
-    public static <K,V> Matcher<Map<K,V>> hasEntry(Matcher<K> keyMatcher, Matcher<V> valueMatcher) {
+    /**
+     * Creates a matcher for {@link java.util.Map}s matching when the examined {@link java.util.Map} contains
+     * at least one entry whose key satisfies the specified <code>keyMatcher</code> <b>and</b> whose
+     * value satisfies the specified <code>valueMatcher</code>.
+     * For example:
+     * <pre>assertThat(myMap, hasEntry(equalTo("bar"), equalTo("foo")))</pre>
+     * 
+     * @param keyMatcher
+     *     the key matcher that, in combination with the valueMatcher, must be satisfied by at least one entry
+     * @param valueMatcher
+     *     the value matcher that, in combination with the keyMatcher, must be satisfied by at least one entry
+     */
+    public static <K,V> Matcher<Map<? extends K,? extends V>> hasEntry(Matcher<? super K> keyMatcher, Matcher<? super V> valueMatcher) {
         return new IsMapContaining<K,V>(keyMatcher, valueMatcher);
     }
 
-    @Factory
-    public static <K,V> Matcher<Map<K,V>> hasEntry(K key, V value) {
-        return hasEntry(equalTo(key), equalTo(value));
+    /**
+     * Creates a matcher for {@link java.util.Map}s matching when the examined {@link java.util.Map} contains
+     * at least one entry whose key equals the specified <code>key</code> <b>and</b> whose value equals the
+     * specified <code>value</code>.
+     * For example:
+     * <pre>assertThat(myMap, hasEntry("bar", "foo"))</pre>
+     *  
+     * @param key
+     *     the key that, in combination with the value, must be describe at least one entry
+     * @param value
+     *     the value that, in combination with the key, must be describe at least one entry
+     */
+    public static <K,V> Matcher<Map<? extends K,? extends V>> hasEntry(K key, V value) {
+        return new IsMapContaining<K,V>(equalTo(key), equalTo(value));
+    }
+    
+    /**
+     * Creates a matcher for {@link java.util.Map}s matching when the examined {@link java.util.Map} contains
+     * at least one key that satisfies the specified matcher.
+     * For example:
+     * <pre>assertThat(myMap, hasKey(equalTo("bar")))</pre>
+     * 
+     * @param keyMatcher
+     *     the matcher that must be satisfied by at least one key
+     */
+    public static <K> Matcher<Map<? extends K, ?>> hasKey(Matcher<? super K> keyMatcher) {
+        return new IsMapContaining<K,Object>(keyMatcher, anything());
     }
 
-    @Factory
-    public static <K,V> Matcher<Map<K,V>> hasKey(Matcher<K> keyMatcher) {
-        return hasEntry(keyMatcher, IsAnything.<V>anything());
+    /**
+     * Creates a matcher for {@link java.util.Map}s matching when the examined {@link java.util.Map} contains
+     * at least one key that is equal to the specified key.
+     * For example:
+     * <pre>assertThat(myMap, hasKey("bar"))</pre>
+     * 
+     * @param key
+     *     the key that satisfying maps must contain
+     */
+    public static <K> Matcher<Map<? extends K, ?>> hasKey(K key) {
+        return new IsMapContaining<K,Object>(equalTo(key), anything());
     }
 
-    @Factory
-    public static <K,V> Matcher<Map<K,V>> hasKey(K key) {
-        return hasKey(equalTo(key));
+    /**
+     * Creates a matcher for {@link java.util.Map}s matching when the examined {@link java.util.Map} contains
+     * at least one value that satisfies the specified valueMatcher.
+     * For example:
+     * <pre>assertThat(myMap, hasValue(equalTo("foo")))</pre>
+     * 
+     * @param valueMatcher
+     *     the matcher that must be satisfied by at least one value
+     */
+    public static <V> Matcher<Map<?, ? extends V>> hasValue(Matcher<? super V> valueMatcher) {
+        return new IsMapContaining<Object,V>(anything(), valueMatcher);
     }
 
-    @Factory
-    public static <K,V> Matcher<Map<K,V>> hasValue(Matcher<V> valueMatcher) {
-        return hasEntry(IsAnything.<K>anything(), valueMatcher);
-    }
-
-    @Factory
-    public static <K,V> Matcher<Map<K,V>> hasValue(V value) {
-        return hasValue(equalTo(value));
+    /**
+     * Creates a matcher for {@link java.util.Map}s matching when the examined {@link java.util.Map} contains
+     * at least one value that is equal to the specified value.
+     * For example:
+     * <pre>assertThat(myMap, hasValue("foo"))</pre>
+     * 
+     * @param value
+     *     the value that satisfying maps must contain
+     */
+    public static <V> Matcher<Map<?, ? extends V>> hasValue(V value) {
+        return new IsMapContaining<Object,V>(anything(), equalTo(value));
     }
 }
diff --git a/hamcrest-library/src/main/java/org/hamcrest/collection/IsMapWithSize.java b/hamcrest-library/src/main/java/org/hamcrest/collection/IsMapWithSize.java
new file mode 100644
index 0000000..0132390
--- /dev/null
+++ b/hamcrest-library/src/main/java/org/hamcrest/collection/IsMapWithSize.java
@@ -0,0 +1,60 @@
+package org.hamcrest.collection;
+
+import org.hamcrest.FeatureMatcher;
+import org.hamcrest.Matcher;
+
+import java.util.Map;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+
+/**
+ * Matches if map size satisfies a nested matcher.
+ */
+public final class IsMapWithSize<K, V> extends FeatureMatcher<Map<? extends K, ? extends V>, Integer> {
+    public IsMapWithSize(Matcher<? super Integer> sizeMatcher) {
+      super(sizeMatcher, "a map with size", "map size");
+    }
+
+    @Override
+    protected Integer featureValueOf(Map<? extends K, ? extends V> actual) {
+      return actual.size();
+    }
+
+    /**
+     * Creates a matcher for {@link java.util.Map}s that matches when the <code>size()</code> method returns
+     * a value that satisfies the specified matcher.
+     * For example:
+     * <pre>assertThat(myMap, is(aMapWithSize(equalTo(2))))</pre>
+     * 
+     * @param sizeMatcher
+     *     a matcher for the size of an examined {@link java.util.Map}
+     */
+    public static <K, V> Matcher<Map<? extends K, ? extends V>> aMapWithSize(Matcher<? super Integer> sizeMatcher) {
+        return new IsMapWithSize<K, V>(sizeMatcher);
+    }
+
+    /**
+     * Creates a matcher for {@link java.util.Map}s that matches when the <code>size()</code> method returns
+     * a value equal to the specified <code>size</code>.
+     * For example:
+     * <pre>assertThat(myMap, is(aMapWithSize(2)))</pre>
+     * 
+     * @param size
+     *     the expected size of an examined {@link java.util.Map}
+     */
+    public static <K, V> Matcher<Map<? extends K, ? extends V>> aMapWithSize(int size) {
+        Matcher<? super Integer> matcher = equalTo(size);
+        return IsMapWithSize.aMapWithSize(matcher);
+    }
+    
+    /**
+     * Creates a matcher for {@link java.util.Map}s that matches when the <code>size()</code> method returns
+     * zero.
+     * For example:
+     * <pre>assertThat(myMap, is(anEmptyMap()))</pre>
+     * 
+     */
+    public static <K, V> Matcher<Map<? extends K, ? extends V>> anEmptyMap() {
+        return IsMapWithSize.aMapWithSize(equalTo(0));
+    }
+}
diff --git a/hamcrest-library/src/main/java/org/hamcrest/comparator/ComparatorMatcherBuilder.java b/hamcrest-library/src/main/java/org/hamcrest/comparator/ComparatorMatcherBuilder.java
new file mode 100644
index 0000000..cf52211
--- /dev/null
+++ b/hamcrest-library/src/main/java/org/hamcrest/comparator/ComparatorMatcherBuilder.java
@@ -0,0 +1,178 @@
+package org.hamcrest.comparator;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+
+import java.util.Comparator;
+
+import static java.lang.Integer.signum;
+
+public final class ComparatorMatcherBuilder<T> {
+
+    private final Comparator<T> comparator;
+    private final boolean includeComparatorInDescription;
+
+    /**
+     * Creates a matcher factory for matchers of {@code Comparable}s.
+     * For example:
+     * <pre>assertThat(1, ComparatorMatcherBuilder.&lt;Integer&gt;usingNaturalOrdering().lessThanOrEqualTo(1))</pre>
+     */
+    public static <T extends Comparable<T>> ComparatorMatcherBuilder<T> usingNaturalOrdering() {
+        return new ComparatorMatcherBuilder<T>(new Comparator<T>() {
+            @Override
+            public int compare(T o1, T o2) {
+                return o1.compareTo(o2);
+            }
+        }, false);
+    }
+
+    /**
+     * Creates a matcher factory for matchers of {@code Comparators}s of {@code T}.
+     * For example:
+     * <pre>assertThat(5, comparedBy(new Comparator&lt;Integer&gt;() {
+     * public int compare(Integer o1, Integer o2) {
+     * return -o1.compareTo(o2);
+     * }
+     * }).lessThan(4))</pre>
+     */
+    public static <T> ComparatorMatcherBuilder<T> comparedBy(Comparator<T> comparator) {
+        return new ComparatorMatcherBuilder<T>(comparator, true);
+    }
+
+    private ComparatorMatcherBuilder(Comparator<T> comparator, boolean includeComparatorInDescription) {
+        this.comparator = comparator;
+        this.includeComparatorInDescription = includeComparatorInDescription;
+    }
+
+    private static final class ComparatorMatcher<T> extends TypeSafeMatcher<T> {
+        private static final int LESS_THAN = -1;
+        private static final int GREATER_THAN = 1;
+        private static final int EQUAL = 0;
+
+        private final Comparator<T> comparator;
+        private final T expected;
+        private final int minCompare;
+        private final int maxCompare;
+        private final boolean includeComparatorInDescription;
+
+        private static final String[] comparisonDescriptions = {
+                "less than",
+                "equal to",
+                "greater than"
+        };
+
+        private ComparatorMatcher(Comparator<T> comparator, T expected, int minCompare, int maxCompare, boolean includeComparatorInDescription) {
+            this.comparator = comparator;
+            this.expected = expected;
+            this.minCompare = minCompare;
+            this.maxCompare = maxCompare;
+            this.includeComparatorInDescription = includeComparatorInDescription;
+        }
+
+        @Override
+        public boolean matchesSafely(T actual) {
+            try {
+                int compare = signum(comparator.compare(actual, expected));
+                return minCompare <= compare && compare <= maxCompare;
+            } catch (ClassCastException e) {
+                return false; // type erasure means someone can shonk in a non-T :(
+            }
+        }
+
+        @Override
+        public void describeMismatchSafely(T actual, Description mismatchDescription) {
+            mismatchDescription.appendValue(actual).appendText(" was ")
+                    .appendText(asText(comparator.compare(actual, expected)))
+                    .appendText(" ").appendValue(expected);
+            if (includeComparatorInDescription) {
+                mismatchDescription.appendText(" when compared by ").appendValue(comparator);
+            }
+        }
+
+        @Override
+        public void describeTo(Description description) {
+            description.appendText("a value ").appendText(asText(minCompare));
+            if (minCompare != maxCompare) {
+                description.appendText(" or ").appendText(asText(maxCompare));
+            }
+            description.appendText(" ").appendValue(expected);
+            if (includeComparatorInDescription) {
+                description.appendText(" when compared by ").appendValue(comparator);
+            }
+        }
+
+        private static String asText(int comparison) {
+            return comparisonDescriptions[signum(comparison) + 1];
+        }
+    }
+
+    /**
+     * Creates a matcher of {@code T} object that matches when the examined object is
+     * equal to the specified value, as reported by the {@code Comparator} used to
+     * create this builder.
+     * For example:
+     * <pre>assertThat(1, ComparatorMatcherBuilder.&lt;Integer&gt;usingNaturalOrdering().comparesEqualTo(1))</pre>
+     *
+     * @param value the value which, when passed to the Comparator supplied to this builder, should return zero
+     */
+    public Matcher<T> comparesEqualTo(T value) {
+        return new ComparatorMatcher<T>(comparator, value, ComparatorMatcher.EQUAL, ComparatorMatcher.EQUAL, includeComparatorInDescription);
+    }
+
+    /**
+     * Creates a matcher of {@code T} object that matches when the examined object is
+     * greater than the specified value, as reported by the {@code Comparator} used to
+     * create this builder.
+     * For example:
+     * <pre>assertThat(2, ComparatorMatcherBuilder.&lt;Integer&gt;usingNaturalOrdering().greaterThan(1))</pre>
+     *
+     * @param value the value which, when passed to the Comparator supplied to this builder, should return greater
+     *              than zero
+     */
+    public Matcher<T> greaterThan(T value) {
+        return new ComparatorMatcher<T>(comparator, value, ComparatorMatcher.GREATER_THAN, ComparatorMatcher.GREATER_THAN, includeComparatorInDescription);
+    }
+
+    /**
+     * Creates a matcher of {@code T} object that matches when the examined object is
+     * greater than or equal to the specified value, as reported by the {@code Comparator} used to
+     * create this builder.
+     * For example:
+     * <pre>assertThat(1, ComparatorMatcherBuilder.&lt;Integer&gt;usingNaturalOrdering().greaterThanOrEqualTo(1))</pre>
+     *
+     * @param value the value which, when passed to the Comparator supplied to this builder, should return greater
+     *              than or equal to zero
+     */
+    public Matcher<T> greaterThanOrEqualTo(T value) {
+        return new ComparatorMatcher<T>(comparator, value, ComparatorMatcher.EQUAL, ComparatorMatcher.GREATER_THAN, includeComparatorInDescription);
+    }
+
+    /**
+     * Creates a matcher of {@code T} object that matches when the examined object is
+     * less than the specified value, as reported by the {@code Comparator} used to
+     * create this builder.
+     * For example:
+     * <pre>assertThat(1, ComparatorMatcherBuilder.&lt;Integer&gt;usingNaturalOrdering().lessThan(2))</pre>
+     *
+     * @param value the value which, when passed to the Comparator supplied to this builder, should return less
+     *              than zero
+     */
+    public Matcher<T> lessThan(T value) {
+        return new ComparatorMatcher<T>(comparator, value, ComparatorMatcher.LESS_THAN, ComparatorMatcher.LESS_THAN, includeComparatorInDescription);
+    }
+
+    /**
+     * Creates a matcher of {@code T} object that matches when the examined object is
+     * less than or equal to the specified value, as reported by the {@code Comparator} used to
+     * create this builder.
+     * For example:
+     * <pre>assertThat(1, ComparatorMatcherBuilder.&lt;Integer&gt;usingNaturalOrdering().lessThanOrEqualTo(1))</pre>
+     *
+     * @param value the value which, when passed to the Comparator supplied to this builder, should return less
+     *              than or equal to zero
+     */
+    public Matcher<T> lessThanOrEqualTo(T value) {
+        return new ComparatorMatcher<T>(comparator, value, ComparatorMatcher.LESS_THAN, ComparatorMatcher.EQUAL, includeComparatorInDescription);
+    }
+}
diff --git a/hamcrest-library/src/main/java/org/hamcrest/io/FileMatchers.java b/hamcrest-library/src/main/java/org/hamcrest/io/FileMatchers.java
new file mode 100644
index 0000000..88288b0
--- /dev/null
+++ b/hamcrest-library/src/main/java/org/hamcrest/io/FileMatchers.java
@@ -0,0 +1,107 @@
+package org.hamcrest.io;
+
+import org.hamcrest.Description;
+import org.hamcrest.FeatureMatcher;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeDiagnosingMatcher;
+
+import java.io.File;
+import java.io.IOException;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+
+public final class FileMatchers {
+
+    public static Matcher<File> anExistingDirectory() {
+        return fileChecker(IS_DIRECTORY, "an existing directory", "is not a directory");
+    }
+
+    public static Matcher<File> anExistingFileOrDirectory() {
+        return fileChecker(EXISTS, "an existing file or directory", "does not exist");
+    }
+
+    public static Matcher<File> anExistingFile() {
+        return fileChecker(IS_FILE, "an existing File", "is not a file");
+    }
+
+    public static Matcher<File> aReadableFile() {
+        return fileChecker(CAN_READ, "a readable File", "cannot be read");
+    }
+
+    public static Matcher<File> aWritableFile() {
+        return fileChecker(CAN_WRITE, "a writable File", "cannot be written to");
+    }
+
+    public static Matcher<File> aFileWithSize(long size) {
+        return aFileWithSize(equalTo(size));
+    }
+
+    public static Matcher<File> aFileWithSize(final Matcher<Long> expected) {
+        return new FeatureMatcher<File, Long>(expected, "A file with size", "size") {
+            @Override protected Long featureValueOf(File actual) { return actual.length(); }
+        };
+    }
+
+    public static Matcher<File> aFileNamed(final Matcher<String> expected) {
+        return new FeatureMatcher<File, String>(expected, "A file with name", "name") {
+            @Override protected String featureValueOf(File actual) { return actual.getName(); }
+        };
+    }
+
+    public static Matcher<File> aFileWithCanonicalPath(final Matcher<String> expected) {
+        return new FeatureMatcher<File, String>(expected, "A file with canonical path", "path") {
+            @Override protected String featureValueOf(File actual) {
+                try {
+                    return actual.getCanonicalPath();
+                } catch (IOException e) {
+                    return "Exception: " + e.getMessage();
+                }
+            }
+        };
+    }
+
+    public static Matcher<File> aFileWithAbsolutePath(final Matcher<String> expected) {
+        return new FeatureMatcher<File, String>(expected, "A file with absolute path", "path") {
+            @Override protected String featureValueOf(File actual) { return actual.getAbsolutePath(); }
+        };
+    }
+
+    public static interface FileStatus {
+        boolean check(File actual);
+    }
+
+    public static final FileStatus CAN_WRITE = new FileStatus() {
+        @Override public boolean check(File actual) { return actual.canWrite(); }
+    };
+    public static final FileStatus CAN_READ = new FileStatus() {
+        @Override public boolean check(File actual) { return actual.canRead(); }
+    };
+
+    public static final FileStatus IS_FILE = new FileStatus() {
+        @Override public boolean check(File actual) { return actual.isFile(); }
+    };
+
+    public static final FileStatus IS_DIRECTORY = new FileStatus() {
+        @Override public boolean check(File actual) { return actual.isDirectory(); }
+    };
+
+    public static final FileStatus EXISTS = new FileStatus() {
+        @Override public boolean check(File actual) { return actual.exists(); }
+    };
+
+    private static Matcher<File> fileChecker(final FileStatus fileStatus, final String successDescription, final String failureDescription) {
+        return new TypeSafeDiagnosingMatcher<File>() {
+            public boolean matchesSafely(File actual, Description mismatchDescription) {
+                final boolean result = fileStatus.check(actual);
+                if (!result) {
+                    mismatchDescription.appendText(failureDescription);
+                }
+                return result;
+            }
+
+            public void describeTo(Description description) {
+                description.appendText(successDescription);
+            }
+        };
+    }
+}
diff --git a/hamcrest-library/src/main/java/org/hamcrest/number/BigDecimalCloseTo.java b/hamcrest-library/src/main/java/org/hamcrest/number/BigDecimalCloseTo.java
new file mode 100644
index 0000000..d9cb026
--- /dev/null
+++ b/hamcrest-library/src/main/java/org/hamcrest/number/BigDecimalCloseTo.java
@@ -0,0 +1,63 @@
+package org.hamcrest.number;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+
+import java.math.BigDecimal;
+import java.math.MathContext;
+
+public class BigDecimalCloseTo extends TypeSafeMatcher<BigDecimal> {
+
+  private final BigDecimal delta;
+  private final BigDecimal value;
+
+  public BigDecimalCloseTo(BigDecimal value, BigDecimal error) {
+      this.delta = error;
+      this.value = value;
+  }
+
+  @Override
+  public boolean matchesSafely(BigDecimal item) {
+      return actualDelta(item).compareTo(BigDecimal.ZERO) <= 0;
+  }
+
+  @Override
+  public void describeMismatchSafely(BigDecimal item, Description mismatchDescription) {
+      mismatchDescription.appendValue(item)
+              .appendText(" differed by ")
+              .appendValue(actualDelta(item))
+              .appendText(" more than delta ")
+              .appendValue(delta);
+  }
+
+  @Override
+  public void describeTo(Description description) {
+      description.appendText("a numeric value within ")
+              .appendValue(delta)
+              .appendText(" of ")
+              .appendValue(value);
+  }
+
+  private BigDecimal actualDelta(BigDecimal item) {
+      return item.subtract(value, MathContext.DECIMAL128).abs().subtract(delta, MathContext.DECIMAL128).stripTrailingZeros();
+  }
+
+  /**
+   * Creates a matcher of {@link java.math.BigDecimal}s that matches when an examined BigDecimal is equal
+   * to the specified <code>operand</code>, within a range of +/- <code>error</code>. The comparison for equality
+   * is done by BigDecimals {@link java.math.BigDecimal#compareTo(java.math.BigDecimal)} method.
+   * For example:
+   * <pre>assertThat(new BigDecimal("1.03"), is(closeTo(new BigDecimal("1.0"), new BigDecimal("0.03"))))</pre>
+   * 
+   * @param operand
+   *     the expected value of matching BigDecimals
+   * @param error
+   *     the delta (+/-) within which matches will be allowed
+   */
+  public static Matcher<BigDecimal> closeTo(BigDecimal operand, BigDecimal error) {
+      return new BigDecimalCloseTo(operand, error);
+  }
+
+}
+
diff --git a/hamcrest-library/src/main/java/org/hamcrest/number/IsCloseTo.java b/hamcrest-library/src/main/java/org/hamcrest/number/IsCloseTo.java
index dc183e8..3b6967d 100644
--- a/hamcrest-library/src/main/java/org/hamcrest/number/IsCloseTo.java
+++ b/hamcrest-library/src/main/java/org/hamcrest/number/IsCloseTo.java
@@ -1,40 +1,63 @@
-/*  Copyright (c) 2000-2006 hamcrest.org
- */
 package org.hamcrest.number;
 
 import org.hamcrest.Description;
 import org.hamcrest.Matcher;
-import org.hamcrest.Factory;
 import org.hamcrest.TypeSafeMatcher;
 
+import static java.lang.Math.abs;
+
 
 /**
  * Is the value a number equal to a value within some range of
  * acceptable error?
  */
 public class IsCloseTo extends TypeSafeMatcher<Double> {
-    private final double error;
+    private final double delta;
     private final double value;
 
     public IsCloseTo(double value, double error) {
-        this.error = error;
+        this.delta = error;
         this.value = value;
     }
 
+    @Override
     public boolean matchesSafely(Double item) {
-        return Math.abs((item - value)) <= error;
+        return actualDelta(item) <= 0.0;
     }
 
+    @Override
+    public void describeMismatchSafely(Double item, Description mismatchDescription) {
+      mismatchDescription.appendValue(item)
+                         .appendText(" differed by ")
+                         .appendValue(actualDelta(item))
+                         .appendText(" more than delta ")
+                         .appendValue(delta);
+    }
+
+    @Override
     public void describeTo(Description description) {
         description.appendText("a numeric value within ")
-                .appendValue(error)
+                .appendValue(delta)
                 .appendText(" of ")
                 .appendValue(value);
     }
 
-    @Factory
+    private double actualDelta(Double item) {
+      return abs(item - value) - delta;
+    }
+
+    /**
+     * Creates a matcher of {@link Double}s that matches when an examined double is equal
+     * to the specified <code>operand</code>, within a range of +/- <code>error</code>.
+     * For example:
+     * <pre>assertThat(1.03, is(closeTo(1.0, 0.03)))</pre>
+     * 
+     * @param operand
+     *     the expected value of matching doubles
+     * @param error
+     *     the delta (+/-) within which matches will be allowed
+     */
     public static Matcher<Double> closeTo(double operand, double error) {
         return new IsCloseTo(operand, error);
     }
-
 }
diff --git a/hamcrest-library/src/main/java/org/hamcrest/number/IsGreaterThan.java b/hamcrest-library/src/main/java/org/hamcrest/number/IsGreaterThan.java
deleted file mode 100644
index 34046b7..0000000
--- a/hamcrest-library/src/main/java/org/hamcrest/number/IsGreaterThan.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*  Copyright (c) 2000-2006 hamcrest.org
- */
-package org.hamcrest.number;
-
-import org.hamcrest.Description;
-import org.hamcrest.TypeSafeMatcher;
-
-/**
- * Is the value less than or greater than another {@link java.lang.Comparable} value?
- */
-public class IsGreaterThan<T extends Comparable<T>> extends TypeSafeMatcher<T> {
-    private final Comparable<T> compareTo;
-    
-    public IsGreaterThan(Comparable<T> compareTo) {
-        this.compareTo = compareTo;
-    }
-    
-    public boolean matchesSafely(T item) {
-        return compareTo.compareTo(item) < 0;
-    }
-    
-    public void describeTo(Description description) {
-        description.appendText("a value greater than ");
-        description.appendValue(compareTo);
-    }
-}
diff --git a/hamcrest-library/src/main/java/org/hamcrest/number/IsNaN.java b/hamcrest-library/src/main/java/org/hamcrest/number/IsNaN.java
new file mode 100644
index 0000000..415a9a2
--- /dev/null
+++ b/hamcrest-library/src/main/java/org/hamcrest/number/IsNaN.java
@@ -0,0 +1,38 @@
+package org.hamcrest.number;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+
+
+/**
+ * Is the value a number actually not a number (NaN)?
+ */
+public final class IsNaN extends TypeSafeMatcher<Double> {
+
+    private IsNaN() { }
+
+    @Override
+    public boolean matchesSafely(Double item) {
+        return Double.isNaN(item);
+    }
+
+    @Override
+    public void describeMismatchSafely(Double item, Description mismatchDescription) {
+        mismatchDescription.appendText("was ").appendValue(item);
+    }
+
+    @Override
+    public void describeTo(Description description) {
+        description.appendText("a double value of NaN");
+    }
+
+    /**
+     * Creates a matcher of {@link Double}s that matches when an examined double is not a number.
+     * For example:
+     * <pre>assertThat(Double.NaN, is(notANumber()))</pre>
+     */
+    public static Matcher<Double> notANumber() {
+        return new IsNaN();
+    }
+}
diff --git a/hamcrest-library/src/main/java/org/hamcrest/number/OrderingComparison.java b/hamcrest-library/src/main/java/org/hamcrest/number/OrderingComparison.java
new file mode 100644
index 0000000..8a77713
--- /dev/null
+++ b/hamcrest-library/src/main/java/org/hamcrest/number/OrderingComparison.java
@@ -0,0 +1,79 @@
+package org.hamcrest.number;
+
+import org.hamcrest.Matcher;
+import org.hamcrest.comparator.ComparatorMatcherBuilder;
+
+public class OrderingComparison {
+
+    private OrderingComparison() {
+    }
+
+    /**
+     * Creates a matcher of {@link Comparable} object that matches when the examined object is
+     * equal to the specified value, as reported by the <code>compareTo</code> method of the
+     * <b>examined</b> object.
+     * For example:
+     * <pre>assertThat(1, comparesEqualTo(1))</pre>
+     *
+     * @param value the value which, when passed to the compareTo method of the examined object, should return zero
+     */
+    public static <T extends Comparable<T>> Matcher<T> comparesEqualTo(T value) {
+        return ComparatorMatcherBuilder.<T>usingNaturalOrdering().comparesEqualTo(value);
+    }
+
+    /**
+     * Creates a matcher of {@link Comparable} object that matches when the examined object is
+     * greater than the specified value, as reported by the <code>compareTo</code> method of the
+     * <b>examined</b> object.
+     * For example:
+     * <pre>assertThat(2, greaterThan(1))</pre>
+     *
+     * @param value the value which, when passed to the compareTo method of the examined object, should return greater
+     *              than zero
+     */
+    public static <T extends Comparable<T>> Matcher<T> greaterThan(T value) {
+        return ComparatorMatcherBuilder.<T>usingNaturalOrdering().greaterThan(value);
+    }
+
+    /**
+     * Creates a matcher of {@link Comparable} object that matches when the examined object is
+     * greater than or equal to the specified value, as reported by the <code>compareTo</code> method
+     * of the <b>examined</b> object.
+     * For example:
+     * <pre>assertThat(1, greaterThanOrEqualTo(1))</pre>
+     *
+     * @param value the value which, when passed to the compareTo method of the examined object, should return greater
+     *              than or equal to zero
+     */
+    public static <T extends Comparable<T>> Matcher<T> greaterThanOrEqualTo(T value) {
+        return ComparatorMatcherBuilder.<T>usingNaturalOrdering().greaterThanOrEqualTo(value);
+    }
+
+    /**
+     * Creates a matcher of {@link Comparable} object that matches when the examined object is
+     * less than the specified value, as reported by the <code>compareTo</code> method of the
+     * <b>examined</b> object.
+     * For example:
+     * <pre>assertThat(1, lessThan(2))</pre>
+     *
+     * @param value the value which, when passed to the compareTo method of the examined object, should return less
+     *              than zero
+     */
+    public static <T extends Comparable<T>> Matcher<T> lessThan(T value) {
+        return ComparatorMatcherBuilder.<T>usingNaturalOrdering().lessThan(value);
+    }
+
+    /**
+     * Creates a matcher of {@link Comparable} object that matches when the examined object is
+     * less than or equal to the specified value, as reported by the <code>compareTo</code> method
+     * of the <b>examined</b> object.
+     * For example:
+     * <pre>assertThat(1, lessThanOrEqualTo(1))</pre>
+     *
+     * @param value the value which, when passed to the compareTo method of the examined object, should return less
+     *              than or equal to zero
+     */
+    public static <T extends Comparable<T>> Matcher<T> lessThanOrEqualTo(T value) {
+        return ComparatorMatcherBuilder.<T>usingNaturalOrdering().lessThanOrEqualTo(value);
+    }
+}
diff --git a/hamcrest-library/src/main/java/org/hamcrest/number/OrderingComparisons.java b/hamcrest-library/src/main/java/org/hamcrest/number/OrderingComparisons.java
deleted file mode 100644
index 1791a40..0000000
--- a/hamcrest-library/src/main/java/org/hamcrest/number/OrderingComparisons.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.hamcrest.number;
-
-import static org.hamcrest.core.AnyOf.anyOf;
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.hamcrest.core.IsNot.not;
-import static org.hamcrest.core.DescribedAs.describedAs;
-
-import org.hamcrest.Factory;
-import org.hamcrest.Matcher;
-
-@SuppressWarnings("unchecked")
-public class OrderingComparisons {
-    @Factory
-    public static <T extends Comparable<T>> Matcher<T> greaterThan(T value) {
-        return new IsGreaterThan<T>(value);
-    }
-    
-	@Factory
-    public static <T extends Comparable<T>> Matcher<T> greaterThanOrEqualTo(T value) {
-        return describedAs("a value greater than or equal to %0", 
-                           anyOf(greaterThan(value), equalTo(value)),
-                           value);
-    }
-    
-    @Factory
-    public static <T extends Comparable<T>> Matcher<T> lessThan(T value) {
-        return describedAs("a value less than %0", 
-                           not(greaterThanOrEqualTo(value)),
-                           value);
-    }
-
-    @Factory
-    public static <T extends Comparable<T>> Matcher<T> lessThanOrEqualTo(T value) {
-        return describedAs("a value less than or equal to %0",
-                           not(greaterThan(value)),
-                           value);
-    }
-}
diff --git a/hamcrest-library/src/main/java/org/hamcrest/object/HasToString.java b/hamcrest-library/src/main/java/org/hamcrest/object/HasToString.java
index 0f12ffd..2dab9de 100644
--- a/hamcrest-library/src/main/java/org/hamcrest/object/HasToString.java
+++ b/hamcrest-library/src/main/java/org/hamcrest/object/HasToString.java
@@ -1,31 +1,43 @@
 package org.hamcrest.object;
 
-import org.hamcrest.Description;
+import org.hamcrest.FeatureMatcher;
 import org.hamcrest.Matcher;
-import org.hamcrest.Factory;
-import org.hamcrest.BaseMatcher;
 
-public class HasToString<T> extends BaseMatcher<T> {
+import static org.hamcrest.core.IsEqual.equalTo;
 
-    private final Matcher<String> toStringMatcher;
-
-    public HasToString(Matcher<String> toStringMatcher) {
-        this.toStringMatcher = toStringMatcher;
-    }
-
-    public boolean matches(Object item) {
-        return item != null && toStringMatcher.matches(item.toString());
-    }
-
-    public void describeTo(Description description) {
-        description
-	        .appendText("asString(")
-	        .appendDescriptionOf(toStringMatcher)
-	        .appendText(")");
+public class HasToString<T> extends FeatureMatcher<T, String> {
+    public HasToString(Matcher<? super String> toStringMatcher) {
+      super(toStringMatcher, "with toString()", "toString()");
     }
     
-    @Factory
-    public static <T> Matcher<T> hasToString(Matcher<String> toStringMatcher) {
+    @Override
+    protected String featureValueOf(T actual) {
+      return String.valueOf(actual);
+    }
+
+    /**
+     * Creates a matcher that matches any examined object whose <code>toString</code> method
+     * returns a value that satisfies the specified matcher.
+     * For example:
+     * <pre>assertThat(true, hasToString(equalTo("TRUE")))</pre>
+     * 
+     * @param toStringMatcher
+     *     the matcher used to verify the toString result
+     */
+    public static <T> Matcher<T> hasToString(Matcher<? super String> toStringMatcher) {
         return new HasToString<T>(toStringMatcher);
     }
+
+    /**
+     * Creates a matcher that matches any examined object whose <code>toString</code> method
+     * returns a value equalTo the specified string.
+     * For example:
+     * <pre>assertThat(true, hasToString("TRUE"))</pre>
+     * 
+     * @param expectedToString
+     *     the expected toString result
+     */
+    public static <T> Matcher<T> hasToString(String expectedToString) {
+        return new HasToString<T>(equalTo(expectedToString));
+    }
 }
diff --git a/hamcrest-library/src/main/java/org/hamcrest/object/IsCompatibleType.java b/hamcrest-library/src/main/java/org/hamcrest/object/IsCompatibleType.java
index 3a2dc7a..e1410a4 100644
--- a/hamcrest-library/src/main/java/org/hamcrest/object/IsCompatibleType.java
+++ b/hamcrest-library/src/main/java/org/hamcrest/object/IsCompatibleType.java
@@ -2,7 +2,6 @@
 
 import org.hamcrest.Description;
 import org.hamcrest.Matcher;
-import org.hamcrest.Factory;
 import org.hamcrest.TypeSafeMatcher;
 
 public class IsCompatibleType<T> extends TypeSafeMatcher<Class<?>> {
@@ -12,15 +11,30 @@
         this.type = type;
     }
     
+    @Override
     public boolean matchesSafely(Class<?> cls) {
         return type.isAssignableFrom(cls);
     }
     
+    @Override
+    public void describeMismatchSafely(Class<?> cls, Description mismatchDescription) {
+      mismatchDescription.appendValue(cls.getName());
+    }
+    
+    @Override
     public void describeTo(Description description) {
         description.appendText("type < ").appendText(type.getName());
     }
     
-    @Factory
+    /**
+     * Creates a matcher of {@link Class} that matches when the specified baseType is
+     * assignable from the examined class.
+     * For example:
+     * <pre>assertThat(Integer.class, typeCompatibleWith(Number.class))</pre>
+     * 
+     * @param baseType
+     *     the base class to examine classes against
+     */
     public static <T> Matcher<Class<?>> typeCompatibleWith(Class<T> baseType) {
         return new IsCompatibleType<T>(baseType);
     }
diff --git a/hamcrest-library/src/main/java/org/hamcrest/object/IsEventFrom.java b/hamcrest-library/src/main/java/org/hamcrest/object/IsEventFrom.java
index 504a8f5..43b64d4 100644
--- a/hamcrest-library/src/main/java/org/hamcrest/object/IsEventFrom.java
+++ b/hamcrest-library/src/main/java/org/hamcrest/object/IsEventFrom.java
@@ -1,11 +1,8 @@
-/*  Copyright (c) 2000-2006 hamcrest.org
- */
 package org.hamcrest.object;
 
 import org.hamcrest.Description;
 import org.hamcrest.Matcher;
-import org.hamcrest.Factory;
-import org.hamcrest.TypeSafeMatcher;
+import org.hamcrest.TypeSafeDiagnosingMatcher;
 
 import java.util.EventObject;
 
@@ -13,24 +10,35 @@
 /**
  * Tests if the value is an event announced by a specific object.
  */
-public class IsEventFrom extends TypeSafeMatcher<EventObject> {
-    private final Class eventClass;
+public class IsEventFrom extends TypeSafeDiagnosingMatcher<EventObject> {
+    private final Class<?> eventClass;
     private final Object source;
 
-    public IsEventFrom(Class eventClass, Object source) {
+    public IsEventFrom(Class<?> eventClass, Object source) {
         this.eventClass = eventClass;
         this.source = source;
     }
 
-    public boolean matchesSafely(EventObject item) {
-        return eventClass.isInstance(item)
-                && eventHasSameSource(item);
+    @Override
+    public boolean matchesSafely(EventObject item, Description mismatchDescription) {
+        if (!eventClass.isInstance(item)) {
+          mismatchDescription.appendText("item type was " + item.getClass().getName());
+          return false;
+        }
+        
+        if (!eventHasSameSource(item)) {
+          mismatchDescription.appendText("source was ").appendValue(item.getSource());
+          return false;
+        }
+        return true;
     }
 
+    
     private boolean eventHasSameSource(EventObject ev) {
         return ev.getSource() == source;
     }
 
+    @Override
     public void describeTo(Description description) {
         description.appendText("an event of type ")
                 .appendText(eventClass.getName())
@@ -39,20 +47,29 @@
     }
 
     /**
-     * Constructs an IsEventFrom Matcher that returns true for any object
+     * Creates a matcher of {@link java.util.EventObject} that matches any object
      * derived from <var>eventClass</var> announced by <var>source</var>.
+     * For example:
+     * <pre>assertThat(myEvent, is(eventFrom(PropertyChangeEvent.class, myBean)))</pre>
+     * 
+     * @param eventClass
+     *     the class of the event to match on
+     * @param source
+     *     the source of the event
      */
-    @Factory
     public static Matcher<EventObject> eventFrom(Class<? extends EventObject> eventClass, Object source) {
         return new IsEventFrom(eventClass, source);
     }
 
     /**
-     * Constructs an IsEventFrom Matcher that returns true for any object
-     * derived from {@link java.util.EventObject} announced by <var>source
-     * </var>.
+     * Creates a matcher of {@link java.util.EventObject} that matches any EventObject
+     * announced by <var>source</var>.
+     * For example:
+     * <pre>assertThat(myEvent, is(eventFrom(myBean)))</pre>
+     * 
+     * @param source
+     *     the source of the event
      */
-    @Factory
     public static Matcher<EventObject> eventFrom(Object source) {
         return eventFrom(EventObject.class, source);
     }
diff --git a/hamcrest-library/src/main/java/org/hamcrest/text/IsBlankString.java b/hamcrest-library/src/main/java/org/hamcrest/text/IsBlankString.java
new file mode 100644
index 0000000..b168541
--- /dev/null
+++ b/hamcrest-library/src/main/java/org/hamcrest/text/IsBlankString.java
@@ -0,0 +1,55 @@
+
+package org.hamcrest.text;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+
+import java.util.regex.Pattern;
+
+import static org.hamcrest.core.AnyOf.anyOf;
+import static org.hamcrest.core.IsNull.nullValue;
+
+/**
+ * Matches blank Strings (and null).
+ */
+public final class IsBlankString extends TypeSafeMatcher<String> {
+    private static final IsBlankString BLANK_INSTANCE = new IsBlankString();
+    @SuppressWarnings("unchecked")
+    private static final Matcher<String> NULL_OR_BLANK_INSTANCE = anyOf(nullValue(), BLANK_INSTANCE);
+
+    private static final Pattern REGEX_WHITESPACE = Pattern.compile("\\s*");
+
+    private IsBlankString() { }
+
+    @Override
+    public boolean matchesSafely(String item) {
+        return REGEX_WHITESPACE.matcher(item).matches();
+    }
+
+    @Override
+    public void describeTo(Description description) {
+        description.appendText("a blank string");
+    }
+
+    /**
+     * Creates a matcher of {@link String} that matches when the examined string contains
+     * zero or more whitespace characters and nothing else.
+     * For example:
+     * <pre>assertThat("  ", is(blankString()))</pre>
+     */
+    public static Matcher<String> blankString() {
+        return BLANK_INSTANCE;
+    }
+
+    /**
+     * Creates a matcher of {@link String} that matches when the examined string is <code>null</code>, or
+     * contains zero or more whitespace characters and nothing else.
+     * For example:
+     * <pre>assertThat(((String)null), is(blankOrNullString()))</pre>
+     * 
+     */
+    public static Matcher<String> blankOrNullString() {
+        return NULL_OR_BLANK_INSTANCE;
+    }
+}
diff --git a/hamcrest-library/src/main/java/org/hamcrest/text/IsEmptyString.java b/hamcrest-library/src/main/java/org/hamcrest/text/IsEmptyString.java
new file mode 100644
index 0000000..bbe5681
--- /dev/null
+++ b/hamcrest-library/src/main/java/org/hamcrest/text/IsEmptyString.java
@@ -0,0 +1,77 @@
+
+package org.hamcrest.text;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+
+import static org.hamcrest.core.AnyOf.anyOf;
+import static org.hamcrest.core.IsNull.nullValue;
+
+/**
+ * Matches empty Strings (and null).
+ */
+public final class IsEmptyString extends TypeSafeMatcher<String> {
+    private static final IsEmptyString INSTANCE = new IsEmptyString();
+    @SuppressWarnings("unchecked")
+    private static final Matcher<String> NULL_OR_EMPTY_INSTANCE = anyOf(nullValue(), INSTANCE);
+
+    private IsEmptyString() { }
+
+    @Override
+    public boolean matchesSafely(String item) {
+        return item.equals("");
+    }
+
+    @Override
+    public void describeTo(Description description) {
+        description.appendText("an empty string");
+    }
+
+    /**
+     * Creates a matcher of {@link String} that matches when the examined string has zero length.
+     * For example:
+     * <pre>assertThat("", isEmptyString())</pre>
+     * 
+     * @deprecated use is(emptyString()) instead
+     */
+    @Deprecated
+    public static Matcher<String> isEmptyString() {
+        return emptyString();
+    }
+
+    /**
+     * Creates a matcher of {@link String} that matches when the examined string has zero length.
+     * For example:
+     * <pre>assertThat("", is(emptyString()))</pre>
+     * 
+     */
+    public static Matcher<String> emptyString() {
+        return INSTANCE;
+    }
+
+    /**
+     * Creates a matcher of {@link String} that matches when the examined string is <code>null</code>, or
+     * has zero length.
+     * For example:
+     * <pre>assertThat(((String)null), isEmptyOrNullString())</pre>
+     * 
+     * @deprecated use is(emptyOrNullString()) instead
+     * 
+     */
+    @Deprecated
+    public static Matcher<String> isEmptyOrNullString() {
+        return emptyOrNullString();
+    }
+
+    /**
+     * Creates a matcher of {@link String} that matches when the examined string is <code>null</code>, or
+     * has zero length.
+     * For example:
+     * <pre>assertThat(((String)null), is(emptyOrNullString()))</pre>
+     * 
+     */
+    public static Matcher<String> emptyOrNullString() {
+        return NULL_OR_EMPTY_INSTANCE;
+    }
+}
diff --git a/hamcrest-library/src/main/java/org/hamcrest/text/IsEqualIgnoringCase.java b/hamcrest-library/src/main/java/org/hamcrest/text/IsEqualIgnoringCase.java
index cc78c71..00586f6 100644
--- a/hamcrest-library/src/main/java/org/hamcrest/text/IsEqualIgnoringCase.java
+++ b/hamcrest-library/src/main/java/org/hamcrest/text/IsEqualIgnoringCase.java
@@ -1,42 +1,54 @@
-/*  Copyright (c) 2000-2006 hamcrest.org

- */

-package org.hamcrest.text;

-

-import org.hamcrest.Description;

-import org.hamcrest.Matcher;

-import org.hamcrest.Factory;

-import org.hamcrest.TypeSafeMatcher;

-

-/**

- * Tests if a string is equal to another string, regardless of the case.

- */

-public class IsEqualIgnoringCase extends TypeSafeMatcher<String> {

-

-    // TODO: Replace String with CharSequence to allow for easy interopability between

-    //       String, StringBuffer, StringBuilder, CharBuffer, etc (joe).

-

-    private final String string;

-

-    public IsEqualIgnoringCase(String string) {

-        if (string == null) {

-            throw new IllegalArgumentException("Non-null value required by IsEqualIgnoringCase()");

-        }

-        this.string = string;

-    }

-

-    public boolean matchesSafely(String item) {

-        return string.equalsIgnoreCase(item);

-    }

-

-    public void describeTo(Description description) {

-        description.appendText("eqIgnoringCase(")

-                .appendValue(string)

-                .appendText(")");

-    }

-

-    @Factory

-    public static Matcher<String> equalToIgnoringCase(String string) {

-        return new IsEqualIgnoringCase(string);

-    }

-

-}

+package org.hamcrest.text;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+
+/**
+ * Tests if a string is equal to another string, regardless of the case.
+ */
+public class IsEqualIgnoringCase extends TypeSafeMatcher<String> {
+
+    // TODO: Replace String with CharSequence to allow for easy interoperability between
+    //       String, StringBuffer, StringBuilder, CharBuffer, etc (joe).
+
+    private final String string;
+
+    public IsEqualIgnoringCase(String string) {
+        if (string == null) {
+            throw new IllegalArgumentException("Non-null value required by IsEqualIgnoringCase()");
+        }
+        this.string = string;
+    }
+
+    @Override
+    public boolean matchesSafely(String item) {
+        return string.equalsIgnoreCase(item);
+    }
+
+    @Override
+    public void describeMismatchSafely(String item, Description mismatchDescription) {
+      mismatchDescription.appendText("was ").appendValue(item);
+    }
+    
+    @Override
+    public void describeTo(Description description) {
+        description.appendText("equalToIgnoringCase(")
+                .appendValue(string)
+                .appendText(")");
+    }
+
+    /**
+     * Creates a matcher of {@link String} that matches when the examined string is equal to
+     * the specified expectedString, ignoring case.
+     * For example:
+     * <pre>assertThat("Foo", equalToIgnoringCase("FOO"))</pre>
+     * 
+     * @param expectedString
+     *     the expected value of matched strings
+     */
+    public static Matcher<String> equalToIgnoringCase(String expectedString) {
+        return new IsEqualIgnoringCase(expectedString);
+    }
+
+}
diff --git a/hamcrest-library/src/main/java/org/hamcrest/text/IsEqualIgnoringWhiteSpace.java b/hamcrest-library/src/main/java/org/hamcrest/text/IsEqualIgnoringWhiteSpace.java
index dd390e8..f2b706c 100644
--- a/hamcrest-library/src/main/java/org/hamcrest/text/IsEqualIgnoringWhiteSpace.java
+++ b/hamcrest-library/src/main/java/org/hamcrest/text/IsEqualIgnoringWhiteSpace.java
@@ -1,60 +1,79 @@
-/*  Copyright (c) 2000-2006 hamcrest.org

- */

-package org.hamcrest.text;

-

-import org.hamcrest.Description;

-import org.hamcrest.Matcher;

-import org.hamcrest.Factory;

-import org.hamcrest.TypeSafeMatcher;

-

-/**

- * Tests if a string is equal to another string, ignoring any changes in whitespace.

- */

-public class IsEqualIgnoringWhiteSpace extends TypeSafeMatcher<String> {

-

-    // TODO: Replace String with CharSequence to allow for easy interopability between

-    //       String, StringBuffer, StringBuilder, CharBuffer, etc (joe).

-

-    private final String string;

-

-    public IsEqualIgnoringWhiteSpace(String string) {

-        if (string == null) {

-            throw new IllegalArgumentException("Non-null value required by IsEqualIgnoringCase()");

-        }

-        this.string = string;

-    }

-

-    public boolean matchesSafely(String item) {

-        return stripSpace(string).equalsIgnoreCase(stripSpace(item));

-    }

-

-    public void describeTo(Description description) {

-        description.appendText("eqIgnoringWhiteSpace(")

-                .appendValue(string)

-                .appendText(")");

-    }

-

-    public String stripSpace(String string) {

-        StringBuilder result = new StringBuilder();

-        boolean lastWasSpace = true;

-        for (int i = 0; i < string.length(); i++) {

-            char c = string.charAt(i);

-            if (Character.isWhitespace(c)) {

-                if (!lastWasSpace) {

-                    result.append(' ');

-                }

-                lastWasSpace = true;

-            } else {

-                result.append(c);

-                lastWasSpace = false;

-            }

-        }

-        return result.toString().trim();

-    }

-

-    @Factory

-    public static Matcher<String> equalToIgnoringWhiteSpace(String string) {

-        return new IsEqualIgnoringWhiteSpace(string);

-    }

-

-}

+package org.hamcrest.text;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+
+import static java.lang.Character.isWhitespace;
+
+/**
+ * Tests if a string is equal to another string, ignoring any changes in whitespace.
+ */
+public class IsEqualIgnoringWhiteSpace extends TypeSafeMatcher<String> {
+
+    // TODO: Replace String with CharSequence to allow for easy interoperability between
+    //       String, StringBuffer, StringBuilder, CharBuffer, etc (joe).
+
+    private final String string;
+
+    public IsEqualIgnoringWhiteSpace(String string) {
+        if (string == null) {
+            throw new IllegalArgumentException("Non-null value required by IsEqualIgnoringCase()");
+        }
+        this.string = string;
+    }
+
+    @Override
+    public boolean matchesSafely(String item) {
+        return stripSpace(string).equalsIgnoreCase(stripSpace(item));
+    }
+    
+    @Override
+    public void describeMismatchSafely(String item, Description mismatchDescription) {
+      mismatchDescription.appendText("was  ").appendText(stripSpace(item));
+    }
+    
+    @Override
+    public void describeTo(Description description) {
+        description.appendText("equalToIgnoringWhiteSpace(")
+                .appendValue(string)
+                .appendText(")");
+    }
+
+    public String stripSpace(String toBeStripped) {
+        final StringBuilder result = new StringBuilder();
+        boolean lastWasSpace = true;
+        for (int i = 0; i < toBeStripped.length(); i++) {
+            char c = toBeStripped.charAt(i);
+            if (isWhitespace(c)) {
+                if (!lastWasSpace) {
+                    result.append(' ');
+                }
+                lastWasSpace = true;
+            } else {
+                result.append(c);
+                lastWasSpace = false;
+            }
+        }
+        return result.toString().trim();
+    }
+
+    /**
+     * Creates a matcher of {@link String} that matches when the examined string is equal to
+     * the specified expectedString, when whitespace differences are (mostly) ignored.  To be
+     * exact, the following whitespace rules are applied:
+     * <ul>
+     *   <li>all leading and trailing whitespace of both the expectedString and the examined string are ignored</li>
+     *   <li>any remaining whitespace, appearing within either string, is collapsed to a single space before comparison</li>
+     * </ul>
+     * For example:
+     * <pre>assertThat("   my\tfoo  bar ", equalToIgnoringWhiteSpace(" my  foo bar"))</pre>
+     * 
+     * @param expectedString
+     *     the expected value of matched strings
+     */
+    public static Matcher<String> equalToIgnoringWhiteSpace(String expectedString) {
+        return new IsEqualIgnoringWhiteSpace(expectedString);
+    }
+
+}
diff --git a/hamcrest-library/src/main/java/org/hamcrest/text/MatchesPattern.java b/hamcrest-library/src/main/java/org/hamcrest/text/MatchesPattern.java
new file mode 100644
index 0000000..e0eda0a
--- /dev/null
+++ b/hamcrest-library/src/main/java/org/hamcrest/text/MatchesPattern.java
@@ -0,0 +1,41 @@
+package org.hamcrest.text;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+
+import java.util.regex.Pattern;
+
+public class MatchesPattern extends TypeSafeMatcher<String> {
+    private final Pattern pattern;
+
+    public MatchesPattern(Pattern pattern) {
+        this.pattern = pattern;
+    }
+
+    @Override
+    protected boolean matchesSafely(String item) {
+        return pattern.matcher(item).matches();
+    }
+
+    @Override
+    public void describeTo(Description description) {
+        description.appendText("a string matching the pattern '" + pattern + "'");
+    }
+
+    /**
+     * Creates a matcher of {@link java.lang.String} that matches when the examined string
+     * exactly matches the given {@link java.util.regex.Pattern}.
+     */
+    public static Matcher<String> matchesPattern(Pattern pattern) {
+        return new MatchesPattern(pattern);
+    }
+
+    /**
+     * Creates a matcher of {@link java.lang.String} that matches when the examined string
+     * exactly matches the given regular expression, treated as a {@link java.util.regex.Pattern}.
+     */
+    public static Matcher<String> matchesPattern(String regex) {
+        return new MatchesPattern(Pattern.compile(regex));
+    }
+}
diff --git a/hamcrest-library/src/main/java/org/hamcrest/text/StringContains.java b/hamcrest-library/src/main/java/org/hamcrest/text/StringContains.java
deleted file mode 100644
index 9e55560..0000000
--- a/hamcrest-library/src/main/java/org/hamcrest/text/StringContains.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*  Copyright (c) 2000-2006 hamcrest.org
- */
-package org.hamcrest.text;
-
-import org.hamcrest.Factory;
-import org.hamcrest.Matcher;
-
-/**
- * Tests if the argument is a string that contains a substring.
- */
-public class StringContains extends SubstringMatcher {
-    public StringContains(String substring) {
-        super(substring);
-    }
-
-    protected boolean evalSubstringOf(String s) {
-        return s.indexOf(substring) >= 0;
-    }
-
-    protected String relationship() {
-        return "containing";
-    }
-
-    @Factory
-    public static Matcher<String> containsString(String substring) {
-        return new StringContains(substring);
-    }
-
-}
\ No newline at end of file
diff --git a/hamcrest-library/src/main/java/org/hamcrest/text/StringContainsInOrder.java b/hamcrest-library/src/main/java/org/hamcrest/text/StringContainsInOrder.java
new file mode 100644
index 0000000..f5d24ff
--- /dev/null
+++ b/hamcrest-library/src/main/java/org/hamcrest/text/StringContainsInOrder.java
@@ -0,0 +1,69 @@
+package org.hamcrest.text;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+
+import java.util.Arrays;
+
+public class StringContainsInOrder extends TypeSafeMatcher<String> {
+    private final Iterable<String> substrings;
+
+    public StringContainsInOrder(Iterable<String> substrings) {
+        this.substrings = substrings;
+    }
+
+    @Override
+    public boolean matchesSafely(String s) {
+        int fromIndex = 0;
+        
+        for (String substring : substrings) {
+            fromIndex = s.indexOf(substring, fromIndex);
+            if (fromIndex == -1) {
+                return false;
+            }
+        }
+        
+        return true;
+    }
+    
+    @Override
+    public void describeMismatchSafely(String item, Description mismatchDescription) {
+        mismatchDescription.appendText("was \"").appendText(item).appendText("\"");
+    }
+    
+    @Override
+    public void describeTo(Description description) {
+        description.appendText("a string containing ")
+                   .appendValueList("", ", ", "", substrings)
+                   .appendText(" in order");
+    }
+    
+    /**
+     * Creates a matcher of {@link String} that matches when the examined string contains all of
+     * the specified substrings, considering the order of their appearance.
+     * For example:
+     * <pre>assertThat("myfoobarbaz", stringContainsInOrder(Arrays.asList("bar", "foo")))</pre>
+     * fails as "foo" occurs before "bar" in the string "myfoobarbaz"
+     * 
+     * @param substrings
+     *     the substrings that must be contained within matching strings
+     */
+    public static Matcher<String> stringContainsInOrder(Iterable<String> substrings) {
+        return new StringContainsInOrder(substrings);
+    }
+
+    /**
+     * Creates a matcher of {@link String} that matches when the examined string contains all of
+     * the specified substrings, considering the order of their appearance.
+     * For example:
+     * <pre>assertThat("myfoobarbaz", stringContainsInOrder("bar", "foo"))</pre>
+     * fails as "foo" occurs before "bar" in the string "myfoobarbaz"
+     *
+     * @param substrings
+     *     the substrings that must be contained within matching strings
+     */
+    public static Matcher<String> stringContainsInOrder(String... substrings) {
+        return new StringContainsInOrder(Arrays.asList(substrings));
+    }
+}
diff --git a/hamcrest-library/src/main/java/org/hamcrest/text/StringEndsWith.java b/hamcrest-library/src/main/java/org/hamcrest/text/StringEndsWith.java
deleted file mode 100644
index 10e4764..0000000
--- a/hamcrest-library/src/main/java/org/hamcrest/text/StringEndsWith.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*  Copyright (c) 2000-2006 hamcrest.org
- */
-package org.hamcrest.text;
-
-import org.hamcrest.Factory;
-import org.hamcrest.Matcher;
-
-/**
- * Tests if the argument is a string that contains a substring.
- */
-public class StringEndsWith extends SubstringMatcher {
-    public StringEndsWith(String substring) {
-        super(substring);
-    }
-
-    protected boolean evalSubstringOf(String s) {
-        return s.endsWith(substring);
-    }
-
-    protected String relationship() {
-        return "ending with";
-    }
-
-    @Factory
-    public static Matcher<String> endsWith(String substring) {
-        return new StringEndsWith(substring);
-    }
-
-}
diff --git a/hamcrest-library/src/main/java/org/hamcrest/text/StringStartsWith.java b/hamcrest-library/src/main/java/org/hamcrest/text/StringStartsWith.java
deleted file mode 100644
index 4613101..0000000
--- a/hamcrest-library/src/main/java/org/hamcrest/text/StringStartsWith.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*  Copyright (c) 2000-2006 hamcrest.org
- */
-package org.hamcrest.text;
-
-import org.hamcrest.Factory;
-import org.hamcrest.Matcher;
-
-/**
- * Tests if the argument is a string that contains a substring.
- */
-public class StringStartsWith extends SubstringMatcher {
-    public StringStartsWith(String substring) {
-        super(substring);
-    }
-
-    protected boolean evalSubstringOf(String s) {
-        return s.startsWith(substring);
-    }
-
-    protected String relationship() {
-        return "starting with";
-    }
-
-    @Factory
-    public static Matcher<String> startsWith(String substring) {
-        return new StringStartsWith(substring);
-    }
-
-}
\ No newline at end of file
diff --git a/hamcrest-library/src/main/java/org/hamcrest/text/SubstringMatcher.java b/hamcrest-library/src/main/java/org/hamcrest/text/SubstringMatcher.java
deleted file mode 100644
index 8ebe739..0000000
--- a/hamcrest-library/src/main/java/org/hamcrest/text/SubstringMatcher.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package org.hamcrest.text;
-
-import org.hamcrest.Description;
-import org.hamcrest.TypeSafeMatcher;
-
-public abstract class SubstringMatcher extends TypeSafeMatcher<String> {
-
-    // TODO: Replace String with CharSequence to allow for easy interopability between
-    //       String, StringBuffer, StringBuilder, CharBuffer, etc (joe).
-
-    protected final String substring;
-
-    protected SubstringMatcher(final String substring) {
-        this.substring = substring;
-    }
-
-    public boolean matchesSafely(String item) {
-        return evalSubstringOf(item);
-    }
-
-    public void describeTo(Description description) {
-        description.appendText("a string ")
-                .appendText(relationship())
-                .appendText(" ")
-                .appendValue(substring);
-    }
-
-    protected abstract boolean evalSubstringOf(String string);
-
-    protected abstract String relationship();
-}
\ No newline at end of file
diff --git a/hamcrest-library/src/main/java/org/hamcrest/text/X.java b/hamcrest-library/src/main/java/org/hamcrest/text/X.java
deleted file mode 100644
index 7e85bd9..0000000
--- a/hamcrest-library/src/main/java/org/hamcrest/text/X.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.hamcrest.text;
-
-import org.hamcrest.Matcher;
-import org.hamcrest.CoreMatchers;
-
-public class X {
-
-    public static void main(String[] args) {
-
-        x(CoreMatchers.any(String.class));
-
-
-    }
-
-    private static void x(Matcher<String> s) {
-
-    }
-}
diff --git a/hamcrest-library/src/main/java/org/hamcrest/xml/HasXPath.java b/hamcrest-library/src/main/java/org/hamcrest/xml/HasXPath.java
index 742935b..30ed081 100644
--- a/hamcrest-library/src/main/java/org/hamcrest/xml/HasXPath.java
+++ b/hamcrest-library/src/main/java/org/hamcrest/xml/HasXPath.java
@@ -1,27 +1,34 @@
 package org.hamcrest.xml;
 
+import org.hamcrest.Condition;
 import org.hamcrest.Description;
-import org.hamcrest.Factory;
 import org.hamcrest.Matcher;
-import org.hamcrest.TypeSafeMatcher;
+import org.hamcrest.TypeSafeDiagnosingMatcher;
+import org.hamcrest.core.IsAnything;
 import org.w3c.dom.Node;
 
-import javax.xml.xpath.XPath;
-import javax.xml.xpath.XPathConstants;
-import javax.xml.xpath.XPathExpression;
-import javax.xml.xpath.XPathExpressionException;
-import javax.xml.xpath.XPathFactory;
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.namespace.QName;
+import javax.xml.xpath.*;
+
+import static javax.xml.xpath.XPathConstants.STRING;
+import static org.hamcrest.Condition.matched;
+import static org.hamcrest.Condition.notMatched;
 
 /**
  * Applies a Matcher to a given XML Node in an existing XML Node tree, specified by an XPath expression.
  *
  * @author Joe Walnes
+ * @author Steve Freeman
  */
-public class HasXPath extends TypeSafeMatcher<Node> {
-
+public class HasXPath extends TypeSafeDiagnosingMatcher<Node> {
+    public static final NamespaceContext NO_NAMESPACE_CONTEXT = null;
+    private static final IsAnything<String> WITH_ANY_CONTENT = new IsAnything<String>("");
+    private static final Condition.Step<Object,String> NODE_EXISTS = nodeExists();
     private final Matcher<String> valueMatcher;
     private final XPathExpression compiledXPath;
     private final String xpathString;
+    private final QName evaluationMode;
 
     /**
      * @param xPathExpression XPath expression.
@@ -29,46 +36,134 @@
      *                     May be null to specify that the XPath must exist but the value is irrelevant.
      */
     public HasXPath(String xPathExpression, Matcher<String> valueMatcher) {
-        try {
-            XPath xPath = XPathFactory.newInstance().newXPath();
-            compiledXPath = xPath.compile(xPathExpression);
-            this.xpathString = xPathExpression;
-            this.valueMatcher = valueMatcher;
-        } catch (XPathExpressionException e) {
-            throw new IllegalArgumentException("Invalid XPath : " + xPathExpression, e);
-        }
+        this(xPathExpression, NO_NAMESPACE_CONTEXT, valueMatcher);
     }
 
-    public boolean matchesSafely(Node item) {
-        try {
-            String result = (String) compiledXPath.evaluate(item, XPathConstants.STRING);
-            if (result == null) {
-                return false;
-            } else if (valueMatcher == null) {
-                return !result.equals("");
-            } else {
-                return valueMatcher.matches(result);
-            }
-        } catch (XPathExpressionException e) {
-            return false;
-        }
+    /**
+     * @param xPathExpression XPath expression.
+     * @param namespaceContext Resolves XML namespace prefixes in the XPath expression
+     * @param valueMatcher Matcher to use at given XPath.
+     *                     May be null to specify that the XPath must exist but the value is irrelevant.
+     */
+    public HasXPath(String xPathExpression, NamespaceContext namespaceContext, Matcher<String> valueMatcher) {
+        this(xPathExpression, namespaceContext, valueMatcher, STRING);
     }
 
+    private HasXPath(String xPathExpression, NamespaceContext namespaceContext, Matcher<String> valueMatcher, QName mode) {
+        this.compiledXPath = compiledXPath(xPathExpression, namespaceContext);
+        this.xpathString = xPathExpression;
+        this.valueMatcher = valueMatcher;
+        this.evaluationMode = mode;
+    }
+
+    @Override
+    public boolean matchesSafely(Node item, Description mismatch) {
+        return evaluated(item, mismatch)
+               .and(NODE_EXISTS)
+               .matching(valueMatcher);
+    }
+
+    @Override
     public void describeTo(Description description) {
         description.appendText("an XML document with XPath ").appendText(xpathString);
         if (valueMatcher != null) {
             description.appendText(" ").appendDescriptionOf(valueMatcher);
         }
     }
-    
-    @Factory
+
+    private Condition<Object> evaluated(Node item, Description mismatch) {
+        try {
+            return matched(compiledXPath.evaluate(item, evaluationMode), mismatch);
+        } catch (XPathExpressionException e) {
+            mismatch.appendText(e.getMessage());
+        }
+        return notMatched();
+    }
+
+    private static Condition.Step<Object, String> nodeExists() {
+        return new Condition.Step<Object, String>() {
+            @Override
+            public Condition<String> apply(Object value, Description mismatch) {
+                if (value == null) {
+                    mismatch.appendText("xpath returned no results.");
+                    return notMatched();
+                }
+                return matched(String.valueOf(value), mismatch);
+            }
+        };
+    }
+
+    private static XPathExpression compiledXPath(String xPathExpression, NamespaceContext namespaceContext) {
+        try {
+            final XPath xPath = XPathFactory.newInstance().newXPath();
+            if (namespaceContext != null) {
+                xPath.setNamespaceContext(namespaceContext);
+            }
+            return xPath.compile(xPathExpression);
+        } catch (XPathExpressionException e) {
+            throw new IllegalArgumentException("Invalid XPath : " + xPathExpression, e);
+        }
+    }
+
+
+    /**
+     * Creates a matcher of {@link org.w3c.dom.Node}s that matches when the examined node has a value at the
+     * specified <code>xPath</code> that satisfies the specified <code>valueMatcher</code>.
+     * For example:
+     * <pre>assertThat(xml, hasXPath("/root/something[2]/cheese", equalTo("Cheddar")))</pre>
+     * 
+     * @param xPath
+     *     the target xpath
+     * @param valueMatcher
+     *     matcher for the value at the specified xpath
+     */
     public static Matcher<Node> hasXPath(String xPath, Matcher<String> valueMatcher) {
-        return new HasXPath(xPath, valueMatcher);
+        return hasXPath(xPath, NO_NAMESPACE_CONTEXT, valueMatcher);
     }
 
-    @Factory
+    /**
+     * Creates a matcher of {@link org.w3c.dom.Node}s that matches when the examined node has a value at the
+     * specified <code>xPath</code>, within the specified <code>namespaceContext</code>, that satisfies
+     * the specified <code>valueMatcher</code>.
+     * For example:
+     * <pre>assertThat(xml, hasXPath("/root/something[2]/cheese", myNs, equalTo("Cheddar")))</pre>
+     * 
+     * @param xPath
+     *     the target xpath
+     * @param namespaceContext
+     *     the namespace for matching nodes
+     * @param valueMatcher
+     *     matcher for the value at the specified xpath
+     */
+    public static Matcher<Node> hasXPath(String xPath, NamespaceContext namespaceContext, Matcher<String> valueMatcher) {
+        return new HasXPath(xPath, namespaceContext, valueMatcher, STRING);
+    }
+
+    /**
+     * Creates a matcher of {@link org.w3c.dom.Node}s that matches when the examined node contains a node
+     * at the specified <code>xPath</code>, with any content.
+     * For example:
+     * <pre>assertThat(xml, hasXPath("/root/something[2]/cheese"))</pre>
+     * 
+     * @param xPath
+     *     the target xpath
+     */
     public static Matcher<Node> hasXPath(String xPath) {
-        return hasXPath(xPath, null);
+        return hasXPath(xPath, NO_NAMESPACE_CONTEXT);
     }
 
+    /**
+     * Creates a matcher of {@link org.w3c.dom.Node}s that matches when the examined node contains a node
+     * at the specified <code>xPath</code> within the specified namespace context, with any content.
+     * For example:
+     * <pre>assertThat(xml, hasXPath("/root/something[2]/cheese", myNs))</pre>
+     * 
+     * @param xPath
+     *     the target xpath
+     * @param namespaceContext
+     *     the namespace for matching nodes
+     */
+    public static Matcher<Node> hasXPath(String xPath, NamespaceContext namespaceContext) {
+        return new HasXPath(xPath, namespaceContext, WITH_ANY_CONTENT, XPathConstants.NODE);
+    }
 }
diff --git a/hamcrest-library/src/test/java/org/hamcrest/beans/HasPropertyTest.java b/hamcrest-library/src/test/java/org/hamcrest/beans/HasPropertyTest.java
new file mode 100644
index 0000000..314797f
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/beans/HasPropertyTest.java
@@ -0,0 +1,48 @@
+package org.hamcrest.beans;
+
+import org.hamcrest.Matcher;
+import org.junit.Test;
+
+import static org.hamcrest.AbstractMatcherTest.*;
+import static org.hamcrest.beans.HasProperty.hasProperty;
+
+/**
+ * @author Iain McGinniss
+ * @author Nat Pryce
+ * @author Steve Freeman
+ * @author Tom Denley
+ * @since 1.1.0
+ */
+public final class HasPropertyTest {
+
+    private final HasPropertyWithValueTest.BeanWithoutInfo bean = new HasPropertyWithValueTest.BeanWithoutInfo("a bean");
+
+    @Test public void
+    copesWithNullsAndUnknownTypes() {
+        Matcher<Object> matcher = hasProperty("irrelevant");
+        
+        assertNullSafe(matcher);
+        assertUnknownTypeSafe(matcher);
+    }
+
+    @Test public void
+    matchesWhenThePropertyExists() {
+        assertMatches(hasProperty("writeOnlyProperty"), bean);
+    }
+
+    @Test public void
+    doesNotMatchIfPropertyDoesNotExist() {
+        assertDoesNotMatch(hasProperty("aNonExistentProp"), bean);
+    }
+
+    @Test public void
+    describesItself() {
+        assertDescription("hasProperty(\"property\")", hasProperty("property"));
+    }
+
+    @Test public void
+    describesAMismatch() {
+        assertMismatchDescription("no \"aNonExistentProp\" in <[Person: a bean]>",
+                                  hasProperty("aNonExistentProp"), bean);
+    }
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/beans/HasPropertyWithValueTest.java b/hamcrest-library/src/test/java/org/hamcrest/beans/HasPropertyWithValueTest.java
new file mode 100644
index 0000000..eeaa113
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/beans/HasPropertyWithValueTest.java
@@ -0,0 +1,139 @@
+package org.hamcrest.beans;
+
+import org.hamcrest.AbstractMatcherTest;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.StringDescription;
+import org.hamcrest.core.IsEqual;
+
+import java.beans.IntrospectionException;
+import java.beans.PropertyDescriptor;
+import java.beans.SimpleBeanInfo;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.beans.HasPropertyWithValue.hasProperty;
+import static org.hamcrest.core.IsAnything.anything;
+import static org.hamcrest.core.IsEqual.equalTo;
+
+/**
+ * @author Iain McGinniss
+ * @author Nat Pryce
+ * @author Steve Freeman
+ * @since 1.1.0
+ */
+@SuppressWarnings("UnusedDeclaration")
+public class HasPropertyWithValueTest extends AbstractMatcherTest {
+  private final BeanWithoutInfo shouldMatch = new BeanWithoutInfo("is expected");
+  private final BeanWithoutInfo shouldNotMatch = new BeanWithoutInfo("not expected");
+
+  private final BeanWithInfo beanWithInfo = new BeanWithInfo("with info");
+
+  @Override
+  protected Matcher<?> createMatcher() {
+    return hasProperty("irrelevant", anything());
+  }
+
+  public void testMatchesInfolessBeanWithMatchedNamedProperty() {
+    assertMatches("with property", hasProperty("property", equalTo("is expected")), shouldMatch);
+    assertMismatchDescription("property 'property' was \"not expected\"", 
+                              hasProperty("property", equalTo("is expected")), shouldNotMatch);
+  }
+
+  public void testMatchesBeanWithInfoWithMatchedNamedProperty() {
+    assertMatches("with bean info", hasProperty("property", equalTo("with info")), beanWithInfo);
+    assertMismatchDescription("property 'property' was \"with info\"", 
+        hasProperty("property", equalTo("without info")), beanWithInfo);
+  }
+
+  public void testDoesNotMatchInfolessBeanWithoutMatchedNamedProperty() {
+    assertMismatchDescription("No property \"nonExistentProperty\"", 
+                              hasProperty("nonExistentProperty", anything()), shouldNotMatch);
+   }
+
+  public void testDoesNotMatchWriteOnlyProperty() {
+    assertMismatchDescription("property \"writeOnlyProperty\" is not readable",
+                              hasProperty("writeOnlyProperty", anything()), shouldNotMatch); 
+  }
+
+  public void testDescribeTo() {
+    assertDescription("hasProperty(\"property\", <true>)", hasProperty("property", equalTo(true)));
+  }
+
+  public void testMatchesPropertyAndValue() {
+    assertMatches("property with value", hasProperty( "property", anything()), beanWithInfo);
+  }
+  
+  public void testDoesNotWriteMismatchIfPropertyMatches() {
+    Description description = new StringDescription();
+    hasProperty( "property", anything()).describeMismatch(beanWithInfo, description);
+    assertEquals("Expected mismatch description", "", description.toString());
+  }
+
+  public void testDescribesMissingPropertyMismatch() {
+    assertMismatchDescription("No property \"honk\"", hasProperty( "honk", anything()), shouldNotMatch);
+  }
+
+  public void testCanAccessAnAnonymousInnerClass() {
+    class X implements IX {
+      @Override
+      public int getTest() {
+        return 1;
+      }
+    }
+
+    assertThat(new X(), HasPropertyWithValue.hasProperty("test", IsEqual.equalTo(1)));
+  }
+
+  interface IX {
+    int getTest();
+  }
+
+  public static class BeanWithoutInfo {
+    private String property;
+
+    public BeanWithoutInfo(String property) {
+      this.property = property;
+    }
+
+    public String getProperty() {
+      return property;
+    }
+
+    public void setProperty(String property) {
+      this.property = property;
+    }
+
+    public void setWriteOnlyProperty(@SuppressWarnings("unused") float property) {
+    }
+
+    @Override
+    public String toString() {
+      return "[Person: " + property + "]";
+    }
+  }
+
+  public static class BeanWithInfo {
+    private final String propertyValue;
+
+    public BeanWithInfo(String propertyValue) {
+      this.propertyValue = propertyValue;
+    }
+
+    public String property() {
+      return propertyValue;
+    }
+  }
+
+  public static class BeanWithInfoBeanInfo extends SimpleBeanInfo {
+    @Override
+    public PropertyDescriptor[] getPropertyDescriptors() {
+      try {
+        return new PropertyDescriptor[] { 
+            new PropertyDescriptor("property", BeanWithInfo.class, "property", null) 
+          };
+      } catch (IntrospectionException e) {
+        throw new RuntimeException("Introspection exception: " + e.getMessage());
+      }
+    }
+  }
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/beans/SamePropertyValuesAsTest.java b/hamcrest-library/src/test/java/org/hamcrest/beans/SamePropertyValuesAsTest.java
new file mode 100644
index 0000000..173457f
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/beans/SamePropertyValuesAsTest.java
@@ -0,0 +1,98 @@
+package org.hamcrest.beans;
+
+import org.hamcrest.AbstractMatcherTest;
+import org.hamcrest.Matcher;
+
+import static org.hamcrest.beans.SamePropertyValuesAs.samePropertyValuesAs;
+
+@SuppressWarnings("UnusedDeclaration")
+public class SamePropertyValuesAsTest extends AbstractMatcherTest {
+  private static final Value aValue = new Value("expected");
+  private static final ExampleBean expectedBean = new ExampleBean("same", 1, aValue);
+  private static final ExampleBean actualBean = new ExampleBean("same", 1, aValue);
+  
+  
+  @Override
+  protected Matcher<?> createMatcher() {
+    return samePropertyValuesAs(expectedBean);
+  }
+
+  public void testReportsMatchWhenAllPropertiesMatch() {
+    assertMatches("matched properties", samePropertyValuesAs(expectedBean), actualBean);
+  }
+  
+  public void testReportsMismatchWhenActualTypeIsNotAssignableToExpectedType() {
+    assertMismatchDescription("is incompatible type: ExampleBean", 
+                              samePropertyValuesAs((Object)aValue), actualBean);
+  }
+
+  public void testReportsMismatchOnFirstPropertyDifference() {
+    assertMismatchDescription("string was \"different\"", 
+        samePropertyValuesAs(expectedBean), new ExampleBean("different", 1, aValue));
+    assertMismatchDescription("int was <2>", 
+        samePropertyValuesAs(expectedBean), new ExampleBean("same", 2, aValue));
+    assertMismatchDescription("value was <Value other>", 
+        samePropertyValuesAs(expectedBean), new ExampleBean("same", 1, new Value("other")));
+  }
+
+  public void testMatchesBeansWithInheritanceButNoExtraProperties() {
+    assertMatches("sub type with same properties", 
+        samePropertyValuesAs(expectedBean), new SubBeanWithNoExtraProperties("same", 1, aValue));
+  }
+
+  public void testRejectsSubTypeThatHasExtraProperties() {
+    assertMismatchDescription("has extra properties called [extra]", 
+        samePropertyValuesAs(expectedBean), new SubBeanWithExtraProperty("same", 1, aValue));
+  }
+  
+  public void testDescribesItself() {
+    assertDescription("same property values as ExampleBean [int: <1>, string: \"same\", value: <Value expected>]", samePropertyValuesAs(expectedBean));
+  }
+
+  public static class Value {
+    public Value(Object value) {
+      this.value = value;
+    }
+
+    public final Object value;
+    @Override
+    public String toString() {
+      return "Value " + value;
+    }
+  }
+  
+  public static class ExampleBean {
+    private String stringProperty;
+    private int intProperty;
+    private Value valueProperty;
+
+    public ExampleBean(String stringProperty, int intProperty, Value valueProperty) {
+      this.stringProperty = stringProperty;
+      this.intProperty = intProperty;
+      this.valueProperty = valueProperty;
+    }
+    
+    public String getString() {
+      return stringProperty;
+    }
+    public int getInt() {
+      return intProperty;
+    }
+    public Value getValue() {
+      return valueProperty;
+    }
+  }
+  
+  public static class SubBeanWithNoExtraProperties extends ExampleBean {
+    public SubBeanWithNoExtraProperties(String stringProperty, int intProperty, Value valueProperty) {
+      super(stringProperty, intProperty, valueProperty);
+    }
+  }
+  
+  public static class SubBeanWithExtraProperty extends ExampleBean {
+    public SubBeanWithExtraProperty(String stringProperty, int intProperty, Value valueProperty) {
+      super(stringProperty, intProperty, valueProperty);
+    }
+    public String getExtra() { return "extra"; }
+  }
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsArrayContainingInAnyOrderTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsArrayContainingInAnyOrderTest.java
new file mode 100644
index 0000000..d4dc270
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsArrayContainingInAnyOrderTest.java
@@ -0,0 +1,43 @@
+package org.hamcrest.collection;
+
+import org.hamcrest.AbstractMatcherTest;
+import org.hamcrest.Matcher;
+
+import static org.hamcrest.collection.IsArrayContainingInAnyOrder.arrayContainingInAnyOrder;
+import static org.hamcrest.core.IsEqual.equalTo;
+
+public class IsArrayContainingInAnyOrderTest extends AbstractMatcherTest {
+
+    @SuppressWarnings("unchecked")
+    @Override
+    protected Matcher<?> createMatcher() {
+        return arrayContainingInAnyOrder(equalTo(1), equalTo(2));
+    }
+
+    @SuppressWarnings("unchecked")
+    public void testHasAReadableDescription() {
+        assertDescription("[<1>, <2>] in any order", arrayContainingInAnyOrder(equalTo(1), equalTo(2)));
+        assertDescription("[<1>, <2>] in any order", arrayContainingInAnyOrder(1, 2));
+    }
+    
+    public void testMatchesItemsInAnyOrder() {
+      assertMatches("in order", arrayContainingInAnyOrder(1, 2, 3), new Integer[] {1, 2, 3});
+      assertMatches("out of order", arrayContainingInAnyOrder(1, 2, 3), new Integer[] {3, 2, 1});
+      assertMatches("single", arrayContainingInAnyOrder(1), new Integer[] {1});
+    }
+
+    @SuppressWarnings("unchecked")
+    public void testAppliesMatchersInAnyOrder() {
+      assertMatches("in order", arrayContainingInAnyOrder(equalTo(1), equalTo(2), equalTo(3)), new Integer[] {1, 2, 3});
+      assertMatches("out of order", arrayContainingInAnyOrder(equalTo(1), equalTo(2), equalTo(3)), new Integer[] {3, 2, 1});
+      assertMatches("single", arrayContainingInAnyOrder(equalTo(1)), new Integer[] {1});
+    }
+
+    public void testMismatchesItemsInAnyOrder() {
+      Matcher<Integer[]> matcher = arrayContainingInAnyOrder(1, 2, 3);
+      assertMismatchDescription("was null", matcher, null);
+      assertMismatchDescription("no item matches: <1>, <2>, <3> in []", matcher, new Integer[] {});
+      assertMismatchDescription("no item matches: <2>, <3> in [<1>]", matcher, new Integer[] {1});
+      assertMismatchDescription("not matched: <4>", matcher, new Integer[] {4,3,2,1});
+    }
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsArrayContainingInOrderTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsArrayContainingInOrderTest.java
new file mode 100644
index 0000000..ab1d821
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsArrayContainingInOrderTest.java
@@ -0,0 +1,45 @@
+package org.hamcrest.collection;
+
+import org.hamcrest.AbstractMatcherTest;
+import org.hamcrest.Matcher;
+
+import static org.hamcrest.collection.IsArrayContainingInOrder.arrayContaining;
+import static org.hamcrest.core.IsEqual.equalTo;
+
+public class IsArrayContainingInOrderTest extends AbstractMatcherTest {
+
+    @SuppressWarnings("unchecked")
+    @Override
+    protected Matcher<?> createMatcher() {
+        return arrayContaining(equalTo(1), equalTo(2));
+    }
+
+    @SuppressWarnings("unchecked")
+    public void testHasAReadableDescription() {
+        assertDescription("[<1>, <2>]", arrayContaining(equalTo(1), equalTo(2)));
+    }
+    
+    public void testMatchesItemsInOrder() {
+      assertMatches("in order", arrayContaining(1, 2, 3), new Integer[] {1, 2, 3});
+      assertMatches("single", arrayContaining(1), new Integer[] {1});
+    }
+
+    @SuppressWarnings("unchecked")
+    public void testAppliesMatchersInOrder() {
+      assertMatches("in order", arrayContaining(equalTo(1), equalTo(2), equalTo(3)), new Integer[] {1, 2, 3});
+      assertMatches("single", arrayContaining(equalTo(1)), new Integer[] {1});
+    }
+    
+    public void testMismatchesItemsInOrder() {
+      Matcher<Integer[]> matcher = arrayContaining(1, 2, 3);
+      assertMismatchDescription("was null", matcher, null);
+      assertMismatchDescription("no item was <1>", matcher, new Integer[] {});
+      assertMismatchDescription("no item was <2>", matcher, new Integer[] {1});
+      assertMismatchDescription("item 0: was <4>", matcher, new Integer[] {4,3,2,1});
+      assertMismatchDescription("item 2: was <4>", matcher, new Integer[] {1,2, 4});
+    }
+
+    public void testCanHandleNullValuesInAnArray() {
+      assertMatches("with nulls", arrayContaining(null, null), new Object[]{null, null});
+    }
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsArrayContainingTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsArrayContainingTest.java
new file mode 100644
index 0000000..275984c
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsArrayContainingTest.java
@@ -0,0 +1,72 @@
+package org.hamcrest.collection;
+
+import org.hamcrest.AbstractMatcherTest;
+import org.hamcrest.Matcher;
+
+import static org.hamcrest.collection.IsArrayContaining.hasItemInArray;
+
+public class IsArrayContainingTest extends AbstractMatcherTest {
+
+    @Override
+    protected Matcher<?> createMatcher() {
+        return hasItemInArray("irrelevant");
+    }
+
+    public void testMatchesAnArrayThatContainsAnElementMatchingTheGivenMatcher() {
+        assertMatches("should matches array that contains 'a'",
+                hasItemInArray("a"), new String[]{"a", "b", "c"});
+    }
+
+    public void testDoesNotMatchAnArrayThatDoesntContainAnElementMatchingTheGivenMatcher() {
+        assertDoesNotMatch("should not matches array that doesn't contain 'a'",
+                hasItemInArray("a"), new String[]{"b", "c"});
+        assertDoesNotMatch("should not matches empty array",
+                hasItemInArray("a"), new String[0]);
+    }
+
+    public void testDoesNotMatchNull() {
+        assertDoesNotMatch("should not matches null",
+                hasItemInArray("a"), null);
+    }
+
+    public void testHasAReadableDescription() {
+        assertDescription("an array containing \"a\"", hasItemInArray("a"));
+    }
+
+    // Remaining code no longer compiles, thanks to generics. I think that's a good thing, but
+    // I still need to investigate how this behaves with code that doesn't use generics.
+    // I expect ClassCastExceptions will be thrown.
+    // -Joe.
+
+//    public void testDoesNotMatchObjectThatIsNotAnArray() {
+//        assertDoesNotMatch("should not matches empty list",
+//                arrayContaining("a"), "not a collection");
+//    }
+
+//    public void testMatchesPrimitiveArrayElements() {
+//        assertMatches("boolean", arrayContaining(true), new boolean[]{true, false});
+//        assertDoesNotMatch("boolean", arrayContaining(false), new boolean[]{false});
+//
+//        assertMatches("byte", arrayContaining((byte) 1), new byte[]{1, 2, 3});
+//        assertDoesNotMatch("byte", arrayContaining((byte) 0), new byte[]{1, 2, 3});
+//
+//        assertMatches("char", arrayContaining('a'), new char[]{'a', 'b', 'c'});
+//        assertDoesNotMatch("char", arrayContaining('z'), new char[]{'a', 'b', 'c'});
+//
+//        assertMatches("short", arrayContaining((short) 1), new short[]{1, 2, 3});
+//        assertDoesNotMatch("short", arrayContaining((short) 0), new short[]{1, 2, 3});
+//
+//        assertMatches("int", arrayContaining(1), new int[]{1, 2, 3});
+//        assertDoesNotMatch("int", arrayContaining(0), new int[]{1, 2, 3});
+//
+//        assertMatches("long", arrayContaining(1L), new long[]{1, 2, 3});
+//        assertDoesNotMatch("long", arrayContaining(0L), new long[]{1, 2, 3});
+//
+//        assertMatches("float", arrayContaining(1f), new float[]{1f, 2f, 3f});
+//        assertDoesNotMatch("float", arrayContaining(0f), new float[]{1f, 2f, 3f});
+//
+//        assertMatches("double", arrayContaining(1.0), new double[]{1.0, 2.0, 3.0});
+//        assertDoesNotMatch("double", arrayContaining(0.0), new double[]{1.0, 2.0, 3.0});
+//    }
+
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsArrayTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsArrayTest.java
new file mode 100644
index 0000000..4135d9f
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsArrayTest.java
@@ -0,0 +1,59 @@
+package org.hamcrest.collection;
+
+import org.hamcrest.AbstractMatcherTest;
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+
+import static org.hamcrest.collection.IsArray.array;
+import static org.hamcrest.core.IsEqual.equalTo;
+
+@SuppressWarnings("unchecked")
+public class IsArrayTest extends AbstractMatcherTest {
+
+    @Override
+    protected Matcher<?> createMatcher() {
+        return array(equalTo("irrelevant"));
+    }
+
+    public void testMatchesAnArrayThatMatchesAllTheElementMatchers() {
+        assertMatches("should match array with matching elements",
+                array(equalTo("a"), equalTo("b"), equalTo("c")), new String[]{"a", "b", "c"});
+    }
+    
+    public void testDoesNotMatchAnArrayWhenElementsDoNotMatch() {
+        assertDoesNotMatch("should not match array with different elements",
+                array(equalTo("a"), equalTo("b")), new String[]{"b", "c"});
+    }
+    
+    public void testDoesNotMatchAnArrayOfDifferentSize() {
+        assertDoesNotMatch("should not match larger array",
+                           array(equalTo("a"), equalTo("b")), new String[]{"a", "b", "c"});
+        assertDoesNotMatch("should not match smaller array",
+                           array(equalTo("a"), equalTo("b")), new String[]{"a"});
+    }
+    
+    public void testDoesNotMatchNull() {
+        assertDoesNotMatch("should not match null",
+                array(equalTo("a")), null);
+    }
+    
+    public void testHasAReadableDescription() {
+        assertDescription("[\"a\", \"b\"]", array(equalTo("a"), equalTo("b")));
+    }
+    
+    public void testHasAReadableMismatchDescriptionUsing() {
+        assertMismatchDescription("element <0> was \"c\"", array(equalTo("a"), equalTo("b")), new String[]{"c", "b"});
+    }
+    
+    public void testHasAReadableMismatchDescriptionUsingCustomMatchers() {
+        final BaseMatcher<String> m = new BaseMatcher<String>() {
+            @Override public boolean matches(Object item) { return false; }
+            @Override public void describeTo(Description description) { description.appendText("c"); }
+            @Override public void describeMismatch(Object item, Description description) {
+                description.appendText("didn't match");
+            }
+        };
+        assertMismatchDescription("element <0> didn't match", array(m, equalTo("b")), new String[]{"c", "b"});
+    }
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsArrayWithSizeTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsArrayWithSizeTest.java
new file mode 100644
index 0000000..18f607e
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsArrayWithSizeTest.java
@@ -0,0 +1,36 @@
+package org.hamcrest.collection;
+
+import org.hamcrest.AbstractMatcherTest;
+import org.hamcrest.Matcher;
+
+import static org.hamcrest.collection.IsArrayWithSize.arrayWithSize;
+import static org.hamcrest.collection.IsArrayWithSize.emptyArray;
+import static org.hamcrest.core.IsEqual.equalTo;
+
+public class IsArrayWithSizeTest extends AbstractMatcherTest {
+
+    @Override
+    protected Matcher<?> createMatcher() {
+        return arrayWithSize(equalTo(2));
+    }
+
+    public void testMatchesWhenSizeIsCorrect() {
+        assertMatches("correct size", arrayWithSize(equalTo(3)), new Object[] {1, 2, 3});
+        assertDoesNotMatch("incorrect size", arrayWithSize(equalTo(2)), new Object[] {1, 2, 3});
+    }
+
+    public void testProvidesConvenientShortcutForArrayWithSizeEqualTo() {
+        assertMatches("correct size", arrayWithSize(3), new Object[] {1, 2, 3});
+        assertDoesNotMatch("incorrect size", arrayWithSize(2), new Object[] {1, 2, 3});
+    }
+
+    public void testEmptyArray() {
+        assertMatches("correct size", emptyArray(), new Object[] {});
+        assertDoesNotMatch("incorrect size", emptyArray(), new Object[] {1});
+    }
+
+    public void testHasAReadableDescription() {
+        assertDescription("an array with size <3>", arrayWithSize(equalTo(3)));
+        assertDescription("an empty array", emptyArray());
+    }
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsCollectionWithSizeTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsCollectionWithSizeTest.java
new file mode 100644
index 0000000..b04a0c5
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsCollectionWithSizeTest.java
@@ -0,0 +1,77 @@
+package org.hamcrest.collection;
+
+import org.hamcrest.AbstractMatcherTest;
+import org.hamcrest.Matcher;
+import org.hamcrest.MatcherAssert;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import static java.util.Arrays.asList;
+import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
+import static org.hamcrest.core.IsEqual.equalTo;
+
+public class IsCollectionWithSizeTest extends AbstractMatcherTest {
+
+    @Override
+    protected Matcher<?> createMatcher() {
+        return hasSize(7);
+    }
+
+    public void testMatchesWhenSizeIsCorrect() {
+        assertMatches("correct size", hasSize(equalTo(2)), asList(null, null));
+        assertMismatchDescription("collection size was <3>", hasSize(equalTo(2)), asList(null, null, null));
+    }
+
+    public void testMatchesCollectionWhenSizeIsCorrectUsingObjectElementType() {
+        Collection<Object> list = asList(null, null);
+        assertMatches("correct size", hasSize(equalTo(2)), list);
+        assertMismatchDescription("collection size was <2>", hasSize(equalTo(3)), list);
+    }
+
+    public void testMatchesCollectionWhenSizeIsCorrectUsingStringElementType() {
+        Collection<String> list = asList("a", "b");
+        assertMatches("correct size", hasSize(equalTo(2)), list);
+        assertMismatchDescription("collection size was <2>", hasSize(equalTo(3)), list);
+    }
+
+    public void testMatchesCollectionWhenSizeIsCorrectUsingWildcardElementType() {
+        Collection<?> list = asList("a", "b");
+        assertMatches("correct size", hasSize(equalTo(2)), list);
+        assertMismatchDescription("collection size was <2>", hasSize(equalTo(3)), list);
+    }
+
+    public void testMatchesListWhenSizeIsCorrectUsingObjectElementType() {
+        List<Object> list = asList(null, null);
+        assertMatches("correct size", hasSize(equalTo(2)), list);
+        assertMismatchDescription("collection size was <2>", hasSize(equalTo(3)), list);
+    }
+
+    public void testMatchesListWhenSizeIsCorrectUsingStringElementType() {
+        List<String> list = asList("a", "b");
+        assertMatches("correct size", hasSize(equalTo(2)), list);
+        assertMismatchDescription("collection size was <2>", hasSize(equalTo(3)), list);
+    }
+
+    public void testMatchesListWhenSizeIsCorrectUsingWildcardElementType() {
+        List<?> list = asList("a", "b");
+        assertMatches("correct size", hasSize(equalTo(2)), list);
+        assertMismatchDescription("collection size was <2>", hasSize(equalTo(3)), list);
+    }
+
+    public void testProvidesConvenientShortcutForHasSizeEqualTo() {
+        assertMatches("correct size", hasSize(2), asList(null, null));
+        assertMismatchDescription("collection size was <3>", hasSize(2), asList(null, null, null));
+    }
+
+    public void testHasAReadableDescription() {
+        assertDescription("a collection with size <3>", hasSize(equalTo(3)));
+    }
+    
+    public void testCompilesWithATypedCollection() {
+      // To prove Issue 43
+      ArrayList<String> arrayList = new ArrayList<String>();
+      MatcherAssert.assertThat(arrayList, hasSize(0));
+    }
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsEmptyCollectionTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsEmptyCollectionTest.java
new file mode 100644
index 0000000..ea875e8
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsEmptyCollectionTest.java
@@ -0,0 +1,45 @@
+package org.hamcrest.collection;
+
+import org.hamcrest.AbstractMatcherTest;
+import org.hamcrest.Matcher;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import static java.util.Arrays.asList;
+import static org.hamcrest.collection.IsEmptyCollection.empty;
+import static org.hamcrest.core.Is.is;
+
+public class IsEmptyCollectionTest extends AbstractMatcherTest {
+
+    @Override
+    protected Matcher<Collection<?>> createMatcher() {
+        return empty();
+    }
+
+    public void testMatchesAnEmptyCollection() {
+        assertMatches("empty collection", createMatcher(), emptyCollection());
+    }
+
+    public void testDoesNotMatchACollectionWithAnItem() {
+        assertMismatchDescription("<[one, three]>", is(createMatcher()), collectionOfValues());
+    }
+
+    public void testHasAReadableDescription() {
+        assertDescription("an empty collection", createMatcher());
+    }
+
+    public void testCompiles() {
+        needs(IsEmptyCollection.emptyCollectionOf(String.class));
+    }
+
+    private void needs(@SuppressWarnings("unused") Matcher<Collection<String>> bar) { }
+    
+    private static Collection<String> collectionOfValues() {
+        return new ArrayList<String>(asList("one", "three"));
+    }
+
+    private static Collection<Integer> emptyCollection() {
+        return new ArrayList<Integer>();
+    }
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsEmptyIterableTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsEmptyIterableTest.java
new file mode 100644
index 0000000..600b576
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsEmptyIterableTest.java
@@ -0,0 +1,44 @@
+package org.hamcrest.collection;
+
+import org.hamcrest.AbstractMatcherTest;
+import org.hamcrest.Matcher;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import static java.util.Arrays.asList;
+import static org.hamcrest.collection.IsEmptyIterable.emptyIterable;
+
+public class IsEmptyIterableTest extends AbstractMatcherTest {
+
+    @Override
+    protected Matcher<Iterable<?>> createMatcher() {
+        return emptyIterable();
+    }
+
+    public void testMatchesAnEmptyIterable() {
+        assertMatches("empty iterable", createMatcher(), emptyCollection());
+    }
+
+    public void testDoesNotMatchAnIterableWithItems() {
+        assertDoesNotMatch("iterable with an item", createMatcher(), collectionOfValues());
+    }
+
+    public void testHasAReadableDescription() {
+        assertDescription("an empty iterable", createMatcher());
+    }
+
+    public void testCompiles() {
+        needs(IsEmptyIterable.emptyIterableOf(String.class));
+    }
+
+    private void needs(@SuppressWarnings("unused") Matcher<Iterable<String>> bar) { }
+
+    private static Collection<String> collectionOfValues() {
+        return new ArrayList<String>(asList("one", "three"));
+    }
+
+    private static Collection<Integer> emptyCollection() {
+        return new ArrayList<Integer>();
+    }
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsInTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsInTest.java
new file mode 100644
index 0000000..e9fcbdc
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsInTest.java
@@ -0,0 +1,44 @@
+package org.hamcrest.collection;
+
+import org.hamcrest.AbstractMatcherTest;
+import org.hamcrest.Matcher;
+import org.hamcrest.StringDescription;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+public class IsInTest extends AbstractMatcherTest {
+    String[] elements = {"a", "b", "c"};
+
+    @Override
+    protected Matcher<?> createMatcher() {
+        return new IsIn<String>(elements);
+    }
+
+    public void testReturnsTrueIfArgumentIsInCollection() {
+        Collection<String> collection = Arrays.asList(elements);
+        Matcher<String> isIn = new IsIn<String>(collection);
+        
+        assertMatches("a", isIn, "a");
+        assertMatches("b", isIn, "b");
+        assertMatches("c", isIn, "c");
+        assertDoesNotMatch("d", isIn, "d");
+    }
+    
+    public void testReturnsTrueIfArgumentIsInArray() {
+        Matcher<String> isIn = new IsIn<String>(elements);
+        
+        assertMatches("a", isIn, "a");
+        assertMatches("b", isIn, "b");
+        assertMatches("c", isIn, "c");
+        assertDoesNotMatch("d", isIn, "d");
+    }
+    
+    public void testHasReadableDescription() {
+        Matcher<String> isIn = new IsIn<String>(elements);
+        
+        assertEquals("description", 
+            "one of {\"a\", \"b\", \"c\"}", 
+            StringDescription.toString(isIn));
+    }
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsIterableContainingInAnyOrderTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsIterableContainingInAnyOrderTest.java
new file mode 100644
index 0000000..091c347
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsIterableContainingInAnyOrderTest.java
@@ -0,0 +1,54 @@
+package org.hamcrest.collection;
+
+import org.hamcrest.AbstractMatcherTest;
+import org.hamcrest.Matcher;
+import org.hamcrest.collection.IsIterableContainingInOrderTest.WithValue;
+
+import java.util.Collections;
+
+import static java.util.Arrays.asList;
+import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
+import static org.hamcrest.collection.IsIterableContainingInOrderTest.make;
+import static org.hamcrest.collection.IsIterableContainingInOrderTest.value;
+
+public class IsIterableContainingInAnyOrderTest extends AbstractMatcherTest {
+
+    @Override
+    protected Matcher<?> createMatcher() {
+        return containsInAnyOrder(1, 2);
+    }   
+
+    public void testMatchesSingleItemIterable() {
+      assertMatches("single item", containsInAnyOrder(1), asList(1));
+    }
+
+    public void testDoesNotMatchEmpty() {
+        assertMismatchDescription("no item matches: <1>, <2> in []", containsInAnyOrder(1, 2), Collections.<Integer>emptyList());
+    }
+    
+    public void testMatchesIterableOutOfOrder() {
+        assertMatches("Out of order", containsInAnyOrder(1, 2), asList(2, 1));
+    }
+    
+    public void testMatchesIterableInOrder() {
+        assertMatches("In order", containsInAnyOrder(1, 2), asList(1, 2));
+    }
+    
+    public void testDoesNotMatchIfOneOfMultipleElementsMismatches() {
+        assertMismatchDescription("not matched: <4>", containsInAnyOrder(1, 2, 3), asList(1, 2, 4));
+    }
+
+    @SuppressWarnings("unchecked")
+    public void testDoesNotMatchIfThereAreMoreElementsThanMatchers() {
+        final Matcher<Iterable<? extends WithValue>> helpTheCompilerOut = containsInAnyOrder(value(1), value(3));
+        assertMismatchDescription("not matched: <WithValue 2>", helpTheCompilerOut, asList(make(1), make(2), make(3)));
+    }
+    
+    public void testDoesNotMatchIfThereAreMoreMatchersThanElements() {
+        assertMismatchDescription("no item matches: <4> in [<1>, <2>, <3>]", containsInAnyOrder(1, 2, 3, 4), asList(1, 2, 3));
+    }
+
+    public void testHasAReadableDescription() {
+        assertDescription("iterable with items [<1>, <2>] in any order", containsInAnyOrder(1, 2));
+    }
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsIterableContainingInOrderTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsIterableContainingInOrderTest.java
new file mode 100644
index 0000000..8cb1bf8
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsIterableContainingInOrderTest.java
@@ -0,0 +1,77 @@
+package org.hamcrest.collection;
+
+import org.hamcrest.AbstractMatcherTest;
+import org.hamcrest.FeatureMatcher;
+import org.hamcrest.Matcher;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static java.util.Arrays.asList;
+import static org.hamcrest.collection.IsIterableContainingInOrder.contains;
+import static org.hamcrest.core.IsEqual.equalTo;
+
+@SuppressWarnings("unchecked")
+public class IsIterableContainingInOrderTest extends AbstractMatcherTest {
+    // temporary hack until the Java type system works
+    private final Matcher<Iterable<? extends WithValue>> contains123 = contains(value(1), value(2), value(3));
+
+    @Override
+    protected Matcher<?> createMatcher() {
+        return contains(1, 2);
+    }
+
+    public void testMatchingSingleItemIterable() throws Exception {
+        assertMatches("Single item iterable", contains(1), asList(1));
+    }
+
+    public void testMatchingMultipleItemIterable() throws Exception {
+        assertMatches("Multiple item iterable", contains(1, 2, 3), asList(1, 2, 3));
+    }
+
+    public void testDoesNotMatchWithMoreElementsThanExpected() throws Exception {
+        assertMismatchDescription("not matched: <4>", contains(1, 2, 3), asList(1, 2, 3, 4));
+    }
+
+    public void testDoesNotMatchWithFewerElementsThanExpected() throws Exception {
+        List<WithValue> valueList = asList(make(1), make(2));
+        assertMismatchDescription("no item was value with <3>", contains123, valueList);
+    }
+
+    public void testDoesNotMatchIfSingleItemMismatches() throws Exception {
+        assertMismatchDescription("item 0: value was <3>", contains(value(4)), asList(make(3)));
+    }
+
+    public void testDoesNotMatchIfOneOfMultipleItemsMismatch() throws Exception {
+        assertMismatchDescription("item 2: value was <4>", contains123, asList(make(1), make(2), make(4)));
+    }
+
+    public void testDoesNotMatchEmptyIterable() throws Exception {
+        assertMismatchDescription("no item was value with <4>", contains(value(4)), new ArrayList<WithValue>());
+    }
+
+    public void testHasAReadableDescription() {
+        assertDescription("iterable containing [<1>, <2>]", contains(1, 2));
+    }
+    
+    public void testCanHandleNullMatchers() {
+    	assertMatches(contains(null, null), asList(null, null));
+    }
+
+    public static class WithValue {
+      private final int value;
+      public WithValue(int value) { this.value = value; }
+      public int getValue() { return value; }
+      @Override public String toString() { return "WithValue " + value; }
+    }
+
+    public static WithValue make(int value) {
+      return new WithValue(value);
+    }
+
+    public static Matcher<WithValue> value(int value) {
+      return new FeatureMatcher<WithValue, Integer>(equalTo(value), "value with", "value") {
+        @Override protected Integer featureValueOf(WithValue actual) { return actual.getValue(); }
+      };
+    }
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsIterableContainingInRelativeOrderTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsIterableContainingInRelativeOrderTest.java
new file mode 100644
index 0000000..8192c8b
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsIterableContainingInRelativeOrderTest.java
@@ -0,0 +1,93 @@
+package org.hamcrest.collection;
+
+import org.hamcrest.AbstractMatcherTest;
+import org.hamcrest.FeatureMatcher;
+import org.hamcrest.Matcher;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static java.util.Arrays.asList;
+import static org.hamcrest.collection.IsIterableContainingInRelativeOrder.containsInRelativeOrder;
+import static org.hamcrest.core.IsEqual.equalTo;
+
+@SuppressWarnings("unchecked")
+public class IsIterableContainingInRelativeOrderTest extends AbstractMatcherTest {
+    // temporary hack until the Java type system works
+    private final Matcher<Iterable<? extends WithValue>> contains123 = containsInRelativeOrder(value(1), value(2), value(3));
+
+    @Override
+    protected Matcher<?> createMatcher() {
+        return containsInRelativeOrder(1, 2);
+    }
+
+    public void testMatchingSingleItemIterable() throws Exception {
+        assertMatches("Single item iterable", containsInRelativeOrder(1), asList(1));
+    }
+
+    public void testMatchingMultipleItemIterable() throws Exception {
+        assertMatches("Multiple item iterable", containsInRelativeOrder(1, 2, 3), asList(1, 2, 3));
+    }
+
+    public void testMatchesWithMoreElementsThanExpectedAtBeginning() throws Exception {
+        assertMatches("More elements at beginning", containsInRelativeOrder(2, 3, 4), asList(1, 2, 3, 4));
+    }
+
+    public void testMatchesWithMoreElementsThanExpectedAtEnd() throws Exception {
+        assertMatches("More elements at end", containsInRelativeOrder(1, 2, 3), asList(1, 2, 3, 4));
+    }
+
+    public void testMatchesWithMoreElementsThanExpectedInBetween() throws Exception {
+        assertMatches("More elements in between", containsInRelativeOrder(1, 3), asList(1, 2, 3));
+    }
+
+    public void testMatchesSubSection() throws Exception {
+        assertMatches("Sub section of iterable", containsInRelativeOrder(2, 3), asList(1, 2, 3, 4));
+    }
+
+    public void testMatchesWithSingleGapAndNotFirstOrLast() throws Exception {
+        assertMatches("Sub section with single gaps without a first or last match", containsInRelativeOrder(2, 4), asList(1, 2, 3, 4, 5));
+    }
+
+    public void testMatchingSubSectionWithManyGaps() throws Exception {
+        assertMatches("Sub section with many gaps iterable", containsInRelativeOrder(2, 4, 6), asList(1, 2, 3, 4, 5, 6, 7));
+    }
+
+    public void testDoesNotMatchWithFewerElementsThanExpected() throws Exception {
+        List<WithValue> valueList = asList(make(1), make(2));
+        assertMismatchDescription("value with <3> was not found after <WithValue 2>", contains123, valueList);
+    }
+
+    public void testDoesNotMatchIfSingleItemNotFound() throws Exception {
+        assertMismatchDescription("value with <4> was not found", containsInRelativeOrder(value(4)), asList(make(3)));
+    }
+
+    public void testDoesNotMatchIfOneOfMultipleItemsNotFound() throws Exception {
+        assertMismatchDescription("value with <3> was not found after <WithValue 2>", contains123, asList(make(1), make(2), make(4)));
+    }
+
+    public void testDoesNotMatchEmptyIterable() throws Exception {
+        assertMismatchDescription("value with <4> was not found", containsInRelativeOrder(value(4)), new ArrayList<WithValue>());
+    }
+
+    public void testHasAReadableDescription() {
+        assertDescription("iterable containing [<1>, <2>] in relative order", containsInRelativeOrder(1, 2));
+    }
+
+    public static class WithValue {
+      private final int value;
+      public WithValue(int value) { this.value = value; }
+      public int getValue() { return value; }
+      @Override public String toString() { return "WithValue " + value; }
+    }
+
+    public static WithValue make(int value) {
+      return new WithValue(value);
+    }
+
+    public static Matcher<WithValue> value(int value) {
+      return new FeatureMatcher<WithValue, Integer>(equalTo(value), "value with", "value") {
+        @Override protected Integer featureValueOf(WithValue actual) { return actual.getValue(); }
+      };
+    }
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsIterableWithSizeTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsIterableWithSizeTest.java
new file mode 100644
index 0000000..8bf65d1
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsIterableWithSizeTest.java
@@ -0,0 +1,37 @@
+package org.hamcrest.collection;
+
+import org.hamcrest.AbstractMatcherTest;
+import org.hamcrest.Matcher;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import static org.hamcrest.collection.IsIterableWithSize.iterableWithSize;
+
+public class IsIterableWithSizeTest extends AbstractMatcherTest {
+
+    @Override
+    protected Matcher<?> createMatcher() {
+        return iterableWithSize(7);
+    }
+
+    public void testMatchesEmptyIterable() throws Exception {
+        assertMatches("Empty iterable", iterableWithSize(0), Collections.emptyList());
+    }
+
+    public void testMatchingSingleItemIterable() throws Exception {
+        assertMatches("Single item iterable", iterableWithSize(1), Arrays.<Object>asList(1));
+    }
+
+    public void testMatchingMultipleItemIterable() throws Exception {
+        assertMatches("Multiple item iterable", iterableWithSize(3), Arrays.<Object>asList(1, 2, 3));
+    }
+
+    public void testDoesNotMatchIncorrectSize() throws Exception {
+        assertDoesNotMatch("Incorrect size", iterableWithSize(3), Arrays.<Object>asList(1));
+    }
+
+    public void testHasAReadableDescription() {
+        assertDescription("an iterable with size <4>", iterableWithSize(4));
+    }
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsMapContainingKeyTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsMapContainingKeyTest.java
new file mode 100644
index 0000000..13f067c
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsMapContainingKeyTest.java
@@ -0,0 +1,84 @@
+package org.hamcrest.collection;
+
+import org.hamcrest.AbstractMatcherTest;
+import org.hamcrest.Matcher;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.collection.IsMapContaining.hasKey;
+
+public class IsMapContainingKeyTest extends AbstractMatcherTest {
+
+    @Override
+    protected Matcher<?> createMatcher() {
+        return hasKey("foo");
+    }
+
+    public void testMatchesSingletonMapContainingKey() {
+        Map<String,Integer> map = new HashMap<String, Integer>();
+        map.put("a", 1);
+        
+        assertMatches("Matches single key", hasKey("a"), map);
+    }
+    
+    public void testMatchesMapContainingKey() {
+        Map<String,Integer> map = new HashMap<String, Integer>();
+        map.put("a", 1);
+        map.put("b", 2);
+        map.put("c", 3);
+        
+        assertMatches("Matches a", hasKey("a"), map);
+        assertMatches("Matches c", hasKey("c"), map);
+    }
+    
+
+//    No longer compiles
+//    public void testMatchesMapContainingKeyWithNoGenerics() {
+//        Map map = new HashMap();
+//        map.put("a", 1);
+//        map.put("b", 2);
+//        map.put("c", 3);
+//
+//        assertMatches("Matches a", hasKey("a"), map);
+//        assertMatches("Matches c", hasKey("c"), map);
+//    }
+
+    public void testMatchesMapContainingKeyWithIntegerKeys() throws Exception {
+        Map<Integer, String> map = new HashMap<Integer, String>();
+        map.put(1, "A");
+        map.put(2, "B");
+
+        assertThat(map, hasKey(1));
+    }
+
+    public void testMatchesMapContainingKeyWithNumberKeys() throws Exception {
+        Map<Number, String> map = new HashMap<Number, String>();
+        map.put(1, "A");
+        map.put(2, "B");
+
+        assertThat(map, hasKey((Number)1));
+
+        // TODO: work out the correct sprinkling of wildcards to get this to work!
+//        assertThat(map, hasKey(1));
+    }
+
+    public void testHasReadableDescription() {
+        assertDescription("map containing [\"a\"->ANYTHING]", hasKey("a"));
+    }
+    
+    public void testDoesNotMatchEmptyMap() {
+        assertMismatchDescription("map was []", hasKey("Foo"), new HashMap<String,Integer>());
+    }
+    
+    public void testDoesNotMatchMapMissingKey() {
+        Map<String,Integer> map = new TreeMap<String, Integer>();
+        map.put("a", 1);
+        map.put("b", 2);
+        map.put("c", 3);
+        
+        assertMismatchDescription("map was [<a=1>, <b=2>, <c=3>]", hasKey("d"), map);
+    }
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsMapContainingTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsMapContainingTest.java
new file mode 100644
index 0000000..f472224
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsMapContainingTest.java
@@ -0,0 +1,58 @@
+package org.hamcrest.collection;
+
+import org.hamcrest.AbstractMatcherTest;
+import org.hamcrest.Matcher;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+import static org.hamcrest.collection.IsMapContaining.hasEntry;
+import static org.hamcrest.core.IsAnything.anything;
+import static org.hamcrest.core.IsEqual.equalTo;
+
+public class IsMapContainingTest extends AbstractMatcherTest {
+
+    @Override
+    protected Matcher<?> createMatcher() {
+        return IsMapContaining.hasEntry("irrelevant", "irrelevant");
+    }
+
+    public void testMatchesMapContainingMatchingKeyAndValue() {
+        Map<String,Integer> map = new TreeMap<String,Integer>();
+        map.put("a", 1);
+        map.put("b", 2);
+
+        assertMatches("matcherA", hasEntry(equalTo("a"), equalTo(1)), map);
+        assertMatches("matcherB", hasEntry(equalTo("b"), equalTo(2)), map);
+        assertMismatchDescription("map was [<a=1>, <b=2>]", hasEntry(equalTo("c"), equalTo(3)), map);
+    }
+
+//    no longer compiles. SF
+//    public void testMatchesMapContainingMatchingKeyAndValueWithoutGenerics() {
+//        Map map = new HashMap();
+//        map.put("a", 1);
+//        map.put("b", 2);
+//
+//        assertMatches("matcherA", hasEntry(equalTo("a"), equalTo(1)), map);
+//        assertMatches("matcherB", hasEntry(equalTo("b"), equalTo(2)), map);
+//        assertDoesNotMatch("matcherC", hasEntry(equalTo("c"), equalTo(3)), map);
+//    }
+//
+    public void testDoesNotMatchNull() {
+        assertMismatchDescription("was null", hasEntry(anything(), anything()), null);
+    }
+
+    public void testHasReadableDescription() {
+        assertDescription("map containing [\"a\"-><2>]", hasEntry(equalTo("a"), (equalTo(2))));
+    }
+
+    // Remaining code no longer compiles, thanks to generics. I think that's a good thing, but
+    // I still need to investigate how this behaves with code that doesn't use generics.
+    // I expect ClassCastExceptions will be thrown.
+    // -Joe.
+    
+//    public void testDoesNotMatchAnObjectThatIsNotAMap() {
+//        assertDoesNotMatch("should not matches a string",
+//                mapContaining(ANYTHING, ANYTHING), "not a map");
+//    }
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsMapContainingValueTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsMapContainingValueTest.java
new file mode 100644
index 0000000..a2d7f90
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsMapContainingValueTest.java
@@ -0,0 +1,46 @@
+package org.hamcrest.collection;
+
+
+import org.hamcrest.AbstractMatcherTest;
+import org.hamcrest.Matcher;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+
+import static org.hamcrest.collection.IsMapContaining.hasValue;
+
+public class IsMapContainingValueTest extends AbstractMatcherTest {
+
+    @Override
+    protected Matcher<?> createMatcher() {
+        return hasValue("foo");
+    }
+
+    public void testHasReadableDescription() {
+        assertDescription("map containing [ANYTHING->\"a\"]", hasValue("a"));
+    }
+    
+    public void testDoesNotMatchEmptyMap() {
+        Map<String,Integer> map = new HashMap<String,Integer>();
+        assertMismatchDescription("map was []", hasValue(1), map);
+    }
+    
+    public void testMatchesSingletonMapContainingValue() {
+        Map<String,Integer> map = new HashMap<String,Integer>();
+        map.put("a", 1);
+        
+        assertMatches("Singleton map", hasValue(1), map);
+    }
+
+    public void testMatchesMapContainingValue() {
+        Map<String,Integer> map = new TreeMap<String,Integer>();
+        map.put("a", 1);
+        map.put("b", 2);
+        map.put("c", 3);
+        
+        assertMatches("hasValue 1", hasValue(1), map);      
+        assertMatches("hasValue 3", hasValue(3), map);      
+        assertMismatchDescription("map was [<a=1>, <b=2>, <c=3>]", hasValue(4), map);      
+    }
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsMapWithSizeTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsMapWithSizeTest.java
new file mode 100644
index 0000000..c050924
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsMapWithSizeTest.java
@@ -0,0 +1,82 @@
+package org.hamcrest.collection;
+
+import org.hamcrest.AbstractMatcherTest;
+import org.hamcrest.Matcher;
+import org.hamcrest.MatcherAssert;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.hamcrest.collection.IsMapWithSize.aMapWithSize;
+import static org.hamcrest.core.IsEqual.equalTo;
+
+public final class IsMapWithSizeTest extends AbstractMatcherTest {
+
+    @Override
+    protected Matcher<?> createMatcher() {
+        return aMapWithSize(7);
+    }
+
+    public void testMatchesWhenSizeIsCorrect() {
+        assertMatches("correct size", aMapWithSize(equalTo(2)), mapWithKeys("a", "b"));
+        assertMismatchDescription("map size was <3>", aMapWithSize(equalTo(2)), mapWithKeys("a", "b", "c"));
+    }
+
+    public void testMatchesMapWhenSizeIsCorrectUsingObjectElementType() {
+        Map<Object, Object> map = mapWithKeys(new Object(), new Object());
+        assertMatches("correct size", aMapWithSize(equalTo(2)), map);
+        assertMismatchDescription("map size was <2>", aMapWithSize(equalTo(3)), map);
+    }
+
+    public void testMatchesMapWhenSizeIsCorrectUsingStringElementType() {
+        Map<String, Integer> map = mapWithKeys("a", "b");
+        assertMatches("correct size", aMapWithSize(equalTo(2)), map);
+        assertMismatchDescription("map size was <2>", aMapWithSize(equalTo(3)), map);
+    }
+
+    public void testMatchesMapWhenSizeIsCorrectUsingWildcardElementType() {
+        Map<?, ?> map = mapWithKeys("a", "b");
+        assertMatches("correct size", aMapWithSize(equalTo(2)), map);
+        assertMismatchDescription("map size was <2>", aMapWithSize(equalTo(3)), map);
+    }
+
+    public void testMatchesListWhenSizeIsCorrectUsingObjectElementType() {
+        Map<Object, Object> map = mapWithKeys(new Object(), new Object());
+        assertMatches("correct size", aMapWithSize(equalTo(2)), map);
+        assertMismatchDescription("map size was <2>", aMapWithSize(equalTo(3)), map);
+    }
+
+    public void testMatchesListWhenSizeIsCorrectUsingStringElementType() {
+        Map<String, Integer> list = mapWithKeys("a", "b");
+        assertMatches("correct size", aMapWithSize(equalTo(2)), list);
+        assertMismatchDescription("map size was <2>", aMapWithSize(equalTo(3)), list);
+    }
+
+    public void testMatchesListWhenSizeIsCorrectUsingWildcardElementType() {
+        Map<?, ?> list = mapWithKeys("a", "b");
+        assertMatches("correct size", aMapWithSize(equalTo(2)), list);
+        assertMismatchDescription("map size was <2>", aMapWithSize(equalTo(3)), list);
+    }
+
+    public void testProvidesConvenientShortcutForHasSizeEqualTo() {
+        assertMatches("correct size", aMapWithSize(2), mapWithKeys(new Object(), new Object()));
+        assertMismatchDescription("map size was <3>", aMapWithSize(2), mapWithKeys(new Object(), new Object(), new Object()));
+    }
+
+    public void testHasAReadableDescription() {
+        assertDescription("a map with size <3>", aMapWithSize(equalTo(3)));
+    }
+    
+    public void testCompilesWithATypedMap() {
+      Map<String, Integer> arrayList = new HashMap<String, Integer>();
+      MatcherAssert.assertThat(arrayList, aMapWithSize(0));
+    }
+    
+    private static <K, V> Map<K, V> mapWithKeys(K... keys) {
+        final Map<K, V> result = new HashMap<K, V>();
+        for (K key : keys) {
+            result.put(key, null);
+        }
+        return result;
+    }
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/comparator/ComparatorMatcherBuilderTest.java b/hamcrest-library/src/test/java/org/hamcrest/comparator/ComparatorMatcherBuilderTest.java
new file mode 100644
index 0000000..a5fdb4a
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/comparator/ComparatorMatcherBuilderTest.java
@@ -0,0 +1,128 @@
+package org.hamcrest.comparator;
+
+import org.hamcrest.AbstractMatcherTest;
+import org.hamcrest.Matcher;
+
+import java.math.BigDecimal;
+import java.util.Comparator;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.comparator.ComparatorMatcherBuilder.comparedBy;
+import static org.hamcrest.core.IsNot.not;
+
+public class ComparatorMatcherBuilderTest extends AbstractMatcherTest {
+
+    private final ComparatorMatcherBuilder<Integer> integerComparatorMatcherBuilder = ComparatorMatcherBuilder.usingNaturalOrdering();
+    private final ComparatorMatcherBuilder<Double> doubleComparatorMatcherBuilder = ComparatorMatcherBuilder.usingNaturalOrdering();
+    private final ComparatorMatcherBuilder<String> stringComparatorMatcherBuilder = ComparatorMatcherBuilder.usingNaturalOrdering();
+    private final ComparatorMatcherBuilder<BigDecimal> bigDecimalComparatorMatcherBuilder = ComparatorMatcherBuilder.usingNaturalOrdering();
+    private final Comparator<Integer> backwardsIntegerComparator = new Comparator<Integer>() {
+        @Override
+        public int compare(Integer o1, Integer o2) {
+            return -o1.compareTo(o2);
+        }
+
+        @Override
+        public String toString() {
+            return "backwards integer comparator";
+        }
+    };
+
+    @Override
+    protected Matcher<Integer> createMatcher() {
+        return integerComparatorMatcherBuilder.greaterThan(1);
+    }
+
+    public void testDescription() {
+        assertDescription("a value greater than <1>", integerComparatorMatcherBuilder.greaterThan(1));
+        assertDescription("a value equal to or greater than <1>", integerComparatorMatcherBuilder.greaterThanOrEqualTo(1));
+        assertDescription("a value equal to <1>", integerComparatorMatcherBuilder.comparesEqualTo(1));
+        assertDescription("a value less than or equal to <1>", integerComparatorMatcherBuilder.lessThanOrEqualTo(1));
+        assertDescription("a value less than <1>", integerComparatorMatcherBuilder.lessThan(1));
+
+        assertDescription("a value greater than <1> when compared by <backwards integer comparator>", comparedBy(backwardsIntegerComparator).greaterThan(1));
+        assertDescription("a value equal to or greater than <1> when compared by <backwards integer comparator>", comparedBy(backwardsIntegerComparator).greaterThanOrEqualTo(1));
+        assertDescription("a value equal to <1> when compared by <backwards integer comparator>", comparedBy(backwardsIntegerComparator).comparesEqualTo(1));
+        assertDescription("a value less than or equal to <1> when compared by <backwards integer comparator>", comparedBy(backwardsIntegerComparator).lessThanOrEqualTo(1));
+        assertDescription("a value less than <1> when compared by <backwards integer comparator>", comparedBy(backwardsIntegerComparator).lessThan(1));
+    }
+
+    public void testMismatchDescriptions() {
+        assertMismatchDescription("<0> was less than <1>", integerComparatorMatcherBuilder.greaterThan(1), 0);
+        assertMismatchDescription("<1> was equal to <1>", integerComparatorMatcherBuilder.greaterThan(1), 1);
+        assertMismatchDescription("<1> was greater than <0>", integerComparatorMatcherBuilder.lessThan(0), 1);
+        assertMismatchDescription("<2> was equal to <2>", integerComparatorMatcherBuilder.lessThan(2), 2);
+
+        assertMismatchDescription("<1> was less than <0> when compared by <backwards integer comparator>", comparedBy(backwardsIntegerComparator).greaterThan(0), 1);
+        assertMismatchDescription("<1> was equal to <1> when compared by <backwards integer comparator>", comparedBy(backwardsIntegerComparator).greaterThan(1), 1);
+        assertMismatchDescription("<0> was greater than <1> when compared by <backwards integer comparator>", comparedBy(backwardsIntegerComparator).lessThan(1), 0);
+        assertMismatchDescription("<2> was equal to <2> when compared by <backwards integer comparator>", comparedBy(backwardsIntegerComparator).lessThan(2), 2);
+    }
+
+    public void testComparesObjectsForGreaterThan() {
+        assertThat(2, integerComparatorMatcherBuilder.greaterThan(1));
+        assertThat(0, not(integerComparatorMatcherBuilder.greaterThan(1)));
+    }
+
+    public void testComparesObjectsForLessThan() {
+        assertThat(2, integerComparatorMatcherBuilder.lessThan(3));
+        assertThat(0, integerComparatorMatcherBuilder.lessThan(1));
+    }
+
+
+    public void testComparesObjectsForEquality() {
+        assertThat(3, integerComparatorMatcherBuilder.comparesEqualTo(3));
+        assertThat("aa", stringComparatorMatcherBuilder.comparesEqualTo("aa"));
+    }
+
+    public void testAllowsForInclusiveComparisons() {
+        assertThat("less", 1, integerComparatorMatcherBuilder.lessThanOrEqualTo(1));
+        assertThat("greater", 1, integerComparatorMatcherBuilder.greaterThanOrEqualTo(1));
+    }
+
+    public void testSupportsDifferentTypesOfComparableObjects() {
+        assertThat(1.1, doubleComparatorMatcherBuilder.greaterThan(1.0));
+        assertThat("cc", stringComparatorMatcherBuilder.greaterThan("bb"));
+    }
+
+    public void testComparesBigDecimalsWithDifferentScalesCorrectlyForIssue20() {
+        assertThat(new BigDecimal("10.0"), bigDecimalComparatorMatcherBuilder.greaterThanOrEqualTo(new BigDecimal("10")));
+        assertThat(new BigDecimal(10), bigDecimalComparatorMatcherBuilder.greaterThanOrEqualTo(new BigDecimal("10.0")));
+        assertThat(new BigDecimal("2"), bigDecimalComparatorMatcherBuilder.comparesEqualTo(new BigDecimal("2.000")));
+    }
+
+    public void testComparesCustomTypesWhoseCompareToReturnsValuesGreaterThatOne() {
+        assertThat(new CustomInt(5), ComparatorMatcherBuilder.<CustomInt>usingNaturalOrdering().lessThan(new CustomInt(10)));
+    }
+
+    public void testComparesByCustomComparator() {
+        assertThat(5, comparedBy(backwardsIntegerComparator).lessThan(4));
+    }
+
+    public void testJavadocExamples() {
+        assertThat(1, ComparatorMatcherBuilder.<Integer>usingNaturalOrdering().comparesEqualTo(1));
+        assertThat(2, ComparatorMatcherBuilder.<Integer>usingNaturalOrdering().greaterThan(1));
+        assertThat(1, ComparatorMatcherBuilder.<Integer>usingNaturalOrdering().greaterThanOrEqualTo(1));
+        assertThat(1, ComparatorMatcherBuilder.<Integer>usingNaturalOrdering().lessThan(2));
+        assertThat(1, ComparatorMatcherBuilder.<Integer>usingNaturalOrdering().lessThanOrEqualTo(1));
+        assertThat(5, comparedBy(new Comparator<Integer>() {
+            @Override
+            public int compare(Integer o1, Integer o2) {
+                return -o1.compareTo(o2);
+            }
+        }).lessThan(4));
+    }
+
+    private static final class CustomInt implements Comparable<CustomInt> {
+        private final int value;
+
+        public CustomInt(int value) {
+            this.value = value;
+        }
+
+        @Override
+        public int compareTo(CustomInt other) {
+            return value - other.value;
+        }
+    }
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/comparator/ComparatorMatcherTest.java b/hamcrest-library/src/test/java/org/hamcrest/comparator/ComparatorMatcherTest.java
new file mode 100644
index 0000000..2bc53d4
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/comparator/ComparatorMatcherTest.java
@@ -0,0 +1,87 @@
+package org.hamcrest.comparator;
+
+import org.hamcrest.AbstractMatcherTest;
+import org.hamcrest.Matcher;
+
+import java.math.BigDecimal;
+import java.util.Comparator;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.IsNot.not;
+import static org.hamcrest.number.OrderingComparison.*;
+
+public class ComparatorMatcherTest extends AbstractMatcherTest {
+
+    @Override
+    protected Matcher<Integer> createMatcher() {
+        return ComparatorMatcherBuilder.comparedBy(new Comparator<Integer>() {
+            @Override
+            public int compare(Integer o1, Integer o2) {
+                return o1.compareTo(o2);
+            }
+        }).greaterThan(1);
+    }
+
+    public void testDescription() {
+        assertDescription("a value greater than <1>", greaterThan(1));
+        assertDescription("a value equal to or greater than <1>", greaterThanOrEqualTo(1));
+        assertDescription("a value equal to <1>", comparesEqualTo(1));
+        assertDescription("a value less than or equal to <1>", lessThanOrEqualTo(1));
+        assertDescription("a value less than <1>", lessThan(1));
+    }
+
+    public void testMismatchDescriptions() {
+        assertMismatchDescription("<0> was less than <1>", greaterThan(1), 0);
+        assertMismatchDescription("<1> was equal to <1>", greaterThan(1), 1);
+        assertMismatchDescription("<1> was greater than <0>", lessThan(0), 1);
+        assertMismatchDescription("<2> was equal to <2>", lessThan(2), 2);
+    }
+
+    public void testComparesObjectsForGreaterThan() {
+        assertThat(2, greaterThan(1));
+        assertThat(0, not(greaterThan(1)));
+    }
+
+    public void testComparesObjectsForLessThan() {
+        assertThat(2, lessThan(3));
+        assertThat(0, lessThan(1));
+    }
+
+
+    public void testComparesObjectsForEquality() {
+        assertThat(3, comparesEqualTo(3));
+        assertThat("aa", comparesEqualTo("aa"));
+    }
+
+    public void testAllowsForInclusiveComparisons() {
+        assertThat("less", 1, lessThanOrEqualTo(1));
+        assertThat("greater", 1, greaterThanOrEqualTo(1));
+    }
+
+    public void testSupportsDifferentTypesOfComparableObjects() {
+        assertThat(1.1, greaterThan(1.0));
+        assertThat("cc", greaterThan("bb"));
+    }
+
+    public void testComparesBigDecimalsWithDifferentScalesCorrectlyForIssue20() {
+        assertThat(new BigDecimal("10.0"), greaterThanOrEqualTo(new BigDecimal("10")));
+        assertThat(new BigDecimal(10), greaterThanOrEqualTo(new BigDecimal("10.0")));
+        assertThat(new BigDecimal("2"), comparesEqualTo(new BigDecimal("2.000")));
+    }
+
+    public void testComparesCustomTypesWhoseCompareToReturnsValuesGreaterThatOne() {
+        assertThat(new CustomInt(5), lessThan(new CustomInt(10)));
+    }
+
+    private static final class CustomInt implements Comparable<CustomInt> {
+        private final int value;
+
+        public CustomInt(int value) {
+            this.value = value;
+        }
+
+        public int compareTo(CustomInt other) {
+            return value - other.value;
+        }
+    }
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/io/FileMatchersTest.java b/hamcrest-library/src/test/java/org/hamcrest/io/FileMatchersTest.java
new file mode 100644
index 0000000..b186549
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/io/FileMatchersTest.java
@@ -0,0 +1,93 @@
+package org.hamcrest.io;
+
+import org.hamcrest.AbstractMatcherTest;
+import org.hamcrest.Matcher;
+
+import java.io.File;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+
+@SuppressWarnings("ResultOfMethodCallIgnored")
+public class FileMatchersTest extends AbstractMatcherTest {
+
+    private File directory;
+    private File file;
+
+    @Override
+    protected void setUp() throws Exception {
+        directory = File.createTempFile("myDir", "");
+        directory.delete();
+        directory.mkdirs();
+        
+        file = new File(directory, "myFile");
+        file.createNewFile();
+    }
+    
+    public void testAnExistingDirectory() {
+        assertMatches("matches existing directory", FileMatchers.anExistingDirectory(), directory);
+        assertDoesNotMatch("doesn't match existing file", FileMatchers.anExistingDirectory(), file);
+        assertDoesNotMatch("doesn't match missing file", FileMatchers.anExistingDirectory(), new File("foo"));
+    }
+
+    public void testAnExistingFileOrDirectory() {
+        assertMatches("matches existing file", FileMatchers.anExistingFileOrDirectory(), file);
+        assertMatches("matches existing directory", FileMatchers.anExistingFileOrDirectory(), directory);
+        assertDoesNotMatch("doesn't match missing file", FileMatchers.anExistingFileOrDirectory(), new File("foo"));
+    }
+
+    public void testAnExistingFile() {
+        assertMatches("matches existing file", FileMatchers.anExistingFile(), file);
+        assertDoesNotMatch("doesn't match existing directory", FileMatchers.anExistingFile(), directory);
+        assertDoesNotMatch("doesn't match missing file", FileMatchers.anExistingFile(), new File("foo"));
+    }
+
+    public void testAReadableFile() {
+        file.setReadable(true);
+        assertMatches("matches readable file", FileMatchers.aReadableFile(), file);
+        if (file.setReadable(false)) {
+            assertDoesNotMatch("doesn't match unreadable file", FileMatchers.aReadableFile(), file);
+        }
+    }
+
+    public void testAWritableFile() {
+        assertMatches("matches writable file", FileMatchers.aWritableFile(), file);
+        file.setWritable(false);
+        assertDoesNotMatch("doesn't match unwritable file", FileMatchers.aWritableFile(), file);
+    }
+
+    public void testAFileWithSizeLong() {
+        assertMatches("matches file size", FileMatchers.aFileWithSize(0L), file);
+        file.setWritable(false);
+        assertDoesNotMatch("doesn't match incorrect file size", FileMatchers.aFileWithSize(34L), file);
+    }
+
+    public void testAFileWithSizeMatcherOfLong() {
+        assertMatches("matches file size", FileMatchers.aFileWithSize(equalTo(0L)), file);
+        file.setWritable(false);
+        assertDoesNotMatch("doesn't match incorrect file size", FileMatchers.aFileWithSize(equalTo(23L)), file);
+    }
+
+    public void testAFileNamed() {
+        assertMatches("matches file name", FileMatchers.aFileNamed(equalTo(file.getName())), file);
+        file.setWritable(false);
+        assertDoesNotMatch("doesn't match incorrect file name", FileMatchers.aFileNamed(equalTo("foo")), file);
+    }
+
+    public void testAFileWithCanonicalPath() throws Exception {
+        assertMatches("matches file canonical path", FileMatchers.aFileWithCanonicalPath(equalTo(file.getCanonicalPath())), file);
+        file.setWritable(false);
+        assertDoesNotMatch("doesn't match incorrect canonical path", FileMatchers.aFileWithCanonicalPath(equalTo("foo")), file);
+    }
+
+    public void testAFileWithAbsolutePath() {
+        assertMatches("matches file absolute path", FileMatchers.aFileWithAbsolutePath(equalTo(file.getAbsolutePath())), file);
+        file.setWritable(false);
+        assertDoesNotMatch("doesn't match incorrect absolute path", FileMatchers.aFileWithAbsolutePath(equalTo("foo")), file);
+    }
+
+    @Override
+    protected Matcher<?> createMatcher() {
+        return FileMatchers.aFileWithSize(1L);
+    }
+
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/number/BigDecimalCloseToTest.java b/hamcrest-library/src/test/java/org/hamcrest/number/BigDecimalCloseToTest.java
new file mode 100644
index 0000000..c82e6f4
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/number/BigDecimalCloseToTest.java
@@ -0,0 +1,45 @@
+package org.hamcrest.number;
+
+import org.hamcrest.AbstractMatcherTest;
+import org.hamcrest.Matcher;
+
+import java.math.BigDecimal;
+
+import static org.hamcrest.number.BigDecimalCloseTo.closeTo;
+
+public class BigDecimalCloseToTest  extends AbstractMatcherTest {
+  private final Matcher<BigDecimal> matcher = closeTo(new BigDecimal("1.0"), new BigDecimal("0.5"));
+
+  @Override
+  protected Matcher<?> createMatcher() {
+    BigDecimal irrelevant = new BigDecimal("0.01");
+    return closeTo(irrelevant, irrelevant);
+  }
+  
+  public void testEvaluatesToTrueIfArgumentIsEqualToABigDecimalWithinSomeError() {
+    assertTrue(matcher.matches(new BigDecimal("1.0")));
+    assertTrue(matcher.matches(new BigDecimal("0.5")));
+    assertTrue(matcher.matches(new BigDecimal("1.5")));
+
+    assertDoesNotMatch("too large", matcher, new BigDecimal("2.0"));
+    assertMismatchDescription("<2.0> differed by <0.5> more than delta <0.5>", matcher, new BigDecimal("2.0"));
+    assertDoesNotMatch("number too small", matcher, new BigDecimal("0.0"));
+    assertMismatchDescription("<0.0> differed by <0.5> more than delta <0.5>", matcher, new BigDecimal("0.0"));
+  }
+  
+  public void testEvaluatesToTrueIfArgumentHasDifferentScale() {
+    assertTrue(matcher.matches(new BigDecimal("1.000000")));
+    assertTrue(matcher.matches(new BigDecimal("0.500000")));
+    assertTrue(matcher.matches(new BigDecimal("1.500000")));
+
+    assertDoesNotMatch("too large", matcher, new BigDecimal("2.000000"));
+    assertMismatchDescription("<2.000000> differed by <0.5> more than delta <0.5>", matcher, new BigDecimal("2.000000"));
+    assertDoesNotMatch("number too small", matcher, new BigDecimal("0.000000"));
+    assertMismatchDescription("<0.000000> differed by <0.5> more than delta <0.5>", matcher, new BigDecimal("0.000000"));
+  }
+
+  public void test_is_self_describing() {
+    assertDescription("a numeric value within <0.5> of <1.0>", matcher);
+  }
+
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/number/IsCloseToTest.java b/hamcrest-library/src/test/java/org/hamcrest/number/IsCloseToTest.java
new file mode 100644
index 0000000..8b0e244
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/number/IsCloseToTest.java
@@ -0,0 +1,32 @@
+package org.hamcrest.number;
+
+import org.hamcrest.AbstractMatcherTest;
+import org.hamcrest.Matcher;
+
+import static org.hamcrest.number.IsCloseTo.closeTo;
+
+public class IsCloseToTest extends AbstractMatcherTest {
+  private final Matcher<Double> matcher = closeTo(1.0d, 0.5d);
+
+  @Override
+    protected Matcher<?> createMatcher() {
+        final double irrelevant = 0.1;
+        return closeTo(irrelevant, irrelevant);
+    }
+
+    public void test_matchesIfArgumentIsEqualToADoubleValueWithinSomeError() {
+        assertMatches("1.0", matcher, 1.0);
+        assertMatches("0.5d", matcher, 0.5d);
+        assertMatches("1.5d", matcher, 1.5d);
+
+        assertDoesNotMatch("too large", matcher, 2.0);
+        assertMismatchDescription("<3.0> differed by <1.5> more than delta <0.5>", matcher, 3.0d);
+        assertDoesNotMatch("number too small", matcher, 0.0);
+        assertMismatchDescription("<0.1> differed by <0.4> more than delta <0.5>", matcher, 0.1);
+    }
+
+    public void test_is_self_describing() {
+        assertDescription("a numeric value within <0.5> of <1.0>", matcher);
+    }
+
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/number/IsNanTest.java b/hamcrest-library/src/test/java/org/hamcrest/number/IsNanTest.java
new file mode 100644
index 0000000..c9b3956
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/number/IsNanTest.java
@@ -0,0 +1,43 @@
+package org.hamcrest.number;
+
+import org.hamcrest.Matcher;
+import org.junit.Test;
+
+import static org.hamcrest.AbstractMatcherTest.*;
+import static org.hamcrest.number.IsNaN.notANumber;
+
+public final class IsNanTest {
+
+    @Test public void
+    copesWithNullsAndUnknownTypes() {
+        Matcher<Double> matcher = notANumber();
+        
+        assertNullSafe(matcher);
+        assertUnknownTypeSafe(matcher);
+    }
+
+    @Test public void
+    matchesNaN() {
+        assertMatches(notANumber(), Double.NaN);
+    }
+
+    @Test public void
+    doesNotMatchDoubleValue() {
+        assertDoesNotMatch(notANumber(), 1.25);
+    }
+
+    @Test public void
+    doesNotMatchInfinity() {
+        assertDoesNotMatch(notANumber(), Double.POSITIVE_INFINITY);
+    }
+
+    @Test public void
+    describesItself() {
+        assertDescription("a double value of NaN", notANumber());
+    }
+
+    @Test public void
+    describesAMismatch() {
+        assertMismatchDescription("was <1.25>", notANumber(), 1.25);
+    }
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/number/OrderingComparisonTest.java b/hamcrest-library/src/test/java/org/hamcrest/number/OrderingComparisonTest.java
new file mode 100644
index 0000000..5953bd0
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/number/OrderingComparisonTest.java
@@ -0,0 +1,80 @@
+package org.hamcrest.number;
+
+import org.hamcrest.AbstractMatcherTest;
+import org.hamcrest.Matcher;
+
+import java.math.BigDecimal;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.IsNot.not;
+import static org.hamcrest.number.OrderingComparison.*;
+
+public class OrderingComparisonTest extends AbstractMatcherTest {
+
+    @Override
+    protected Matcher<Integer> createMatcher() {
+        return greaterThan(1);
+    }
+
+    public void testDescription() {
+      assertDescription("a value greater than <1>", greaterThan(1));
+      assertDescription("a value equal to or greater than <1>", greaterThanOrEqualTo(1));
+      assertDescription("a value equal to <1>", comparesEqualTo(1));
+      assertDescription("a value less than or equal to <1>", lessThanOrEqualTo(1));
+      assertDescription("a value less than <1>", lessThan(1));
+    }
+
+    public void testMismatchDescriptions() {
+      assertMismatchDescription("<0> was less than <1>", greaterThan(1), 0);
+      assertMismatchDescription("<1> was equal to <1>", greaterThan(1), 1);
+      assertMismatchDescription("<1> was greater than <0>", lessThan(0), 1);
+      assertMismatchDescription("<2> was equal to <2>", lessThan(2), 2);
+    }
+
+    public void testComparesObjectsForGreaterThan() {
+        assertThat(2, greaterThan(1));
+        assertThat(0, not(greaterThan(1)));
+    }
+
+    public void testComparesObjectsForLessThan() {
+        assertThat(2, lessThan(3));
+        assertThat(0, lessThan(1));
+    }
+
+
+    public void testComparesObjectsForEquality() {
+      assertThat(3, comparesEqualTo(3));
+      assertThat("aa", comparesEqualTo("aa"));
+    }
+
+    public void testAllowsForInclusiveComparisons() {
+        assertThat("less", 1, lessThanOrEqualTo(1));
+        assertThat("greater", 1, greaterThanOrEqualTo(1));
+    }
+
+    public void testSupportsDifferentTypesOfComparableObjects() {
+        assertThat(1.1, greaterThan(1.0));
+        assertThat("cc", greaterThan("bb"));
+    }
+
+    public void testComparesBigDecimalsWithDifferentScalesCorrectlyForIssue20() {
+      assertThat(new BigDecimal("10.0"), greaterThanOrEqualTo(new BigDecimal("10")));
+      assertThat(new BigDecimal(10), greaterThanOrEqualTo(new BigDecimal("10.0")));
+      assertThat(new BigDecimal("2"), comparesEqualTo(new BigDecimal("2.000")));
+    }
+    
+    public void testComparesCustomTypesWhoseCompareToReturnsValuesGreaterThatOne() {
+        assertThat(new CustomInt(5), lessThan(new CustomInt(10)));
+    }
+
+    private static final class CustomInt implements Comparable<CustomInt> {
+        private final int value;
+        public CustomInt(int value) {
+            this.value = value;
+        }
+
+        public int compareTo(CustomInt other) {
+            return value - other.value;
+        }
+    }
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/object/HasToStringTest.java b/hamcrest-library/src/test/java/org/hamcrest/object/HasToStringTest.java
new file mode 100644
index 0000000..5c75ae7
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/object/HasToStringTest.java
@@ -0,0 +1,55 @@
+package org.hamcrest.object;
+
+import org.hamcrest.Matcher;
+import org.junit.Test;
+
+import static org.hamcrest.AbstractMatcherTest.*;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.hamcrest.object.HasToString.hasToString;
+
+public final class HasToStringTest {
+    private static final String TO_STRING_RESULT = "toString result";
+    private static final Object TEST_OBJECT = new Object() {
+        @Override
+        public String toString() {
+            return TO_STRING_RESULT;
+        }
+    };
+
+    @Test public void
+    copesWithNullsAndUnknownTypes() {
+        Matcher<Object> matcher = hasToString(equalTo("irrelevant"));
+        
+        assertNullSafe(matcher);
+        assertUnknownTypeSafe(matcher);
+    }
+    
+    @Test public void
+    matchesWhenUtilisingANestedMatcher() {
+    	final Matcher<Object> matcher = hasToString(equalTo(TO_STRING_RESULT));
+
+    	assertMatches(matcher, TEST_OBJECT);
+    	assertDoesNotMatch(matcher, new Object());
+    }
+
+    @Test public void
+    matchesWhenUsingShortcutForHasToStringEqualTo() {
+    	final Matcher<Object> matcher = hasToString(TO_STRING_RESULT);
+    	
+		assertMatches(matcher, TEST_OBJECT);
+    	assertDoesNotMatch(matcher, new Object());
+    }
+
+    @Test public void
+    describesItself() {
+    	final Matcher<Object> matcher = hasToString(equalTo(TO_STRING_RESULT));
+        assertDescription("with toString() \"toString result\"", matcher);
+    }
+
+    @Test public void
+    describesAMismatch() {
+    	final Matcher<Object> matcher = hasToString(equalTo(TO_STRING_RESULT));
+    	String expectedMismatchString = "toString() was \"Cheese\"";
+        assertMismatchDescription(expectedMismatchString, matcher, "Cheese");
+    }
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/object/IsCompatibleTypeTest.java b/hamcrest-library/src/test/java/org/hamcrest/object/IsCompatibleTypeTest.java
new file mode 100644
index 0000000..8432fdb
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/object/IsCompatibleTypeTest.java
@@ -0,0 +1,58 @@
+package org.hamcrest.object;
+
+import org.hamcrest.AbstractMatcherTest;
+import org.hamcrest.Matcher;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.object.IsCompatibleType.typeCompatibleWith;
+
+public class IsCompatibleTypeTest extends AbstractMatcherTest {
+    public static class BaseClass {
+    }
+
+    public static class ExtendedClass extends BaseClass {
+    }
+
+    public interface BaseInterface {
+    }
+
+    public interface ExtendedInterface extends BaseInterface {
+    }
+
+    public static class ClassImplementingBaseInterface implements BaseInterface {
+    }
+
+    @Override
+    protected Matcher<?> createMatcher() {
+        return typeCompatibleWith(BaseClass.class);
+    }
+
+    public void testMatchesSameClass() {
+        assertThat(BaseClass.class, typeCompatibleWith(BaseClass.class));
+    }
+
+    public void testMatchesSameInterface() {
+        assertThat(BaseInterface.class, typeCompatibleWith(BaseInterface.class));
+    }
+
+    public void testMatchesExtendedClass() {
+        assertThat(ExtendedClass.class, typeCompatibleWith(BaseClass.class));
+    }
+
+    public void testMatchesClassImplementingInterface() {
+        assertThat(ClassImplementingBaseInterface.class, typeCompatibleWith(BaseInterface.class));
+    }
+
+    public void testMatchesExtendedInterface() {
+        assertThat(ExtendedInterface.class, typeCompatibleWith(BaseInterface.class));
+    }
+
+//    public void testDoesNotMatchIncompatibleTypes() {
+//        assertThat(BaseClass.class, not(compatibleType(ExtendedClass.class)));
+//        assertThat(Integer.class, not(compatibleType(String.class)));
+//    }
+
+    public void testHasReadableDescription() {
+        assertDescription("type < java.lang.Runnable", typeCompatibleWith(Runnable.class));
+    }
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/object/IsEventFromTest.java b/hamcrest-library/src/test/java/org/hamcrest/object/IsEventFromTest.java
new file mode 100644
index 0000000..b3c4a3a
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/object/IsEventFromTest.java
@@ -0,0 +1,52 @@
+package org.hamcrest.object;
+
+import org.hamcrest.AbstractMatcherTest;
+import org.hamcrest.Matcher;
+
+import java.util.EventObject;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.object.IsEventFrom.eventFrom;
+
+
+public class IsEventFromTest extends AbstractMatcherTest {
+
+    @Override
+    protected Matcher<?> createMatcher() {
+        return eventFrom(null);
+    }
+
+    public void testEvaluatesToTrueIfArgumentIsAnEventObjectFiredByASpecifiedSource() {
+        Object o = "Source";
+        EventObject ev = new EventObject(o);
+        EventObject ev2 = new EventObject("source 2");
+
+        Matcher<EventObject> isEventMatcher = eventFrom(o);
+
+        assertThat(ev, isEventMatcher);
+        assertMismatchDescription("source was \"source 2\"", isEventMatcher, ev2);
+    }
+
+    private static class DerivedEvent extends EventObject {
+        private static final long serialVersionUID = 1L;
+
+        public DerivedEvent(Object source) {
+            super(source);
+        }
+    }
+
+    public void testCanTestForSpecificEventClasses() {
+        Object o = new Object();
+        DerivedEvent goodEv = new DerivedEvent(o);
+        DerivedEvent wrongSource = new DerivedEvent("wrong source");
+        EventObject wrongType = new EventObject(o);
+        EventObject wrongSourceAndType = new EventObject(new Object());
+
+        Matcher<EventObject> isEventMatcher = IsEventFrom.eventFrom(DerivedEvent.class, o);
+
+        assertThat(goodEv, isEventMatcher);
+        assertMismatchDescription("source was \"wrong source\"", isEventMatcher, wrongSource);
+        assertMismatchDescription("item type was java.util.EventObject", isEventMatcher, wrongType);
+        assertMismatchDescription("item type was java.util.EventObject", isEventMatcher, wrongSourceAndType);
+    }
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/object/MatchesPatternTest.java b/hamcrest-library/src/test/java/org/hamcrest/object/MatchesPatternTest.java
new file mode 100644
index 0000000..3e2d911
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/object/MatchesPatternTest.java
@@ -0,0 +1,59 @@
+package org.hamcrest.object;
+
+import org.hamcrest.Matcher;
+import org.hamcrest.text.MatchesPattern;
+import org.junit.Test;
+
+import java.util.regex.Pattern;
+
+import static org.hamcrest.AbstractMatcherTest.*;
+import static org.junit.Assert.assertThat;
+
+public class MatchesPatternTest {
+    @Test
+    public void copesWithNullsAndUnknownTypes() {
+        Matcher<String> matcher = new MatchesPattern(Pattern.compile("."));
+
+        assertNullSafe(matcher);
+        assertUnknownTypeSafe(matcher);
+    }
+
+    @Test
+    public void matchesExactString() {
+        assertThat("a", new MatchesPattern(Pattern.compile("a")));
+    }
+
+    @Test
+    public void doesNotMatchADifferentString() {
+        assertDoesNotMatch("A different string does not match", new MatchesPattern(Pattern.compile("a")), "b");
+    }
+
+    @Test
+    public void doesNotMatchSubstring() {
+        assertDoesNotMatch("A substring does not match", new MatchesPattern(Pattern.compile("a")), "ab");
+    }
+
+    @Test
+    public void hasAReadableDescription() {
+        Matcher<?> m = new MatchesPattern(Pattern.compile("a[bc](d|e)"));
+        assertDescription("a string matching the pattern 'a[bc](d|e)'", m );
+    }
+
+    @Test
+    public void describesAMismatch() {
+        final Matcher<String> matcher = new MatchesPattern(Pattern.compile("a"));
+        assertMismatchDescription("was \"Cheese\"", matcher, "Cheese");
+    }
+
+    @Test
+    public void factoryMethodAllowsCreationWithPattern() {
+        Matcher<?> m = MatchesPattern.matchesPattern(Pattern.compile("a[bc](d|e)"));
+        assertDescription("a string matching the pattern 'a[bc](d|e)'", m );
+    }
+
+    @Test
+    public void factoryMethodAllowsCreationWithString() {
+        Matcher<?> m = MatchesPattern.matchesPattern("a[bc](d|e)");
+        assertDescription("a string matching the pattern 'a[bc](d|e)'", m );
+    }
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/text/IsBlankStringTest.java b/hamcrest-library/src/test/java/org/hamcrest/text/IsBlankStringTest.java
new file mode 100644
index 0000000..c5f35f1
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/text/IsBlankStringTest.java
@@ -0,0 +1,55 @@
+package org.hamcrest.text;
+
+import org.hamcrest.Matcher;
+import org.junit.Test;
+
+import static org.hamcrest.AbstractMatcherTest.*;
+import static org.hamcrest.text.IsBlankString.blankOrNullString;
+import static org.hamcrest.text.IsBlankString.blankString;
+
+public final class IsBlankStringTest {
+
+    @Test public void
+    copesWithNullsAndUnknownTypes() {
+        Matcher<String> matcher = blankString();
+        
+        assertNullSafe(matcher);
+        assertUnknownTypeSafe(matcher);
+    }
+
+    @Test public void
+    matchesEmptyString() {
+        assertMatches(blankOrNullString(), "");
+        assertMatches(blankString(), "");
+    }
+
+    @Test public void
+    matchesNullAppropriately() {
+        assertMatches(blankOrNullString(), null);
+        assertDoesNotMatch(blankString(), null);
+    }
+
+    @Test public void
+    matchesBlankStringAppropriately() {
+        assertMatches(blankString(), " \t");
+        assertMatches(blankOrNullString(), " \t");
+    }
+
+    @Test public void
+    doesNotMatchFilledString() {
+        assertDoesNotMatch(blankString(), "a");
+        assertDoesNotMatch(blankOrNullString(), "a");
+    }
+
+    @Test public void
+    describesItself() {
+        assertDescription("a blank string", blankString());
+        assertDescription("(null or a blank string)", blankOrNullString());
+    }
+
+    @Test public void
+    describesAMismatch() {
+        assertMismatchDescription("was \"a\"", blankString(), "a");
+        assertMismatchDescription("was \"a\"", blankOrNullString(), "a");
+    }
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/text/IsEmptyStringTest.java b/hamcrest-library/src/test/java/org/hamcrest/text/IsEmptyStringTest.java
new file mode 100644
index 0000000..62e3053
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/text/IsEmptyStringTest.java
@@ -0,0 +1,55 @@
+package org.hamcrest.text;
+
+import org.hamcrest.Matcher;
+import org.junit.Test;
+
+import static org.hamcrest.AbstractMatcherTest.*;
+import static org.hamcrest.text.IsEmptyString.emptyOrNullString;
+import static org.hamcrest.text.IsEmptyString.emptyString;
+
+public final class IsEmptyStringTest {
+
+    @Test public void
+    copesWithNullsAndUnknownTypes() {
+        Matcher<String> matcher = emptyString();
+        
+        assertNullSafe(matcher);
+        assertUnknownTypeSafe(matcher);
+    }
+
+    @Test public void
+    matchesEmptyString() {
+        assertMatches(emptyOrNullString(), "");
+        assertMatches(emptyString(), "");
+    }
+
+    @Test public void
+    matchesNullAppropriately() {
+        assertMatches(emptyOrNullString(), null);
+        assertDoesNotMatch(emptyString(), null);
+    }
+
+    @Test public void
+    matchesBlankStringAppropriately() {
+        assertDoesNotMatch(emptyString(), "  ");
+        assertDoesNotMatch(emptyOrNullString(), "  ");
+    }
+
+    @Test public void
+    doesNotMatchFilledString() {
+        assertDoesNotMatch(emptyString(), "a");
+        assertDoesNotMatch(emptyOrNullString(), "a");
+    }
+
+    @Test public void
+    describesItself() {
+        assertDescription("an empty string", emptyString());
+        assertDescription("(null or an empty string)", emptyOrNullString());
+    }
+
+    @Test public void
+    describesAMismatch() {
+        assertMismatchDescription("was \"a\"", emptyString(), "a");
+        assertMismatchDescription("was \"a\"", emptyOrNullString(), "a");
+    }
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/text/IsEqualIgnoringCaseTest.java b/hamcrest-library/src/test/java/org/hamcrest/text/IsEqualIgnoringCaseTest.java
new file mode 100644
index 0000000..4800f43
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/text/IsEqualIgnoringCaseTest.java
@@ -0,0 +1,62 @@
+package org.hamcrest.text;
+
+import org.hamcrest.Matcher;
+import org.junit.Test;
+
+import static org.hamcrest.AbstractMatcherTest.*;
+import static org.hamcrest.text.IsEqualIgnoringCase.equalToIgnoringCase;
+
+public final class IsEqualIgnoringCaseTest {
+
+    @Test public void
+    copesWithNullsAndUnknownTypes() {
+        Matcher<String> matcher = equalToIgnoringCase("irrelevant");
+        
+        assertNullSafe(matcher);
+        assertUnknownTypeSafe(matcher);
+    }
+
+    @Test public void
+    ignoresCaseOfCharsInString() {
+        final Matcher<String> matcher = equalToIgnoringCase("heLLo");
+		
+        assertMatches(matcher, "HELLO");
+        assertMatches(matcher, "hello");
+        assertMatches(matcher, "HelLo");
+    	assertDoesNotMatch(matcher, "bye");
+    }
+
+    @Test public void 
+    mismatchesIfAdditionalWhitespaceIsPresent() {
+    	final Matcher<String> matcher = equalToIgnoringCase("heLLo");
+		
+    	assertDoesNotMatch(matcher, "hello ");
+    	assertDoesNotMatch(matcher, " hello");
+    }
+
+    @Test public void 
+    mismatchesNull() {
+    	final Matcher<String> matcher = equalToIgnoringCase("heLLo");
+		
+    	assertDoesNotMatch(matcher, null);
+    }
+
+    @Test(expected=IllegalArgumentException.class) public void
+    canOnlyBeConstructedAboutANonNullString() {
+        equalToIgnoringCase(null);
+    }
+
+
+    @Test public void
+    describesItself() {
+    	final Matcher<String> matcher = equalToIgnoringCase("heLLo");
+        assertDescription("equalToIgnoringCase(\"heLLo\")", matcher);
+    }
+
+    @Test public void
+    describesAMismatch() {
+    	final Matcher<String> matcher = equalToIgnoringCase("heLLo");
+    	String expectedMismatchString = "was \"Cheese\"";
+        assertMismatchDescription(expectedMismatchString, matcher, "Cheese");
+    }
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/text/IsEqualIgnoringWhiteSpaceTest.java b/hamcrest-library/src/test/java/org/hamcrest/text/IsEqualIgnoringWhiteSpaceTest.java
new file mode 100644
index 0000000..d5c7576
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/text/IsEqualIgnoringWhiteSpaceTest.java
@@ -0,0 +1,51 @@
+package org.hamcrest.text;
+
+import org.hamcrest.AbstractMatcherTest;
+import org.hamcrest.Matcher;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.IsNot.not;
+import static org.hamcrest.text.IsEqualIgnoringWhiteSpace.equalToIgnoringWhiteSpace;
+
+public class IsEqualIgnoringWhiteSpaceTest extends AbstractMatcherTest {
+
+    private final Matcher<String> matcher = equalToIgnoringWhiteSpace("Hello World   how\n are we? ");
+
+    @Override
+    protected Matcher<?> createMatcher() {
+        return matcher;
+    }
+
+    public void testPassesIfWordsAreSameButWhitespaceDiffers() {
+        assertThat("Hello World how are we?", matcher);
+        assertThat("   Hello World   how are \n\n\twe?", matcher);
+    }
+
+    public void testFailsIfTextOtherThanWhitespaceDiffers() {
+        assertThat("Hello PLANET how are we?", not(matcher));
+        assertThat("Hello World how are we", not(matcher));
+    }
+
+    public void testFailsIfWhitespaceIsAddedOrRemovedInMidWord() {
+        assertThat("HelloWorld how are we?", not(matcher));
+        assertThat("Hello Wo rld how are we?", not(matcher));
+    }
+
+    public void testFailsIfMatchingAgainstNull() {
+        assertThat(null, not(matcher));
+    }
+
+    public void testRequiresNonNullStringToBeConstructed() {
+        try {
+            new IsEqualIgnoringWhiteSpace(null);
+            fail("Expected exception");
+        } catch (IllegalArgumentException goodException) {
+            // expected!
+        }
+    }
+
+    public void testHasAReadableDescription() {
+        assertDescription("equalToIgnoringWhiteSpace(\"Hello World   how\\n are we? \")",
+                        matcher);
+    }
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/text/StringContainsInOrderTest.java b/hamcrest-library/src/test/java/org/hamcrest/text/StringContainsInOrderTest.java
new file mode 100644
index 0000000..8ffbc67
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/text/StringContainsInOrderTest.java
@@ -0,0 +1,30 @@
+package org.hamcrest.text;
+
+import org.hamcrest.AbstractMatcherTest;
+import org.hamcrest.Matcher;
+
+import static java.util.Arrays.asList;
+
+
+public class StringContainsInOrderTest extends AbstractMatcherTest {
+    StringContainsInOrder m = new StringContainsInOrder(asList("a", "b", "c"));
+
+    @Override
+    protected Matcher<?> createMatcher() {
+        return m;
+    }
+    
+    public void testMatchesOnlyIfStringContainsGivenSubstringsInTheSameOrder() {
+        assertMatches("substrings in order", m, "abc");
+        assertMatches("substrings separated", m, "1a2b3c4");
+        
+        assertDoesNotMatch("substrings out of order", m, "cab");
+        assertDoesNotMatch("no substrings in string", m, "xyz");
+        assertDoesNotMatch("substring missing", m, "ac");
+        assertDoesNotMatch("empty string", m, "");
+    }
+    
+    public void testHasAReadableDescription() {
+        assertDescription("a string containing \"a\", \"b\", \"c\" in order", m);
+    }
+}
diff --git a/hamcrest-library/src/test/java/org/hamcrest/xml/HasXPathTest.java b/hamcrest-library/src/test/java/org/hamcrest/xml/HasXPathTest.java
new file mode 100644
index 0000000..a66689d
--- /dev/null
+++ b/hamcrest-library/src/test/java/org/hamcrest/xml/HasXPathTest.java
@@ -0,0 +1,147 @@
+package org.hamcrest.xml;
+
+import org.hamcrest.Matcher;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import java.io.ByteArrayInputStream;
+import java.util.HashSet;
+import java.util.Iterator;
+
+import static org.hamcrest.AbstractMatcherTest.*;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.hamcrest.core.IsNot.not;
+import static org.hamcrest.core.StringContains.containsString;
+import static org.hamcrest.xml.HasXPath.hasXPath;
+import static org.junit.Assert.fail;
+
+/**
+ * @author Joe Walnes
+ * @author Tom Denley
+ */
+public final class HasXPathTest {
+
+    private final Document xml = parse(""
+            + "<root type='food'>\n"
+            + "  <something id='a'><cheese>Edam</cheese></something>\n"
+            + "  <something id='b'><cheese>Cheddar</cheese></something>\n"
+            + "  <f:foreignSomething xmlns:f=\"http://cheese.com\" milk=\"camel\">Caravane</f:foreignSomething>\n"
+            + "  <emptySomething />\n"
+            + "  <f:emptySomething xmlns:f=\"http://cheese.com\" />"
+            + "</root>\n"
+            );
+
+    private final NamespaceContext ns = new NamespaceContext() {
+        @Override
+        public String getNamespaceURI(String prefix) {
+            return ("cheese".equals(prefix) ? "http://cheese.com" : null);
+        }
+
+        @Override
+        public String getPrefix(String namespaceURI) {
+            return ("http://cheese.com".equals(namespaceURI) ? "cheese" : null);
+        }
+
+        @Override
+        public Iterator<String> getPrefixes(String namespaceURI) {
+            HashSet<String> prefixes = new HashSet<String>();
+            String prefix = getPrefix(namespaceURI);
+            if (prefix != null) {
+                prefixes.add(prefix);
+            }
+            return prefixes.iterator();
+        }
+    };
+
+    @Test public void
+    copesWithNullsAndUnknownTypes() {
+        Matcher<Node> matcher = hasXPath("//irrelevant");
+        
+        assertNullSafe(matcher);
+        assertUnknownTypeSafe(matcher);
+    }
+
+    @Test public void
+    appliesMatcherToXPathInDocument() {
+        assertMatches(hasXPath("/root/something[2]/cheese", equalTo("Cheddar")), xml);
+        assertMatches(hasXPath("//something[1]/cheese", containsString("dam")), xml);
+        assertMatches(hasXPath("//something[2]/cheese", not(containsString("dam"))), xml);
+        assertMatches(hasXPath("/root/@type", equalTo("food")), xml);
+        assertMatches(hasXPath("//something[@id='b']/cheese", equalTo("Cheddar")), xml);
+        assertMatches(hasXPath("//something[@id='b']/cheese"), xml);
+    }
+
+    @Test public void
+    matchesEmptyElement() {
+        assertMatches(hasXPath("//emptySomething"), xml);
+    }
+
+    @Test public void
+    matchesEmptyElementInNamespace() {
+        assertMatches(hasXPath("//cheese:emptySomething", ns), xml);
+    }
+
+    @Test public void
+    failsIfNodeIsMissing() {
+        assertDoesNotMatch(hasXPath("/root/something[3]/cheese", ns, equalTo("Cheddar")), xml);
+        assertDoesNotMatch(hasXPath("//something[@id='c']/cheese", ns), xml);
+    }
+
+    @Test public void
+    failsIfNodeIsMissingInNamespace() {
+        assertDoesNotMatch(hasXPath("//cheese:foreignSomething", equalTo("Badger")), xml);
+        assertDoesNotMatch(hasXPath("//cheese:foreignSomething"), xml);
+    }
+
+    @Test public void
+    matchesWithNamespace() {
+        assertMatches(hasXPath("//cheese:foreignSomething", ns), xml);
+        assertMatches(hasXPath("//cheese:foreignSomething/@milk", ns, equalTo("camel")), xml);
+        assertMatches(hasXPath("//cheese:foreignSomething/text()", ns, equalTo("Caravane")), xml);
+    }
+
+    @Test public void
+    throwsIllegalArgumentExceptionIfGivenIllegalExpression() {
+        try {
+            hasXPath("\\g:dfgd::DSgf/root/something[2]/cheese", equalTo("blah"));
+            fail("Expected exception");
+        } catch (IllegalArgumentException expectedException) {
+            // expected exception
+        }
+    }
+
+    @Test public void
+    describesItself() {
+        assertDescription("an XML document with XPath /some/path \"Cheddar\"",
+                          hasXPath("/some/path", equalTo("Cheddar")));
+        
+        assertDescription("an XML document with XPath /some/path",
+                          hasXPath("/some/path"));
+    }
+
+    @Test public void
+    describesMissingNodeMismatch() {
+        assertMismatchDescription("xpath returned no results.", hasXPath("//honky"), xml);
+    }
+
+    @Test public void
+    describesIncorrectNodeValueMismatch() {
+        assertMismatchDescription("was \"Edam\"", hasXPath("//something[1]/cheese", equalTo("parmesan")), xml);
+    }
+
+    private static Document parse(String xml) {
+        try {
+            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+            documentBuilderFactory.setNamespaceAware(true);
+            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
+            return documentBuilder.parse(new ByteArrayInputStream(xml.getBytes()));
+        }
+        catch (Exception e) {
+            throw new IllegalStateException(e);
+        }
+    }
+}