Filter and FileProject support for extended properties.
* Added support for extended properties to `Filter`. Unlike the basic properties, which allow the caller to specify a list of acceptable values, the extended properties only supports a map of properties, all of which must be available on the issue and match the given value. * Made `Issue` a concrete class. There was no reason it could not be a concrete object. The main difference is that the extending classes all add some sort of persistence to the issue, but having an in-memory `Issue` in its most basic form can be useful and should be allowed. * Changed the default priority for new issues from 9 to 5. * Bug fix on `FileIssue.formatIssue()`. If was not properly returning its result leading to failure if no extended properties were given. * Reworked `FileIssue.formatIssue()` to only print the horizontal rule seperating the issue text from the extended properties if there are extended properties to print as well. * Changed the `FileProject.createNewIssue()` to handle extended properties and handle the basic properties in a manner more consistent with `Issue`. It is now creating an `Issue` object and using the `FileIssue.formatIssue()` function to write that to a new issue file, then loading that file back in as a `FileIssue`. This cuts down on code duplication and makes it so that the options map that `FileProject.createNewIssue()` expects is the same as the options to the `Issue` constructor.
This commit is contained in:
parent
fd94f0e41a
commit
846d1edc74
@ -1,11 +1,11 @@
|
||||
#Wed, 07 Dec 2011 17:53:14 -0600
|
||||
#Thu, 08 Dec 2011 14:35:45 -0600
|
||||
#Sat Apr 24 17:08:00 CDT 2010
|
||||
build.dir=build
|
||||
src.dir=src
|
||||
lib.shared.dir=../shared-libs
|
||||
test.dir=test
|
||||
build.number=8
|
||||
version=3.1.0
|
||||
build.number=10
|
||||
version=3.2.0
|
||||
name=libpit
|
||||
lib.dir=lib
|
||||
lib.local=true
|
||||
|
@ -6,6 +6,7 @@ class Filter {
|
||||
List<Status> status = null
|
||||
List<String> projects = null
|
||||
List<String> ids = null
|
||||
Map<String, Object> extendedProperties = null
|
||||
int priority = 9
|
||||
boolean acceptProjects = true
|
||||
def issueSorter = defaultIssueSorter
|
||||
@ -15,10 +16,18 @@ class Filter {
|
||||
public static Closure defaultProjectSorter = { it.name }
|
||||
|
||||
public boolean accept(Issue i) {
|
||||
return (i.priority <= priority &&
|
||||
(!categories || categories.contains(i.category)) &&
|
||||
(!status || status.contains(i.status)) &&
|
||||
(!ids || ids.contains(i.id)))
|
||||
return (
|
||||
// Needs to meet the priority threshold.
|
||||
i.priority <= priority &&
|
||||
// Needs to be in one of the filtered categories (if given)
|
||||
(!categories || categories.contains(i.category)) &&
|
||||
// Needs to have one of the filtered statuses (if given)
|
||||
(!status || status.contains(i.status)) &&
|
||||
// Needs to be one of the filtered ids (if given)
|
||||
(!ids || ids.contains(i.id)) &&
|
||||
// Needs to have all of the extended properties (if given)
|
||||
(!extendedProperties ||
|
||||
extendedProperties.every { name, value -> i[name] == value }))
|
||||
}
|
||||
|
||||
public boolean accept(Project p) {
|
||||
|
@ -2,7 +2,7 @@ package com.jdbernard.pit
|
||||
|
||||
import java.lang.IllegalArgumentException as IAE
|
||||
|
||||
public abstract class Issue {
|
||||
public class Issue {
|
||||
|
||||
protected String id
|
||||
protected Category category
|
||||
@ -17,16 +17,15 @@ public abstract class Issue {
|
||||
this.id = props.id
|
||||
this.category = props.category ?: Category.TASK
|
||||
this.status = props.status ?: Status.NEW
|
||||
this.priority = props.priority ?: 9
|
||||
this.priority = props.priority ?: 5
|
||||
this.title = props.title ?: ''
|
||||
this.text = props.text ?: ''
|
||||
|
||||
// Put all the non-native properties into our extendedProperties map.
|
||||
def nativeProps =
|
||||
["id", "category", "status", "priority", "title", "text"]
|
||||
|
||||
props.each { key, val ->
|
||||
if (nativeProps.contains(key)) { return }
|
||||
this.extendedProperties[key] = val }}
|
||||
extendedProperties.putAll(props.findAll {
|
||||
!nativeProps.contains(it.key) })}
|
||||
|
||||
public String getId() { return id; }
|
||||
|
||||
|
@ -138,10 +138,10 @@ public class FileIssue extends Issue {
|
||||
result.append("=".multiply(issue.title.length()))
|
||||
result.append("\n\n")
|
||||
result.append(issue.text)
|
||||
result.append("\n----\n\n")
|
||||
|
||||
// If there are any extended properties, let's write those.
|
||||
if (issue.extendedProperties.size() > 0) {
|
||||
result.append("\n----\n\n")
|
||||
def extOutput = [:]
|
||||
def maxKeyLen = 0
|
||||
def maxValLen = 0
|
||||
@ -169,7 +169,9 @@ public class FileIssue extends Issue {
|
||||
result.append("=".multiply(maxKeyLen + 1))
|
||||
result.append(" ")
|
||||
result.append("=".multiply(maxValLen))
|
||||
result.append("\n") }}
|
||||
result.append("\n") }
|
||||
|
||||
return result.toString()}
|
||||
|
||||
protected void writeFile() {
|
||||
try { source.write(formatIssue(this)) }
|
||||
|
@ -23,56 +23,65 @@ class FileProject extends Project {
|
||||
child.isHidden()) return // just an issue folder
|
||||
|
||||
// otherwise build and add to list
|
||||
projects[(child.name)] = new FileProject(child)
|
||||
} else if (child.isFile() &&
|
||||
projects[(child.name)] = new FileProject(child) }
|
||||
else if (child.isFile() &&
|
||||
FileIssue.isValidFilename(child.name)) {
|
||||
def issue
|
||||
|
||||
// if exception, then not an issue
|
||||
try { issue = new FileIssue(child) } catch (all) { return }
|
||||
|
||||
issues[(issue.id)] = issue
|
||||
}
|
||||
}
|
||||
}
|
||||
issues[(issue.id)] = issue } }}
|
||||
|
||||
public void setName(String name) {
|
||||
super.setName(name)
|
||||
source.renameTo(new File(source.canonicalFile.parentFile, name))
|
||||
}
|
||||
source.renameTo(new File(source.canonicalFile.parentFile, name)) }
|
||||
|
||||
public FileIssue createNewIssue(Map options) {
|
||||
Issue issue
|
||||
File issueFile
|
||||
|
||||
if (!options) options = [:]
|
||||
if (!options.category) options.category = Category.TASK
|
||||
if (!options.status) options.status = Status.NEW
|
||||
if (!options.priority) options.priority = 5
|
||||
if (!options.text) options.text = "Default issue title.\n" +
|
||||
"====================\n"
|
||||
String id
|
||||
if (issues.size() == 0) id = '0000'
|
||||
|
||||
// We want some different defaults for issues due to the parser being
|
||||
// unable to handle empty title or text.
|
||||
if (!options.title) options.title = "Default issue title."
|
||||
if (!options.text) options.text = "Describe the issue here."
|
||||
|
||||
// We are also going to find the next id based on the issues already in the
|
||||
// project.
|
||||
if (issues.size() == 0) options.id = '0000'
|
||||
else {
|
||||
id = (issues.values().max { it.id.toInteger() }).id
|
||||
id = (id.toInteger() + 1).toString().padLeft(id.length(), '0')
|
||||
}
|
||||
def lastId = (issues.values().max { it.id.toInteger() }).id
|
||||
options.id = (lastId.toInteger() + 1).toString().padLeft(
|
||||
lastId.length(), '0') }
|
||||
|
||||
def issueFile = new File(source, FileIssue.makeFilename(id,
|
||||
options.category, options.status, options.priority))
|
||||
// Create an Issue object from the options (we will discard it later).
|
||||
issue = new Issue(options)
|
||||
|
||||
// Create the filename and File object based on the options given.
|
||||
issueFile = new File(source, FileIssue.makeFilename(
|
||||
issue.id, issue.category, issue.status, issue.priority))
|
||||
|
||||
// Create the actual file on the system
|
||||
issueFile.createNewFile()
|
||||
issueFile.write(options.text)
|
||||
|
||||
def issue = new FileIssue(issueFile)
|
||||
// Write the issue to the file created.
|
||||
issueFile.write(FileIssue.formatIssue(issue))
|
||||
|
||||
// Read that new file back in as a FileIssue
|
||||
issue = new FileIssue(issueFile)
|
||||
|
||||
// Add the issue to our collection.
|
||||
issues[(issue.id)] = issue
|
||||
|
||||
return issue
|
||||
}
|
||||
return issue }
|
||||
|
||||
public FileProject createNewProject(String name) {
|
||||
def newDir = new File(source, name)
|
||||
newDir.mkdirs()
|
||||
|
||||
return new FileProject(newDir)
|
||||
}
|
||||
return new FileProject(newDir) }
|
||||
|
||||
public boolean deleteIssue(Issue issue) {
|
||||
if (!issues[(issue.id)]) return false
|
||||
@ -81,8 +90,7 @@ class FileProject extends Project {
|
||||
if (issue instanceof FileIssue)
|
||||
return issue.deleteFile()
|
||||
|
||||
else return true
|
||||
}
|
||||
else return true }
|
||||
|
||||
public boolean deleteProject(Project project) {
|
||||
if (!projects[(project.name)]) return false
|
||||
@ -91,8 +99,7 @@ class FileProject extends Project {
|
||||
if (project instanceof FileProject)
|
||||
return project.source.delete()
|
||||
|
||||
return true
|
||||
}
|
||||
return true }
|
||||
|
||||
@Override
|
||||
public String toString() { return name }
|
||||
|
Loading…
x
Reference in New Issue
Block a user