]> gitweb @ CieloNegro.org - task-reporter.git/blobdiff - src/main/scala/jp/ymir/taskReporter/core/Task.scala
adopt the new format
[task-reporter.git] / src / main / scala / jp / ymir / taskReporter / core / Task.scala
index 7b38e0a8013f8ddbecf77d0b1e64c87642d2b7a6..d6ed1d89677d2b4fd941654f4353450c380f9af6 100644 (file)
@@ -1,90 +1,64 @@
 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._
 
-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 DeadlineChanged 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 class Task(
+  date:                   Calendar,
+  ticketID:               Option[Int],
+  title:                  String,
+  expectedCompletionDate: Calendar,
+  deadline:               Option[Calendar],
+  status:                 Task.Status,
+  description:            Option[String]
+)
 
-  private val cols = tsvLine.split("\\t")
-  if (cols.length != 7) {
-    throw new InvalidNumberOfColumnsException(tsvLine)
-  }
-
-  var date : Calendar = {
-    val pattern = """^(?:報告日:)?(\d{4})/(\d{2})/(\d{2})$""".r
-    cols(0) match {
-      case pattern(year, month, day) =>
-        new GregorianCalendar(year.toInt, month.toInt, day.toInt)
-    }
-  }
+object Task {
+  import TSV._
 
-  var ticketID : Int = {
-    val pattern = """^(?:チケットID:)?(\d+)$""".r
-    cols(1) match {
-      case pattern(id) => id.toInt
-    }
+  sealed abstract class Status
+  object Status {
+    case object DoingFine extends Status { override def toString() = "順調"}
+    case object Lagging   extends Status { override def toString() = "遅延"}
+    case object Completed extends Status { override def toString() = "完了"}
   }
 
-  var title : String = {
-    val pattern = """^(?:作業名:)?(.*)$""".r
-    cols(2) match {
-      case pattern(title) => title
-    }
-  }
+  implicit val CalendarFromField = new FromField[Calendar] {
+    val pattern = """^(\d{4})/(\d{2})/(\d{2})$""".r
 
-  var tentativeDeadline : Option[Calendar] = {
-    val pattern = """^(?:仮期限:)?(\d{4})/(\d{2})/(\d{2})$""".r
-    cols(3) match {
+    def parseField(f: Field): Parser[Calendar] = f.value match {
       case pattern(year, month, day) =>
-        Some(new GregorianCalendar(year.toInt, month.toInt, day.toInt))
+        new GregorianCalendar(year.toInt, month.toInt - 1, day.toInt).point[Parser]
       case _ =>
-        None
+        ("date not in format yyyy/MM/dd: " + f).raiseError[Calendar]
     }
   }
 
-  var deadline : Option[Calendar] = {
-    val pattern = """^(?:期限:)?(\d{4})/(\d{2})/(\d{2})$""".r
-    cols(4) match {
-      case pattern(year, month, day) =>
-        Some(new GregorianCalendar(year.toInt, month.toInt, day.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.Completed: Status).point[Parser]
       case _ =>
-        None
+        ("invalid status: " + f).raiseError[Status]
     }
   }
 
-  var status : Status = {
-    val pattern = """^(?:状態:)?(.+)$""".r
-    cols(5) match {
-      case pattern(s) =>
-        s match {
-          case "未作業"   => Status.NoProgress
-          case "順調"     => Status.DoingFine
-          case "悪化"     => Status.Lagging
-          case "遅延"     => Status.WillDelay
-          case "期限変更" => Status.DeadlineChanged
-          case "完了"     => Status.Completed
-        }
-    }
-  }
-
-  var supplement : String = {
-    val pattern = """^(?:補足:)?(.*)$""".r
-    cols(6) 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]  ]('説明, "")
+      }
+      yield Task(date, ticketID, title, expectedCompletionDate,
+                 deadline, status, description)
   }
 }