/////////////////////////////////////////////////////////////////////////// The purpose of Task::validate is three-fold: 1) To provide missing attributes where possible 2) To provide suitable warnings about odd states 3) To update status depending on other attributes As required by TaskChampion, no combination of properties and values is an error. This function will try to make sensible defaults
| 1442 | // Critically, note that despite the name this is not a read-only function. |
| 1443 | // |
| 1444 | void Task::validate(bool applyDefault /* = true */) { |
| 1445 | Task::status status = Task::pending; |
| 1446 | if (get("status") != "") status = getStatus(); |
| 1447 | |
| 1448 | // 1) Provide missing attributes where possible |
| 1449 | // Provide a UUID if necessary. Validate if present. |
| 1450 | std::string uid = get("uuid"); |
| 1451 | if (has("uuid") && uid != "") { |
| 1452 | Lexer lex(uid); |
| 1453 | std::string token; |
| 1454 | Lexer::Type type; |
| 1455 | // `uuid` is not a property in the TaskChampion model, so an invalid UUID is |
| 1456 | // actually an error. |
| 1457 | if (!lex.isUUID(token, type, true)) throw format("Not a valid UUID '{1}'.", uid); |
| 1458 | } else |
| 1459 | set("uuid", uuid()); |
| 1460 | |
| 1461 | // TODO Obsolete remove for 3.0.0 |
| 1462 | // Recurring tasks get a special status. |
| 1463 | if (status == Task::pending && has("due") && has("recur") && |
| 1464 | (!has("parent") || get("parent") == "") && (!has("template") || get("template") == "")) { |
| 1465 | status = Task::recurring; |
| 1466 | } |
| 1467 | /* |
| 1468 | // TODO Add for 3.0.0 |
| 1469 | if (status == Task::pending && |
| 1470 | has ("due") && |
| 1471 | has ("recur") && |
| 1472 | (! has ("template") || get ("template") == "")) |
| 1473 | { |
| 1474 | status = Task::recurring; |
| 1475 | } |
| 1476 | */ |
| 1477 | |
| 1478 | // Tasks with a wait: date get a special status. |
| 1479 | else if (status == Task::pending && has("wait") && get("wait") != "") |
| 1480 | status = Task::waiting; |
| 1481 | |
| 1482 | // By default, tasks are pending. |
| 1483 | else if (!has("status") || get("status") == "") |
| 1484 | status = Task::pending; |
| 1485 | |
| 1486 | // Default to 'periodic' type recurrence. |
| 1487 | if (status == Task::recurring && (!has("rtype") || get("rtype") == "")) { |
| 1488 | set("rtype", "periodic"); |
| 1489 | } |
| 1490 | |
| 1491 | // Store the derived status. |
| 1492 | setStatus(status); |
| 1493 | |
| 1494 | #ifdef PRODUCT_TASKWARRIOR |
| 1495 | // Provide an entry date unless user already specified one. |
| 1496 | if (!has("entry") || get("entry") == "") setAsNow("entry"); |
| 1497 | |
| 1498 | // Completed tasks need an end date, so inherit the entry date. |
| 1499 | if ((status == Task::completed || status == Task::deleted) && (!has("end") || get("end") == "")) |
| 1500 | setAsNow("end"); |
| 1501 |