package org.xpect.expectation.impl;
import java.util.Collection;
import java.util.List;
import org.eclipse.xtext.util.Pair;
import org.junit.ComparisonFailure;
import org.xpect.XpectArgument;
import org.xpect.XpectImport;
import org.xpect.expectation.CommaSeparatedValuesExpectation;
import org.xpect.expectation.ICommaSeparatedValuesExpectation;
import org.xpect.expectation.impl.ActualCollection.ActualItem;
import org.xpect.expectation.impl.ExpectationCollection.ExpectationItem;
import org.xpect.setup.XpectSetupFactory;
import org.xpect.state.Creates;
import org.xpect.text.Text;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
@XpectSetupFactory
@XpectImport(ExpectationRegionProvider.class)
public class CommaSeparatedValuesExpectationImpl extends AbstractExpectation implements ICommaSeparatedValuesExpectation {
protected static class ValueImpl implements ICommaSeparatedValuesExpectation.Value {
private final ExpectationCollection.ExpectationItem delegate;
public ValueImpl(ExpectationItem delegate) {
super();
this.delegate = delegate;
}
public String getText() {
return delegate.getPure();
}
public boolean isNegated() {
return delegate.isNegated();
}
public boolean isWildcard() {
return delegate.isWildcard();
}
@Override
public String toString() {
ToStringHelper helper = Objects.toStringHelper(ICommaSeparatedValuesExpectation.Value.class);
helper.add("text", getText()).add("negated", isNegated()).add("wildcard", isWildcard());
return helper.toString();
}
}
private final CommaSeparatedValuesExpectation annotation;
private final ExpectationCollection expectationCollection;
public CommaSeparatedValuesExpectationImpl(CommaSeparatedValuesExpectationImpl original, CommaSeparatedValuesExpectation config) {
super(original.getArgument(), original.getTargetSyntax());
this.annotation = config;
this.expectationCollection = createExpectationCollection();
}
public CommaSeparatedValuesExpectationImpl(XpectArgument argument, TargetSyntaxSupport syntax) {
super(argument, syntax);
this.annotation = argument.getAnnotationOrDefault(CommaSeparatedValuesExpectation.class);
this.expectationCollection = createExpectationCollection();
}
public void assertEquals(Iterable<?> actual) {
assertEquals(actual, null);
}
public void assertEquals(Iterable<?> actual, Predicate<String> predicate) {
ActualCollection act = new ActualCollection();
act.setTargetLiteralSupport(getTargetSyntaxLiteral());
act.setCaseSensitive(annotation.caseSensitive());
act.setOrdered(annotation.ordered());
act.setQuoted(annotation.quoted());
act.setSeparator(',');
act.setWhitespaceSensitive(annotation.whitespaceSensitive());
if (actual != null && predicate != null) {
if (expectationCollection.isWildcard())
act.init(expectationCollection.applyPredicate(predicate), annotation.itemFormatter());
else
act.init(actual, annotation.itemFormatter());
} else if (predicate != null)
act.init(expectationCollection.applyPredicate(predicate), annotation.itemFormatter());
else if (actual != null)
act.init(actual, annotation.itemFormatter());
else
throw new NullPointerException();
String nl = new Text(this.getRegion().getDocument()).getNL();
if (!expectationCollection.matches(act)) {
StringBuilder expString = new StringBuilder();
StringBuilder actString = new StringBuilder();
boolean expWrap = false;
boolean expEmpty = false;
boolean actWrap = false;
int lineLength = 0, lineCount = 0;
for (Pair<Collection<ExpectationItem>, ActualItem> pair : expectationCollection.map(act)) {
String expItem = null;
String actItem = null;
if (pair.getFirst() != null && !pair.getFirst().isEmpty()) {
if (pair.getSecond() != null)
expItem = pair.getSecond().getEscaped();
else
expItem = pair.getFirst().iterator().next().getEscaped();
} else {
if (pair.getSecond() != null)
expItem = str(pair.getSecond().getEscaped().length());
}
if (pair.getSecond() != null) {
actItem = pair.getSecond().getEscaped();
lineCount++;
lineLength += actItem.length() + 2;
boolean count = annotation.maxItemsPerLine() > 0 && lineCount > annotation.maxItemsPerLine();
boolean width = annotation.maxLineWidth() > 0 && lineLength > annotation.maxLineWidth();
if (count || width)
expWrap = actWrap = true;
}
if (expItem != null && expString.length() > 0) {
if (expWrap) {
expString.append(expEmpty ? nl : "," + nl);
expWrap = false;
} else
expString.append(expEmpty ? " " : ", ");
}
if (actItem != null && actString.length() > 0) {
if (actWrap) {
actString.append("," + nl);
actWrap = false;
lineCount = 0;
lineLength = 0;
} else
actString.append(", ");
}
if (expItem != null) {
expString.append(expItem);
expEmpty = expItem.trim().length() == 0;
}
if (actItem != null)
actString.append(actItem);
}
String expDoc = replaceInDocument(expString.toString());
String actDoc = replaceInDocument(actString.toString());
throw new ComparisonFailure("", expDoc, actDoc);
}
}
public void assertEquals(Predicate<String> predicate) {
assertEquals(null, predicate);
}
@Creates
public ICommaSeparatedValuesExpectation create() {
return this;
}
protected ExpectationCollection createExpectationCollection() {
ExpectationCollection exp = new ExpectationCollection();
exp.setCaseSensitive(annotation.caseSensitive());
exp.setOrdered(annotation.ordered());
exp.setQuoted(annotation.quoted());
exp.setSeparator(',');
exp.setWhitespaceSensitive(annotation.whitespaceSensitive());
exp.init(getExpectation());
return exp;
}
public CommaSeparatedValuesExpectation getAnnotation() {
return annotation;
}
public List<Value> getExpectedValues() {
List<Value> result = Lists.newArrayList();
for (ExpectationItem item : expectationCollection)
result.add(new ValueImpl(item));
return ImmutableList.copyOf(result);
}
protected String str(int length) {
StringBuilder b = new StringBuilder();
for (int i = 0; i < length; i++)
b.append(" ");
return b.toString();
}
}