diff --git a/libpit/lib/joda-time-2.0.jar b/libpit/lib/joda-time-2.0.jar new file mode 100644 index 0000000..169a7a4 Binary files /dev/null and b/libpit/lib/joda-time-2.0.jar differ diff --git a/libpit/lib/logback-classic-0.9.26.jar b/libpit/lib/logback-classic-0.9.26.jar new file mode 100644 index 0000000..b900b64 Binary files /dev/null and b/libpit/lib/logback-classic-0.9.26.jar differ diff --git a/libpit/lib/logback-core-0.9.26.jar b/libpit/lib/logback-core-0.9.26.jar new file mode 100644 index 0000000..d50f3cd Binary files /dev/null and b/libpit/lib/logback-core-0.9.26.jar differ diff --git a/libpit/lib/slf4j-api-1.6.1.jar b/libpit/lib/slf4j-api-1.6.1.jar new file mode 100644 index 0000000..42e0ad0 Binary files /dev/null and b/libpit/lib/slf4j-api-1.6.1.jar differ diff --git a/libpit/project.properties b/libpit/project.properties index eb29644..b326daa 100755 --- a/libpit/project.properties +++ b/libpit/project.properties @@ -1,10 +1,10 @@ -#Wed, 26 Oct 2011 14:20:47 -0500 +#Thu, 03 Nov 2011 13:47:05 -0500 #Sat Apr 24 17:08:00 CDT 2010 build.dir=build src.dir=src lib.shared.dir=../shared-libs test.dir=test -build.number=0 +build.number=11 expected.application.version=3.0.0 lib.dir=lib release.dir=release diff --git a/libpit/src/com/jdbernard/pit/Issue.groovy b/libpit/src/com/jdbernard/pit/Issue.groovy index 2d4fbf8..3a28421 100755 --- a/libpit/src/com/jdbernard/pit/Issue.groovy +++ b/libpit/src/com/jdbernard/pit/Issue.groovy @@ -13,13 +13,20 @@ public abstract class Issue { protected Map extendedPropeties = [:] - Issue(String id, Category c = Category.TASK, Status s = Status.NEW, - int p = 9) { - this.id = id - this.category = c - this.status = s - this.priority = p - } + Issue(Map props) { + this.id = props.id + this.category = props.category ?: Category.TASK + this.status = props.status ?: Status.NEW + this.priority = props.priority ?: 9 + this.title = props.title ?: '' + this.text = props.text ?: '' + + def nativeProps = + ["id", "category", "status", "priority", "title", "text"] + + props.each { key, val -> + if (nativeProps.contains(key)) { return } + this.extendedProperties[key] = val }} public String getId() { return id; } @@ -49,7 +56,7 @@ public abstract class Issue { public String getTitle() { return title } - public String setTitle(String t) throws IOException { title = t } + public void setTitle(String t) throws IOException { title = t } public String getText() { return text } diff --git a/libpit/src/com/jdbernard/pit/file/FileIssue.groovy b/libpit/src/com/jdbernard/pit/file/FileIssue.groovy index 6598cfe..19637e5 100755 --- a/libpit/src/com/jdbernard/pit/file/FileIssue.groovy +++ b/libpit/src/com/jdbernard/pit/file/FileIssue.groovy @@ -1,31 +1,75 @@ package com.jdbernard.pit.file import com.jdbernard.pit.* + import java.lang.IllegalArgumentException as IAE +import org.joda.time.DateMidnight +import org.joda.time.DateTime + +import org.slf4j.Logger +import org.slf4j.LoggerFactory + public class FileIssue extends Issue { protected File source + private Logger log = LoggerFactory.getLogger(getClass()) + public static final String fileExp = /(\d+)([bft])([ajnsv])(\d).*/ public FileIssue(File file) { - super('REPLACE_ME') + super(id: -1, title: 'REPLACE_ME') + + if (log.isDebugEnabled()) { + log.debug("Loading a FileIssue from '{}'", file.canonicalPath) } def matcher = file.name =~ fileExp if (!matcher) throw new IllegalArgumentException("${file} " + "is not a valid Issue file.") + // Read issue attributes from the filename. super.@id = matcher[0][1] super.@category = Category.toCategory(matcher[0][2]) super.@status = Status.toStatus(matcher[0][3]) super.@priority = matcher[0][4].toInteger() + log.debug("id: {}\tcategory: {}\tstatus: {}\tpriority: {}", + [super.@id, super.@category, super.@status, super.@priority]) + this.source = file - super.@text = file.text - super.@title = super.@text.readLines()[0] + String text = "" + boolean parsingText = true + + // Now parse the actual file contents. + file.text.eachLine { line, lineNumber -> + + log.trace("lineNumber: {}, line: {}", lineNumber, line) + + if (lineNumber == 0) { + super.@title = line + log.debug("Found title: {}", super.@title) } + + else if (lineNumber > 2) { + // We see the horizontal rule + if (line ==~ /\s*^\-{4}\-*\s*$/) { parsingText = false } + + if (parsingText) { text += "$line\n" } + + else { + def match = (line =~ /^([^:]+):(.+)$/) + if (match) { + def key = match[0][1].trim() + def value = parseValue(match[0][2].trim()) + super.@extendedProperties[key] = value + } + } + } + } + + super.@text = text } public void setCategory(Category c) throws IOException { @@ -109,22 +153,22 @@ public class FileIssue extends Issue { public static String formatIssue(Issue issue) { def result = new StringBuilder() - result.append(title) + result.append(issue.@title) result.append("\n") - result.append("=".multiply(title.length())) + result.append("=".multiply(issue.@title.length())) result.append("\n") - result.append(text) + result.append(issue.@text) result.append("\n----\n") // If there are any extended properties, let's write those. - if (super.@extendedProperties.size() > 0) { + if (issue.@extendedProperties.size() > 0) { def extOutput = [:] def maxKeyLen = 0 def maxValLen = 0 // Find the longest key and value, convert all to strings. - super.@extendedProperties.each { key, val -> - def ks = key.toString(), vs = val.toString() + issue.@extendedProperties.each { key, val -> + def ks = key.toString(), vs = formatProperty(val) extOutput[ks] = vs if (ks.length() > maxKeyLen) { maxKeyLen = ks.length() } if (vs.length() > maxKeyLen) { maxValLen = vs.length() } } @@ -146,7 +190,7 @@ public class FileIssue extends Issue { result.append("\n") }} protected void writeFile() { - try { source.write(formatIssue(this) } + try { source.write(formatIssue(this)) } catch (IOException ioe) { throw new IOException("I could not save the new text for this " + "issue. I can not write to the file for this issue. I do not" @@ -154,4 +198,16 @@ public class FileIssue extends Issue { } } + public def parseValue(String value) { + switch (value) { + case ~/\d{4}-\d{2}-\d{2}/: return DateMidnight.parse(value) + default: return value + } + } + + public String formatProperty(DateTime prop) { + return prop.format("YYYY-MM-dd'T'HH:mm:ss") } + + public String formatProperty(DateMidnight prop) { + return prop.format("YYYY-MM-dd") } } diff --git a/libpit/test/com/jdbernard/pit/MockIssue.groovy b/libpit/test/com/jdbernard/pit/MockIssue.groovy index 1f37c1a..b03abfc 100755 --- a/libpit/test/com/jdbernard/pit/MockIssue.groovy +++ b/libpit/test/com/jdbernard/pit/MockIssue.groovy @@ -2,7 +2,7 @@ package com.jdbernard.pit public class MockIssue extends Issue { public MockIssue(String id, Category c, Status s, int p) { - super (id, c, s, p) + super ([id: id, category: c, status: s, priority: p]) } public boolean delete() { return true } } diff --git a/libpit/test/com/jdbernard/pit/file/FileIssueTest.groovy b/libpit/test/com/jdbernard/pit/file/FileIssueTest.groovy index 8fa57a4..122fee3 100755 --- a/libpit/test/com/jdbernard/pit/file/FileIssueTest.groovy +++ b/libpit/test/com/jdbernard/pit/file/FileIssueTest.groovy @@ -171,9 +171,7 @@ class FileIssueTest { assertEquals issue.status , Status.NEW assertEquals issue.priority , 1 assertEquals issue.title , "Add the killer feature to the killer app." - assertEquals issue.text , "Add the killer feature to the killer app.\n" + - "=========================================\n\n" + - "Make our killer app shine!." + assertEquals issue.text , "Make our killer app shine!." assertEquals issue.source , issueFile }