Refactored Issues/Projects in to abstract classes with further implementations.

ALl tests passing. Ran into some frustrationg aspects of Groovy
This commit is contained in:
Jonathan Bernard
2010-02-20 22:31:33 -06:00
parent fe6ce85a73
commit 7ff8806544
11 changed files with 272 additions and 166 deletions

View File

@ -0,0 +1,68 @@
package com.jdbernard.pit
import java.lang.IllegalArgumentException as IAE
public class FileIssue extends Issue {
File source
FileIssue(File file) {
/* I do not like this construction, but groovy automatically
* calls obj.setProperty(...) when you type obj.property = ...
* There is an exception for fields accessed withing the class
* that defines them, it does not catt eh setter/getter, but
* this exception does not extend to subclasses accessing member
* variables of their parent class. So instead of using Issue's
* default constructor and setting the id, category, and priority
* fields here, we have to let Issue's constructor initialize
* those values.*/
super((file.name =~ /(\d+)([bcft])(\d).*/)[0][1],
Category.toCategory((file.name =~ /(\d+)([bcft])(\d).*/)[0][2]),
(file.name =~ /(\d+)([bcft])(\d).*/)[0][3].toInteger())
//def matcher = file.name =~ /(\d{4})([bftc])(\d).*/
/*if (!matcher) return null
id = matcher[0][1]
category = Category.toCategory(matcher[0][2])
priority = matcher[0][3].toInteger()*/
this.source = file
file.withReader { title = it.readLine() }
text = file.text
}
void setCategory(Category c) {
super.setCategory(c)
source.renameTo(new File(source.canonicalFile.parentFile, getFilename()))
}
void setPriority(int p) {
super.setPriority(p)
source.renameTo(new File(source.canonicalFile.parentFile, getFilename()))
}
String getFilename() { return makeFilename(id, category, priority) }
static boolean isValidFilename(String name) {
return name ==~ /(\d+)([bcft])(\d).*/
}
static String makeFilename(String id, Category category, int priority) {
// bounds check priority
priority = Math.min(9, Math.max(0, priority))
//check for valid values of cateogry and id
if (category == null)
throw new IAE("Category must be non-null.")
if (!(id ==~ /\d+/))
throw new IAE( "'${id}' is not a legal value for id.")
return id + category.symbol + priority + ".rst";
}
}

View File

@ -0,0 +1,68 @@
package com.jdbernard.pit
class FileProject extends Project {
File source
FileProject(File dir) {
super(dir.name)
if (!dir.isDirectory())
throw new IllegalArgumentException(
"${dir.name} is not a directory.")
this.source = dir
dir.eachFile { child ->
// add sub projects
if (child.isDirectory()) {
if ( child.name ==~ /\d{4}/) return // just an issue folder
// otherwise build and add to list
projects[(child.name)] = new FileProject(child)
} else if (child.isFile()) {
def issue
// if exception, then not an issue
try { issue = new FileIssue(child) } catch (all) { return }
issues[(issue.id)] = issue
}
}
}
public void rename(String newName) {
this.name = newName
}
public void setName(String name) {
super.setName(name)
source.renameTo(new File(source.canonicalFile.parentFile, name))
}
public FileIssue createNewIssue(Map options) {
if (!options) options = [:]
if (!options.category) options.category = Category.TASK
if (!options.priority) options.priority = 5
if (!options.text) options.text = "Default issue title.\n" +
"====================\n"
String id
if (issues.size() == 0) id = '0000'
else {
id = (issues.values().max { it.id.toInteger() }).id
id = (id.toInteger() + 1).toString().padLeft(id.length(), '0')
}
def issueFile = new File(source, FileIssue.makeFilename(id, options.category, options.priority))
assert !issueFile.exists()
issueFile.createNewFile()
issueFile.write(options.text)
return new FileIssue(issueFile)
}
@Override
String toString() { return name }
}

View File

