Skip to content

Commit f072d61

Browse files
author
joeretro
committed
Added (optional) xml based configuration for generating AllMatchers class.
1 parent 4ca40cc commit f072d61

File tree

6 files changed

+290
-2
lines changed

6 files changed

+290
-2
lines changed

matchers.xml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<matchers>
2+
3+
<!-- Core -->
4+
<factory class="org.hamcrest.core.AllOf"/>
5+
<factory class="org.hamcrest.core.AnyOf"/>
6+
<factory class="org.hamcrest.core.IsNot"/>
7+
<factory class="org.hamcrest.core.IsEqual"/>
8+
<factory class="org.hamcrest.core.IsSame"/>
9+
<factory class="org.hamcrest.core.IsAnything"/>
10+
<factory class="org.hamcrest.core.IsNull"/>
11+
<factory class="org.hamcrest.core.IsIn"/>
12+
<factory class="org.hamcrest.core.IsInstanceOf"/>
13+
<factory class="org.hamcrest.core.Always"/>
14+
<factory class="org.hamcrest.core.DescribedAs"/>
15+
16+
<!-- Collection -->
17+
<factory class="org.hamcrest.collection.IsArray"/>
18+
<factory class="org.hamcrest.collection.IsArrayContaining"/>
19+
<factory class="org.hamcrest.collection.IsCollectionContaining"/>
20+
<factory class="org.hamcrest.collection.IsMapContaining"/>
21+
22+
<!-- Number -->
23+
<factory class="org.hamcrest.number.IsCloseTo"/>
24+
<factory class="org.hamcrest.number.OrderingComparisons"/>
25+
26+
<!-- Text -->
27+
<factory class="org.hamcrest.text.IsEqualIgnoringCase"/>
28+
<factory class="org.hamcrest.text.IsEqualIgnoringWhiteSpace"/>
29+
<factory class="org.hamcrest.text.StringContains"/>
30+
<factory class="org.hamcrest.text.StringEndsWith"/>
31+
<factory class="org.hamcrest.text.StringStartsWith"/>
32+
33+
<!-- Object -->
34+
<factory class="org.hamcrest.object.HasToString"/>
35+
<factory class="org.hamcrest.object.IsCompatibleType"/>
36+
<factory class="org.hamcrest.object.IsEventFrom"/>
37+
38+
<!-- Beans -->
39+
<factory class="org.hamcrest.beans.HasProperty"/>
40+
<factory class="org.hamcrest.beans.HasPropertyWithValue"/>
41+
42+
<!-- XML -->
43+
<factory class="org.hamcrest.xml.HasXPath"/>
44+
45+
</matchers>

