package io.trygvis.esper.testing.jenkins.xml; import java.net.URI; import java.util.ArrayList; import java.util.List; import org.jdom2.Document; import org.jdom2.Element; import org.joda.time.DateTime; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; import org.joda.time.format.ISODateTimeFormat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import fj.F; import fj.data.Option; import io.trygvis.esper.testing.Util; import static fj.data.List.iterableList; import static fj.data.Option.*; import static io.trygvis.esper.testing.Util.childText; import static io.trygvis.esper.testing.Util.parseInt; import static io.trygvis.esper.testing.jenkins.xml.JenkinsBuildXml.ChangeSetItemXml.parseChangeSetItem; import static io.trygvis.esper.testing.jenkins.xml.JenkinsBuildXml.RevisionXml.parseRevision; public class JenkinsBuildXml { private static final Logger logger = LoggerFactory.getLogger(JenkinsBuildXml.class); public final URI url; public final int number; public final Option result; public final int duration; public final long timestamp; public final Option changeSet; JenkinsBuildXml(URI url, int number, Option result, int duration, long timestamp, Option changeSet) { this.url = url; this.number = number; this.result = result; this.duration = duration; this.timestamp = timestamp; this.changeSet = changeSet; } public static F> parse = new F>() { public Option f(Document document) { return parse(document); } }; public static Option parse(Document doc) { Element root = doc.getRootElement(); Option url = childText(root, "url").bind(Util.parseUri); Option number = childText(root, "number").bind(Util.parseInt); Option result = childText(root, "result"); Option duration = childText(root, "duration").bind(Util.parseInt); Option timestamp = childText(root, "timestamp").bind(Util.parseLong); if (url.isNone()) { logger.warn("Missing required field: "); return none(); } if (number.isNone()) { logger.warn("Missing required field: "); return none(); } if (duration.isNone()) { logger.warn("Missing required field: "); return none(); } if (timestamp.isNone()) { logger.warn("Missing required field: "); return none(); } Option changeSet = none(); Element e = root.getChild("changeSet"); if (e != null) { changeSet = ChangeSetXml.parse(e); } return some(new JenkinsBuildXml(url.some(), number.some(), result, duration.some(), timestamp.some(), changeSet)); } public static class ChangeSetXml { public final List items; public final Option revision; public ChangeSetXml(List items, Option revision) { this.items = items; this.revision = revision; } public static Option parse(Element changeSet) { List items = new ArrayList<>(Option.somes(iterableList(changeSet.getChildren("item")).map(parseChangeSetItem)).toCollection()); Option revision = Option.fromNull(changeSet.getChild("revision")).bind(parseRevision); return some(new ChangeSetXml(items, revision)); } } public static class ChangeSetItemXml { public final String commitId; public final DateTime date; public final String msg; public final Option author; public ChangeSetItemXml(String commitId, DateTime date, String msg, Option author) { this.commitId = commitId; this.date = date; this.msg = msg; this.author = author; } private static final F> parseDate = new F>() { // This variant is used by git DateTimeFormatter parser = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss Z"); // and this by subversion DateTimeFormatter parser2 = ISODateTimeFormat.dateTime(); public Option f(String s) { try { return some(parser.parseDateTime(s)); } catch (IllegalArgumentException e) { try { return some(parser2.parseDateTime(s)); } catch (IllegalArgumentException e2) { return none(); } } } }; public static final F> parseChangeSetItem = new F>() { public Option f(Element item) { Option commitId = childText(item, "commitId"); Option date = childText(item, "date").bind(parseDate); Option msg = childText(item, "msg"); if (commitId.isNone() || date.isNone() || msg.isNone()) { return none(); } Option author = fromNull(item.getChild("author")).bind(AuthorXml.parseAuthorXml); return some(new ChangeSetItemXml(commitId.some(), date.some(), msg.some(), author)); } }; } public static class AuthorXml { public final String absoluteUrl; public final String fullName; public AuthorXml(String absoluteUrl, String fullName) { this.absoluteUrl = absoluteUrl; this.fullName = fullName; } public static final F> parseAuthorXml = new F>() { public Option f(Element element) { Option absoluteUrl = childText(element, "absoluteUrl"); Option fullName = childText(element, "fullName"); if(absoluteUrl.isNone() || fullName.isNone()) { return none(); } return some(new AuthorXml(absoluteUrl.some(), fullName.some())); } }; } public static class RevisionXml { public final String module; public final int revision; public RevisionXml(String module, int revision) { this.module = module; this.revision = revision; } public static final F> parseRevision = new F>() { public Option f(Element e) { Option module = childText(e, "module"); Option revision = childText(e, "revision").bind(parseInt); if (module.isNone() || revision.isNone()) { return none(); } return some(new RevisionXml(module.some(), revision.some())); } }; } }