Continued implementation of extended attributes.
* Changed the `Issue` constructor to use an attribute map instead of an increasingly long parameter list. Of course we lose some control over required parameters. * Added the Joda Time and SLF4J logging libraries. * Implemented the `FileIssue` constructor for the new `Issue` refactor.
This commit is contained in:
parent
5ff4665a07
commit
f86316c68f
BIN
libpit/lib/joda-time-2.0.jar
Normal file
BIN
libpit/lib/joda-time-2.0.jar
Normal file
Binary file not shown.
BIN
libpit/lib/logback-classic-0.9.26.jar
Normal file
BIN
libpit/lib/logback-classic-0.9.26.jar
Normal file
Binary file not shown.
BIN
libpit/lib/logback-core-0.9.26.jar
Normal file
BIN
libpit/lib/logback-core-0.9.26.jar
Normal file
Binary file not shown.
BIN
libpit/lib/slf4j-api-1.6.1.jar
Normal file
BIN
libpit/lib/slf4j-api-1.6.1.jar
Normal file
Binary file not shown.
@ -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
|
||||
|
@ -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 }
|
||||
|
||||
|
@ -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") }
|
||||
}
|
||||
|
@ -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 }
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user