src/generator/org/hamcrest/generator/FactoryMethod.java

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
/**
99
* Represents a Matcher Factory method.
10-
*
10+
* <p/>
1111
* <p>This class uses Strings to represent things instead of java.lang.reflect equivalents,
1212
* allowing methods to be defined from sources other than reflection of classes in the
1313
* classpath.
@@ -110,6 +110,53 @@ public String getJavaDoc() {
110110
return javaDoc;
111111
}
112112

113+
@Override
114+
public boolean equals(Object o) {
115+
if (this == o) return true;
116+
if (o == null || getClass() != o.getClass()) return false;
117+
118+
FactoryMethod that = (FactoryMethod) o;
119+
120+
if (exceptions != null ? !exceptions.equals(that.exceptions) : that.exceptions != null) return false;
121+
if (factoryMethod != null ? !factoryMethod.equals(that.factoryMethod) : that.factoryMethod != null)
122+
return false;
123+
if (genericTypeParameters != null ? !genericTypeParameters.equals(that.genericTypeParameters) : that.genericTypeParameters != null)
124+
return false;
125+
if (generifiedType != null ? !generifiedType.equals(that.generifiedType) : that.generifiedType != null)
126+
return false;
127+
if (javaDoc != null ? !javaDoc.equals(that.javaDoc) : that.javaDoc != null) return false;
128+
if (matcherClass != null ? !matcherClass.equals(that.matcherClass) : that.matcherClass != null) return false;
129+
if (parameters != null ? !parameters.equals(that.parameters) : that.parameters != null) return false;
130+
131+
return true;
132+
}
133+
134+
@Override
135+
public int hashCode() {
136+
int result;
137+
result = (matcherClass != null ? matcherClass.hashCode() : 0);
138+
result = 31 * result + (factoryMethod != null ? factoryMethod.hashCode() : 0);
139+
result = 31 * result + (generifiedType != null ? generifiedType.hashCode() : 0);
140+
result = 31 * result + (parameters != null ? parameters.hashCode() : 0);
141+
result = 31 * result + (exceptions != null ? exceptions.hashCode() : 0);
142+
result = 31 * result + (genericTypeParameters != null ? genericTypeParameters.hashCode() : 0);
143+
result = 31 * result + (javaDoc != null ? javaDoc.hashCode() : 0);
144+
return result;
145+
}
146+
147+
@Override
148+
public String toString() {
149+
return "{FactoryMethod: \n" +
150+
" matcherClass = " + matcherClass + "\n" +
151+
" factoryMethod = " + factoryMethod + "\n" +
152+
" generifiedType = " + generifiedType + "\n" +
153+
" parameters = " + parameters + "\n" +
154+
" exceptions = " + exceptions + "\n" +
155+
" genericTypeParameters = " + genericTypeParameters + "\n" +
156+
" javaDoc = " + javaDoc + "\n" +
157+
"}";
158+
}
159+
113160
/**
114161
* Represents a parameter passed to a factory method.
115162
*
@@ -140,6 +187,31 @@ public String getName() {
140187
return name;
141188
}
142189

190+
@Override
191+
public boolean equals(Object o) {
192+
if (this == o) return true;
193+
if (o == null || getClass() != o.getClass()) return false;
194+
195+
Parameter parameter = (Parameter) o;
196+
197+
if (name != null ? !name.equals(parameter.name) : parameter.name != null) return false;
198+
if (type != null ? !type.equals(parameter.type) : parameter.type != null) return false;
199+
200+
return true;
201+
}
202+
203+
@Override
204+
public int hashCode() {
205+
int result;
206+
result = (type != null ? type.hashCode() : 0);
207+
result = 31 * result + (name != null ? name.hashCode() : 0);
208+
return result;
209+
}
210+
211+
@Override
212+
public String toString() {
213+
return type + " " + name;
214+
}
143215
}
144216

145217
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package org.hamcrest.generator;
2+
3+
public interface SugarConfiguration {
4+
void addWriter(FactoryWriter factoryWriter);
5+
6+
void addFactoryMethod(FactoryMethod method);
7+
8+
void addFactoryMethods(Iterable<FactoryMethod> methods);
9+
}

src/generator/org/hamcrest/generator/SugarGenerator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
* @see HamcrestFactoryWriter
4444
* @see ReflectiveFactoryReader
4545
*/
46-
public class SugarGenerator implements Closeable {
46+
public class SugarGenerator implements Closeable, SugarConfiguration {
4747

4848
private final List<FactoryWriter> factoryWriters = new ArrayList<FactoryWriter>();
4949
private final List<FactoryMethod> factoryMethods = new ArrayList<FactoryMethod>();
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package org.hamcrest.generator.config;
2+
3+
import org.hamcrest.generator.ReflectiveFactoryReader;
4+
import org.hamcrest.generator.SugarConfiguration;
5+
import org.hamcrest.generator.SugarGenerator;
6+
import org.xml.sax.Attributes;
7+
import org.xml.sax.InputSource;
8+
import org.xml.sax.SAXException;
9+
import org.xml.sax.helpers.DefaultHandler;
10+
11+
import javax.xml.parsers.ParserConfigurationException;
12+
import javax.xml.parsers.SAXParser;
13+
import javax.xml.parsers.SAXParserFactory;
14+
import java.io.IOException;
15+
16+
public class XmlConfigurator {
17+
18+
private final SugarConfiguration sugarConfiguration;
19+
private final ClassLoader classLoader;
20+
private final SAXParserFactory saxParserFactory;
21+
22+
public XmlConfigurator(SugarConfiguration sugarConfiguration, ClassLoader classLoader) {
23+
this.sugarConfiguration = sugarConfiguration;
24+
this.classLoader = classLoader;
25+
saxParserFactory = SAXParserFactory.newInstance();
26+
saxParserFactory.setNamespaceAware(true);
27+
}
28+
29+
public void load(InputSource inputSource) throws ParserConfigurationException, SAXException, IOException {
30+
SAXParser saxParser = saxParserFactory.newSAXParser();
31+
saxParser.parse(inputSource, new DefaultHandler() {
32+
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
33+
if (localName.equals("factory")) {
34+
String className = attributes.getValue("class");
35+
try {
36+
addClass(className);
37+
} catch (ClassNotFoundException e) {
38+
throw new SAXException("Cannot find Matcher class : " + className);
39+
}
40+
} else {
41+
System.err.println("uri=" + uri + ", localname=" + localName + ", qname=" + qName);
42+
43+
}
44+
}
45+
});
46+
}
47+
48+
private void addClass(String className) throws ClassNotFoundException {
49+
Class cls = classLoader.loadClass(className);
50+
sugarConfiguration.addFactoryMethods(new ReflectiveFactoryReader(cls));
51+
}
52+
53+
public static void main(String[] args) throws Exception {
54+
XmlConfigurator config = new XmlConfigurator(new SugarGenerator(), XmlConfigurator.class.getClassLoader());
55+
config.load(new InputSource("matchers.xml"));
56+
}
57+
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package org.hamcrest.generator.config;
2+
3+
import junit.framework.TestCase;
4+
import org.hamcrest.Factory;
5+
import org.hamcrest.Matcher;
6+
import static org.hamcrest.MatcherAssert.assertThat;
7+
import static org.hamcrest.collection.IsCollectionContaining.collectionContainingAllOf;
8+
import static org.hamcrest.core.IsEqual.equalTo;
9+
import org.hamcrest.generator.FactoryMethod;
10+
import org.hamcrest.generator.FactoryWriter;
11+
import org.hamcrest.generator.SugarConfiguration;
12+
import org.xml.sax.InputSource;
13+
14+
import java.io.StringReader;
15+
import java.util.ArrayList;
16+
import java.util.List;
17+
18+
public class XmlConfiguratorTest extends TestCase {
19+
20+
private MockSugarConfiguration sugarConfiguration;
21+
private StubClassLoader classLoader;
22+
private XmlConfigurator config;
23+
24+
protected void setUp() throws Exception {
25+
super.setUp();
26+
sugarConfiguration = new MockSugarConfiguration();
27+
classLoader = new StubClassLoader();
28+
config = new XmlConfigurator(sugarConfiguration, classLoader);
29+
}
30+
31+
public void testAddsMatcherFactoryMethodsToConfiguration() throws Exception {
32+
config.load(createXml("" +
33+
"<matchers>" +
34+
" <factory class='org.hamcrest.generator.config.XmlConfiguratorTest$SomeMatcher'/>" +
35+
" <factory class='org.hamcrest.generator.config.XmlConfiguratorTest$AnotherMatcher'/>" +
36+
"</matchers>"));
37+
38+
assertThat(sugarConfiguration.factoryMethods(),
39+
collectionContainingAllOf(
40+
equalTo(new FactoryMethod(SomeMatcher.class.getName(), "matcher1")),
41+
equalTo(new FactoryMethod(SomeMatcher.class.getName(), "matcher2")),
42+
equalTo(new FactoryMethod(AnotherMatcher.class.getName(), "matcher3"))
43+
));
44+
}
45+
46+
private InputSource createXml(String xml) {
47+
return new InputSource(new StringReader(xml));
48+
}
49+
50+
// Sample Matchers
51+
52+
public static class SomeMatcher {
53+
@Factory
54+
public static Matcher matcher1() {
55+
return null;
56+
}
57+
58+
@Factory
59+
public static Matcher matcher2() {
60+
return null;
61+
}
62+
}
63+
64+
public static class AnotherMatcher {
65+
@Factory
66+
public static Matcher matcher3() {
67+
return null;
68+
}
69+
}
70+
71+
/**
72+
* Simple 'record and check' style mock. Not using a mocking library to avoid
73+
* cyclical dependency between mocking library and hamcrest.
74+
*/
75+
private static class MockSugarConfiguration implements SugarConfiguration {
76+
77+
private final List<FactoryMethod> seenFactoryMethods = new ArrayList<FactoryMethod>();
78+
private final List<FactoryWriter> seenFactoryWriters = new ArrayList<FactoryWriter>();
79+
80+
public void addWriter(FactoryWriter factoryWriter) {
81+
seenFactoryWriters.add(factoryWriter);
82+
}
83+
84+
public void addFactoryMethod(FactoryMethod method) {
85+
seenFactoryMethods.add(method);
86+
}
87+
88+
public void addFactoryMethods(Iterable<FactoryMethod> methods) {
89+
for (FactoryMethod method : methods) {
90+
addFactoryMethod(method);
91+
}
92+
}
93+
94+
public List<FactoryMethod> factoryMethods() {
95+
return seenFactoryMethods;
96+
}
97+
}
98+
99+
private static class StubClassLoader extends ClassLoader {
100+
public Class<?> loadClass(String name) throws ClassNotFoundException {
101+
return super.loadClass(name);
102+
}
103+
}
104+
105+
}

0 commit comments

Comments
 (0)