package jamex.link;

import java.io.ByteArrayInputStream;
import java.net.URL;
import java.util.regex.Pattern;
import javax.jms.Message;
import javax.jms.TextMessage;
import javax.xml.XMLConstants;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

public abstract class MessageVerifier
{
  public abstract void verifyMessage( final Message message ) throws Exception;

  public static MessageVerifier newRelaxNGVerifier( final URL url )
      throws Exception
  {
    return newXmlVerifier( XMLConstants.RELAXNG_NS_URI, url );
  }

  public static MessageVerifier newDTDVerifier( final URL url )
      throws Exception
  {
    return newXmlVerifier( XMLConstants.XML_DTD_NS_URI, url );
  }

  public static MessageVerifier newXSDVerifier( final URL url )
      throws Exception
  {
    return newXmlVerifier( XMLConstants.W3C_XML_SCHEMA_NS_URI, url );
  }

  public static MessageVerifier newRegexVerifier( final String pattern )
      throws Exception
  {
    return newRegexVerifier( Pattern.compile( pattern ) );
  }

  public static MessageVerifier newRegexVerifier( final Pattern pattern )
      throws Exception
  {
    return new RegexMessageVerifier( pattern );
  }

  private static MessageVerifier newXmlVerifier( final String schemaLanguage, final URL url )
      throws Exception
  {
    if( null == schemaLanguage ) throw new NullPointerException( "schemaLanguage" );
    if( null == url ) throw new NullPointerException( "url" );
    final SchemaFactory factory = SchemaFactory.newInstance( schemaLanguage );
    final Schema schema = factory.newSchema( url );
    return new XmlMessageVerifier( schema.newValidator() );
  }

  private static class XmlMessageVerifier
      extends MessageVerifier
  {
    private final Validator validator;

    private XmlMessageVerifier( final Validator validator )
    {
      this.validator = validator;
    }

    public void verifyMessage( final Message message ) throws Exception
    {
      final TextMessage textMessage = MessageUtil.castToType( message, TextMessage.class );
      validator.validate( new StreamSource( new ByteArrayInputStream( textMessage.getText().getBytes() ) ) );
    }
  }

  private static class RegexMessageVerifier
      extends MessageVerifier
  {
    private final Pattern pattern;

    private RegexMessageVerifier( final Pattern pattern )
    {
      this.pattern = pattern;
    }

    public void verifyMessage( final Message message ) throws Exception
    {
      final TextMessage textMessage = MessageUtil.castToType( message, TextMessage.class );
      if( !pattern.matcher( textMessage.getText() ).matches() )
      {
        final String errorMessage =
            "Message with ID = " + message.getJMSMessageID() + " failed to match pattern \"" + pattern.pattern() + "\".";
        throw new Exception( errorMessage );
      }
    }
  }
}


@@ -592,32 +592,43 @@
  newXmlVerifier(
+ %22RelaxNG%22,
  XMLConstants.RE
@@ -762,32 +762,39 @@
  newXmlVerifier(
+ %22DTD%22,
  XMLConstants.XM
@@ -936,16 +936,23 @@
 erifier(
+ %22XSD%22,
  XMLCons
@@ -1384,15 +1384,139 @@
 maLa
-nguage,
+bel,%0A                                                 final String schemaLanguage,%0A                                                
  fin
@@ -1868,16 +1868,53 @@
 erifier(
+ schemaLabel + %22 loaded from %22 + url,
  schema.
@@ -2004,32 +2004,75 @@
 ageVerifier%0A  %7B%0A
+    private final String m_noMatchMessage;%0A
     private fina
@@ -2075,32 +2075,34 @@
 final Validator 
+m_
 validator;%0A%0A    
@@ -2124,24 +2124,53 @@
 ageVerifier(
+ final String noMatchMessage,
  final Valid
@@ -2198,21 +2198,59 @@
 %7B%0A      
-this.
+m_noMatchMessage = noMatchMessage;%0A      m_
 validato
@@ -2447,16 +2447,38 @@
 ;%0A      
+try%0A      %7B%0A        m_
 validato
@@ -2569,24 +2569,274 @@
 es() ) ) );%0A
+      %7D%0A      catch( final Exception e )%0A      %7B%0A        final String errorMessage =%0A            %22Message with ID = %22 + message.getJMSMessageID() + %22 failed to match %22 + m_noMatchMessage + %22.%22;%0A        throw new Exception( errorMessage, e );%0A      %7D%0A
     %7D%0A  %7D%0A%0A 

Refactor the way the error messages are reported for verifier