pit/libpit/src/main/com/jdbernard/pit/file/FileProject.groovy
Jonathan Bernard 846d1edc74 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.
2011-12-08 14:38:24 -06:00

108 lines
3.3 KiB
Groovy
Executable File

package com.jdbernard.pit.file
import com.jdbernard.pit.*
class FileProject extends Project {
protected File source
public FileProject(File dir) {
super(dir.canonicalFile.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+/ ||
child.isHidden()) return // just an issue folder
// otherwise build and add to list
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 } }}
public void setName(String name) {
super.setName(name)
source.renameTo(new File(source.canonicalFile.parentFile, name)) }
public FileIssue createNewIssue(Map options) {
Issue issue
File issueFile
if (!options) options = [:]
// 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 {
def lastId = (issues.values().max { it.id.toInteger() }).id
options.id = (lastId.toInteger() + 1).toString().padLeft(
lastId.length(), '0') }
// 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()
// 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 }
public FileProject createNewProject(String name) {
def newDir = new File(source, name)
newDir.mkdirs()
return new FileProject(newDir) }
public boolean deleteIssue(Issue issue) {
if (!issues[(issue.id)]) return false
issues.remove(issue.id)
if (issue instanceof FileIssue)
return issue.deleteFile()
else return true }
public boolean deleteProject(Project project) {
if (!projects[(project.name)]) return false
projects.remove(project.name)
if (project instanceof FileProject)
return project.source.delete()
return true }
@Override
public String toString() { return name }
}