@ -4,62 +4,26 @@ import java.lang.IllegalArgumentException as IAE
public class Issue {
final String id
String id
Category category
int priority
String title
String text
File source
Issue(File file) {
def matcher = file.name =~ /(\d{4})([bftc])(\d).*/
if (!matcher) return null
this.source = file
id = matcher[0][1]
category = Category.toCategory(matcher[0][2])
priority = matcher[0][3].toInteger()
file.withReader { title = it.readLine() }
text = file.text
Issue(String id, Category c = Category.TASK, int p = 9) {
this.id = id
this.category = c
this.priority = p
}
/**
*/
void setCategory(Category c) {
if (category == null)
if (c == null)
throw new IAE("Category cannot be null.")
this.category = c
source.renameTo(new File(source.canonicalFile.parentFile, getFilename()))
}
void setPriority(int p) {
// bounds check priority
priority = Math.min(9, Math.max(0, priority))
source.renameTo(new File(source.canonicalFile.parentFile, getFilename()))
}
String getFilename() { return makeFilename(id, category, priority) }
static String makeFilename(String id, Category category, int priority) {
// bounds check priority
priority = Math.min(9, Math.max(0, priority))
//check for valid values of cateogry and id
if (category == null)
throw new IAE("Category must be non-null.")
if (!(/\d+/ ==~ id))
throw new IAE( "'${id}' is not a legal value for id.")
return id + category.symbol + priority + ".rst";
}
void setPriority(int p) { priority = Math.min(9, Math.max(0, p)) }
@Override
String toString() { return "${id}(${priority}): ${category} ${title}" }

View File

@ -1,46 +1,13 @@
package com.jdbernard.pit
class Project {
public abstract class Project {
String name
Map<String, Issue> issues = [:]
Map<String, Project> projects = [:]
File source
Project(File dir) {
if (!dir.isDirectory())
throw new IllegalArgumentException(
"${dir.name} is not a directory.")
Project(String name) { this.name = name }
this.source = dir
this.name = dir.name
dir.eachFile { child ->
// add sub projects
if (child.isDirectory()) {
if ( child.name ==~ /\d{4}/) return // just an issue folder
// otherwise build and add to list
projects[(child.name)] = new Project(child)
} else if (child.isFile()) {
def issue
// if exception, then not an issue
try { issue = new Issue(child) } catch (all) { return }
issues[(issue.id)] = issue
}
}
}
public void rename(String newName) {
this.name = newName
source.renameTo(new File(source.canonicalFile.parentFile, newName))
}
public void setName(String name) { rename(name) }
public void eachIssue(Filter filter = null, Closure c) {
def sorter = filter?.issueSorter ?: Filter.defaultIssueSorter
for (i in issues.values().sort(sorter))
@ -55,46 +22,8 @@ class Project {
c.call(p)
}
/*public void each(Filter filter = null, Closure c) {
def is = filter?.issueSorter ?: Filter.defaultIssueSorter
def ps = filter?.projectSorter ?: Filter.defaultProjectSorter
for (issue in issues.values().sort(is)) {
if (filter && !filter.accept(issue))
return
c.call(issue)
}
for (project in projects.values().sort(ps)) {
if (filter && !filter.accept(project))
return
c.call(project)
}
}*/
public Issue createNewIssue(Map options) {
if (!options.category) options.category = Category.TASK
if (!options.priority) options.priority = 5
if (!options.text) options.text = "Default issue title.\n" +
"====================\n"
String id
if (issues.size() == 0) id = '0000'
else {
id = (issues.values().max { it.id.toInteger() }).id
id = (id.toInteger() + 1).toString().padLeft(id.length(), '0')
}
def issueFile = new File(source, Issue.makeFilename(id, options.category, options.priority))
assert !issueFile.exists()
issueFile.createNewFile()
issueFile.write(options.text)
return new Issue(issueFile)
}
@Override
String toString() { return name }
public abstract Issue createNewIssue(Map options)
}