package org.specs.matcher;
import MatcherUtils._
import java.util.regex._
/**
* The <code>StringMatchers</code> trait provides matchers which are applicable to String objects
*/
trait StringMatchers {
/**
* Matches if (a.equalsIgnoreCase(b))
*/
def equalIgnoreCase[T <: String](a: T) = new Matcher[T](){
def apply(v: => T) = {val b = v; (a != null && b != null && a.equalsIgnoreCase(b), q(b) + " is equal ignoring case to " + q(a), q(b) + " is not equal ignoring case to " + q(a))}
}
/**
* Matches if !(a.equalsIgnoreCase(b))
*/
def notEqualIgnoreCase[T <: String](a: T) = equalIgnoreCase(a).not
/**
* Matches if (a.trim == b.trim)
*/
def equalIgnoreSpace[T <: String](a: T) = new Matcher[T](){
def apply(v: => T) = {val b = v; (a != null && b != null && a.trim == b.trim, q(b) + " is equal ignoring space to " + q(a), q(b) + " is not equal ignoring space to " + q(a))}
}
/**
* Matches if !(a.equalsIgnoreSpace(b))
*/
def notEqualIgnoreSpace[T <: String](a: T) = equalIgnoreSpace(a).not
/**
* Matches if (b.indexOf(a) >= 0)
*/
def include[T <: String](a: String) = new Matcher[T](){
def apply(v: => T) = {val b = v; (a != null && b != null && b.indexOf(a) >= 0, q(b) + " includes " + q(a), q(b) + " doesn't include " + q(a))}
}
/**
* Matches if !(b.indexOf(a) >= 0)
*/
def notInclude[T <: String](a: T) = include[T](a).not
/**
* Matches if b matches the regular expression a
*/
def beMatching[T <: String](a: T) = new Matcher[T](){
def apply(v: => T) = {val b = v; (matches(a)(b), q(b) + " matches " + q(a), q(b) + " doesn't match " + q(a))}
}
/**
* Matches if b doesn't match the regular expression a
*/
def notBeMatching(a: String) = beMatching[String](a).not
/**
* Matches if b.startsWith(a)
*/
def startWith[T <: String](a: T) = new Matcher[T](){
def apply(v: => T) = {val b = v; (b!= null && a!= null && b.startsWith(a), q(b) + " starts with " + q(a), q(b) + " doesn't start with " + q(a))}
}
/**
* Matches if !b.startsWith(a)
*/
def notStartWith(a: String) = startWith[String](a).not
/**
* Matches if b.endsWith(a)
*/
def endWith[T <: String](a: T) = new Matcher[T](){
def apply(v: => T) = {val b = v; (a != null && b != null && b.endsWith(a), q(b) + " ends with " + q(a), q(b) + " doesn't end with " + q(a))}
}
/**
* Matches if !b.endsWith(a)
*/
def notEndWith(a: String) = endWith[String](a).not
/**
* Matches if the regexp a is found inside b
*/
def find[T <: String](a: T) = new FindMatcher(a)
/**
* Matcher to find if the regexp a is found inside b.
* This matcher can be specialized to a FindMatcherWithGroups which will also check the found groups
*/
class FindMatcher[T <: String](a: T) extends Matcher[T] {
def found(b: T) = {
val matcher = Pattern.compile(a).matcher(b)
matcher.find
}
def withGroup(group: String) = new FindMatcherWithGroups(a, group)
def withGroups(groups: String*) = new FindMatcherWithGroups(a, groups:_*)
def apply(v: => T) = {val b = v; (a != null && b != null && found(b), q(a) + " is found in " + q(b), q(a) + " isn't found in " + q(b))}
}
/**
* Matcher to find if the regexp a is found inside b.
* This matcher checks if the found groups are really the ones expected
*/
class FindMatcherWithGroups[T <: String](a: T, groups: String*) extends Matcher[T] {
def found(b: T) = {
val matcher = Pattern.compile(a).matcher(b)
val groupsFound = new scala.collection.mutable.ListBuffer[String]()
while (matcher.find) { groupsFound += matcher.group(1) }
groupsFound.toList
}
def apply(v: => T) = {
val b = v
val groupsFound = found(b)
val withGroups = if (groups.size > 1) " with groups " else " with group "
def foundText = {
if (groupsFound.isEmpty)
". Found nothing"
else
". Found: " + q(groupsFound.mkString(", "))
}
val groupsToFind = if (groups == null) Nil else groups.toList
(a != null && b != null && groupsFound == groupsToFind,
q(a) + " is found in " + q(b) + withGroups + q(groupsToFind.mkString(", ")),
q(a) + " isn't found in " + q(b) + withGroups + q(groupsToFind.mkString(", ")) + foundText
)
}
}
}