interface AttributesChecker {
ValidationResult check(Attributes attrs);
}
Attributes generateRandomAttributes(final boolean valid, final AttributesChecker checker) {
Attributes attrAccu = Attributes.EMPTY_MAP;
if (valid && !checker.check(Attributes.EMPTY_MAP).isValid()
|| !valid && checker.check(Attributes.EMPTY_MAP).isIllFormed()) {
return null;
}
if (!valid) {
// If we want an invalid component, and it's not already invalid without
// any attributes, make it invalid by adding an invalid attribute first.
if (checker.check(attrAccu).isValid()) {
assert attrAccu.isEmpty();
attrAccu = pickRandomNonNullMappedElement(r,
p.getAttributeNames(), new Mapper<String, Attributes>() {
@Override
public Attributes map(final String name) {
return pickRandomNonNullMappedElement(r, p.getAttributeValues(),
new Mapper<String, Attributes> () {
@Override
public Attributes map(String value) {
Attributes b = new AttributesImpl(name, value);
switch (checker.check(b)) {
case ILL_FORMED:
return null;
case INVALID_DOCUMENT:
case INVALID_SCHEMA:
return b;
case VALID:
return null;
default:
throw new RuntimeException("unexpected validation result");
}
}
});
}
});
if (attrAccu == null) {
return null;
}
}
assert !checker.check(attrAccu).isValid();
// Flip a coin and terminate if the number of attributes was really
// supposed to be zero.
if (r.nextBoolean()) {
return attrAccu;
}
}
while (r.nextBoolean()) {
final Attributes finalAttrAccu = attrAccu;
Pair<String, String> newAttr = pickRandomNonNullMappedElement(r,
p.getAttributeNames(), new Mapper<String, Pair<String, String>>() {
@Override
public Pair<String, String> map(final String name) {
if (finalAttrAccu.containsKey(name)) {
return null;
}
return pickRandomNonNullMappedElement(r, p.getAttributeValues(),
new Mapper<String, Pair<String, String>>() {
@Override
public Pair<String, String> map(String value) {
Attributes b = finalAttrAccu.updateWith(
new AttributesUpdateImpl(name, null, value));
assert b != finalAttrAccu; // assert non-destructiveness
ValidationResult v = checker.check(b);
if (valid && !v.isValid() || !valid && v.isIllFormed()) {
return null;