package jp.ymir.taskReporter.core
import java.util.Calendar
import java.util.GregorianCalendar
+import scala.language.reflectiveCalls
import scala.util.matching.Regex
+import scalaz._
+import Scalaz._
+
+case class Task(
+ date: Calendar,
+ ticketID: Option[Int],
+ title: String,
+ expectedCompletionDate: Calendar,
+ deadline: Option[Calendar],
+ status: Task.Status,
+ description: Option[String]
+)
+
+object Task {
+ import TSV._
-class Task(tsvLine: String) {
sealed abstract class Status
object Status {
- case object NoProgress extends Status
- case object DoingFine extends Status
- case object Lagging extends Status
- case object WillDelay extends Status
- case object DeadlinePostponed extends Status
- case object Completed extends Status
- }
-
- class InvalidNumberOfColumnsException private(e: RuntimeException) extends RuntimeException(e) {
- def this(msg: String) = this(new RuntimeException(msg))
- def this(msg: String, cause: Throwable) = this(new RuntimeException(msg, cause))
+ case object DoingFine extends Status { override def toString() = "順調" }
+ case object Lagging extends Status { override def toString() = "遅延" }
+ case object DeadlineChanged extends Status { override def toString() = "期限変更" }
+ case object Completed extends Status { override def toString() = "完了" }
}
- private val cols = tsvLine.split("\\t")
- if (cols.length != 7) {
- throw new InvalidNumberOfColumnsException(tsvLine)
- }
+ implicit val CalendarFromField = new FromField[Calendar] {
+ val pattern = """^(\d{4})/(\d{2})/(\d{2})$""".r
- val date : Calendar = {
- val pattern = """^(?:報告日:)?(\d{4})/(\d{2})/(\d{2})$""".r
- cols(0) match {
+ def parseField(f: Field): Parser[Calendar] = f.value match {
case pattern(year, month, day) =>
- new GregorianCalendar(year.toInt, month.toInt, day.toInt)
+ new GregorianCalendar(year.toInt, month.toInt - 1, day.toInt).point[Parser]
+ case _ =>
+ ("date not in format yyyy/MM/dd: " + f).raiseError[Calendar]
}
}
- val ticketID : Int = {
- val pattern = """^(?:チケットID:)?(\d+)$""".r
- cols(1) match {
- case pattern(id) => id.toInt
+ implicit val StatusFromField = new FromField[Status] {
+ def parseField(f: Field): Parser[Status] = f.value match {
+ case "順調" => (Status.DoingFine: Status).point[Parser]
+ case "遅延" => (Status.Lagging: Status).point[Parser]
+ case "期限変更" => (Status.DeadlineChanged: Status).point[Parser]
+ case "完了" => (Status.Completed: Status).point[Parser]
+ case _ =>
+ ("invalid status: " + f).raiseError[Status]
}
}
- val title : String = {
- val pattern = """^(?:作業名:)?(.*)$""".r
- cols(1) match {
- case pattern(title) => title
- }
+ implicit val TaskFromRecord = new FromRecord[Task] {
+ def parseRecord(r: Record): Parser[Task] =
+ for {
+ date <- r.lookup[Calendar ]('報告日)
+ ticketID <- r.lookup[Option[Int] ]('チケットID)
+ title <- r.lookup[String ]('作業名)
+ expectedCompletionDate <- r.lookup[Calendar ]('作業完了予定年月日)
+ deadline <- r.lookup[Option[Calendar]]('タスク期限)
+ status <- r.lookup[Status ]('状態)
+ description <- r.lookup[Option[String] ]('説明).handleError(_ => None.point[Parser])
+ }
+ yield Task(date, ticketID, title, expectedCompletionDate,
+ deadline, status, description)
}
}