package com.bluecatcode.hamcrest.matchers;

import org.hamcrest.CustomTypeSafeMatcher;
import org.hamcrest.Description;
import org.hamcrest.StringDescription;

/**
 * Convenience class for writing one off matchers with validation.
 * <p>
 * You should provide a description and override the validation method.
 * </p>
 *
 * Usage:
 * <pre>
 *  public class IsValidEmail extends TypeSafeValidatingMatcher&lt;String&gt; {
 *      private static final IsValidEmail NOT_EMPTY_INSTANCE = new IsValidEmail();
 *
 *      public IsValidEmail() {
 *          super("a valid e-mail (RFC822)");
 *      }
 *
 *     {@literal @}Override
 *      protected boolean isValid(String item, Description errorDescription) {
 *          try {
 *              new InternetAddress(item).validate();
 *          } catch (AddressException ex) {
 *              errorDescription.appendText(ex.getMessage());
 *              return false;
 *          }
 *          return true;
 *      }
 *
 *     {@literal @}Factory
 *      public static Matcher&lt;? super String&gt; isValidEmail() {
 *          return NOT_EMPTY_INSTANCE;
 *      }
 *  }
 *
 * </pre>
 *
 * @param <T> The type of object being matched
 */
public abstract class TypeSafeValidatingMatcher<T> extends CustomTypeSafeMatcher<T> {

    private Description errorDescription = new StringDescription();

    public TypeSafeValidatingMatcher(String description) {
        super(description);
    }

    protected abstract boolean isValid(T item, Description errorDescription);

    @Override
    protected boolean matchesSafely(T item) {
        return item != null && isValid(item, errorDescription);
    }

    @Override
    protected void describeMismatchSafely(T item, Description mismatchDescription) {
        mismatchDescription.appendValue(item)
                .appendText(" is not valid, cause: ")
                .appendText(errorDescription.toString());
    }
}

@@ -41,51 +41,8 @@
 s;%0A%0A
-import org.hamcrest.CustomTypeSafeMatcher;%0A
 impo
@@ -108,16 +108,53 @@
 ription;
+%0Aimport org.hamcrest.TypeSafeMatcher;
 %0A%0A/**%0A *
@@ -1232,14 +1232,8 @@
 nds 
-Custom
 Type
@@ -1250,16 +1250,60 @@
 r%3CT%3E %7B%0A%0A
+    private final String fixedDescription;%0A%0A
     priv
@@ -1359,24 +1359,120 @@
 ription();%0A%0A
+    public TypeSafeValidatingMatcher() %7B%0A        this.fixedDescription = %22a valid item%22;%0A    %7D%0A%0A
     public T
@@ -1503,17 +1503,22 @@
 (String 
-d
+fixedD
 escripti
@@ -1535,15 +1535,38 @@
     
-super(d
+this.fixedDescription = fixedD
 escr
@@ -1563,33 +1563,32 @@
 fixedDescription
-)
 ;%0A    %7D%0A%0A    pro
@@ -1912,24 +1912,41 @@
 hDescription
+%0A                
 .appendValue
@@ -1998,16 +1998,284 @@
 alid
-,
  
+(
 cause:
+ '%22)%0A                .appendText(errorDescription.toString())%0A                .appendText(%22')%22);%0A    %7D%0A%0A    @Override%0A    public void describeTo(Description description) %7B%0A        description%0A                .appendText(fixedDescription)%0A                .appendText(%22,
  %22)%0A

Update TypeSafeValidatingMatcher