// returns null on failure
AttributesUpdate generateRandomAttributesUpdate(final boolean valid,
final Attributes oldAttributes,
final AttributesUpdateChecker checker) {
AttributesUpdate accu = new AttributesUpdateImpl();
if (valid && !checker.check(accu).isValid()
|| !valid && checker.check(accu).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(accu).isValid()) {
assert accu.changeSize() == 0;
accu = pickRandomNonNullMappedElement(r,
p.getAttributeNames(), new Mapper<String, AttributesUpdate>() {
@Override
public AttributesUpdate map(final String name) {
return pickRandomNonNullMappedElement(r, p.getAttributeValues(),
new Mapper<String, AttributesUpdate> () {
@Override
public AttributesUpdate map(String value) {
AttributesUpdate b = new AttributesUpdateImpl(name,
oldAttributes.get(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 (accu == null) {
return null;
}
}
assert !checker.check(accu).isValid();
// Flip a coin and terminate if the number of attributes was really
// supposed to be zero.
if (r.nextBoolean()) {
return accu;
}
}
while (r.nextBoolean()) {
final AttributesUpdate finalAccu = accu;
AttributesUpdate newAccu = pickRandomNonNullMappedElement(r,
p.getAttributeNames(), new Mapper<String, AttributesUpdate>() {
@Override
public AttributesUpdate map(final String name) {
for (int i = 0; i < finalAccu.changeSize(); i++) {
if (finalAccu.getChangeKey(i).equals(name)) {
return null;
}
}
return pickRandomNonNullMappedElement(r, p.getAttributeValues(),
new Mapper<String, AttributesUpdate>() {
@Override
public AttributesUpdate map(String value) {
AttributesUpdate b = finalAccu.composeWith(new AttributesUpdateImpl(name,
oldAttributes.get(name), value));
assert b != finalAccu; // assert non-destructiveness
ValidationResult v = checker.check(b);
if (valid && !v.isValid() || !valid && v.isIllFormed()) {
return null;