package tzatziki.pdf.emitter;
import com.google.common.base.Optional;
import com.google.common.collect.FluentIterable;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Section;
import gutenberg.itext.Emitter;
import gutenberg.itext.ITextContext;
import gutenberg.itext.Sections;
import gutenberg.itext.Styles;
import gutenberg.itext.model.Markdown;
import gutenberg.util.KeyValues;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import tzatziki.analysis.exec.model.BackgroundExec;
import tzatziki.analysis.exec.model.FeatureExec;
import tzatziki.analysis.exec.model.ScenarioExec;
import tzatziki.analysis.exec.model.ScenarioOutlineExec;
import tzatziki.analysis.exec.model.StepContainer;
import tzatziki.pdf.Comments;
import tzatziki.pdf.Settings;
import tzatziki.pdf.model.ScenarioOutlineWithResolved;
import tzatziki.pdf.model.Tags;
import java.util.Iterator;
/**
* @author <a href="http://twitter.com/aloyer">@aloyer</a>
*/
public class FeatureEmitter implements Emitter<FeatureExec> {
public static final String DISPLAY_URI = "feature-display-uri";
public static final String DISPLAY_TAGS = "feature-display-tags";
public static final String FEATURE_HEADER_LEVEL_OFFSET = "feature-header-level-offset";
private Logger log = LoggerFactory.getLogger(FeatureEmitter.class);
//
@Override
public void emit(FeatureExec feature, ITextContext emitterContext) {
KeyValues kvs = emitterContext.keyValues();
Sections sections = emitterContext.sections();
Integer rawOffset = kvs.getInteger(FEATURE_HEADER_LEVEL_OFFSET).orNull();
int headerLevel = 1 + ((rawOffset == null) ? 0 : rawOffset);
Section featureChap = sections.newSection(feature.name(), headerLevel);
try {
// Uri
if (kvs.getBoolean(DISPLAY_URI, true)) {
emitUri(feature, emitterContext);
}
// Tags
if (kvs.getBoolean(DISPLAY_TAGS, true)) {
emitTags(feature, emitterContext);
}
// Description
emitDescription(feature, emitterContext);
// Background
BackgroundExec background = feature.background();
if(background!=null) {
emitterContext.emit(BackgroundExec.class, background);
}
// Scenario
Iterator<StepContainer> containers = feature.stepContainers().iterator();
while (containers.hasNext()) {
StepContainer container = containers.next();
if (container instanceof ScenarioOutlineExec) {
ScenarioOutlineExec outline = (ScenarioOutlineExec) container;
ScenarioOutlineWithResolved outlineWithResolved = resolveOutlineWithScenario(containers, outline);
emitterContext.emit(ScenarioOutlineWithResolved.class, outlineWithResolved);
} else if (container instanceof ScenarioExec) {
emitterContext.emit(ScenarioExec.class, (ScenarioExec) container);
}
}
} catch (Exception e) {
log.warn("Error during feature emit", e);
throw new RuntimeException(e);
} finally {
sections.leaveSection(headerLevel);
}
if (headerLevel == 1)
emitterContext.append(featureChap);
}
private ScenarioOutlineWithResolved resolveOutlineWithScenario(Iterator<StepContainer> containers, ScenarioOutlineExec outline) {
ScenarioOutlineWithResolved outlineWithResolved = new ScenarioOutlineWithResolved(outline);
for (int i = 0; i < outline.exampleRowCount(); i++) {
outlineWithResolved.declareScenario((ScenarioExec) containers.next());
}
return outlineWithResolved;
}
private void emitUri(FeatureExec feature, ITextContext emitterContext) {
Styles styles = emitterContext.keyValues().<Styles>getNullable(Styles.class).get();
Paragraph uri = new Paragraph("Uri: " + feature.uri(), styles.getFontOrDefault(Settings.META_FONT));
emitterContext.append(uri);
}
private void emitTags(FeatureExec feature, ITextContext emitterContext) {
emitterContext.emit(Tags.class, new Tags(feature.tags()));
}
protected void emitDescription(FeatureExec feature, ITextContext emitterContext) {
// Description
StringBuilder b = new StringBuilder();
String description = feature.description();
if (StringUtils.isNotBlank(description)) {
b.append(description);
}
BackgroundExec background = feature.background();
if (background != null) {
appendComments(b, background.comments());
} else {
Optional<ScenarioExec> first = feature.scenario().first();
if (first.isPresent()) {
ScenarioExec scenarioExec = first.get();
appendComments(b, scenarioExec.comments());
}
}
if (b.length() > 0) {
log.debug("Description content >>{}<<", b);
emitterContext.emit(Markdown.class, new Markdown(b.toString()));
}
}
private static void appendComments(StringBuilder b, FluentIterable<String> comments) {
for (String comment : comments) {
String uncommented = Comments.discardCommentChar(comment);
if (!Comments.startsWithComment(uncommented)) { // double # case
b.append(uncommented).append(Comments.NL);
}
}
}
}