|
1 | 1 | package pro.taskana.rest;
|
2 | 2 |
|
| 3 | +import java.time.Instant; |
3 | 4 | import java.util.ArrayList;
|
4 | 5 | import java.util.List;
|
5 | 6 | import org.slf4j.Logger;
|
|
27 | 28 | import pro.taskana.TaskService;
|
28 | 29 | import pro.taskana.TaskState;
|
29 | 30 | import pro.taskana.TaskSummary;
|
| 31 | +import pro.taskana.TimeInterval; |
30 | 32 | import pro.taskana.exceptions.AttachmentPersistenceException;
|
31 | 33 | import pro.taskana.exceptions.ClassificationNotFoundException;
|
32 | 34 | import pro.taskana.exceptions.ConcurrencyException;
|
@@ -70,11 +72,17 @@ public class TaskController extends AbstractPagingController {
|
70 | 72 | private static final String POR_SYSTEM = "por.system";
|
71 | 73 | private static final String POR_COMPANY = "por.company";
|
72 | 74 | private static final String DUE = "due";
|
| 75 | + private static final String DUE_TO = "due-until"; |
| 76 | + private static final String DUE_FROM = "due-from"; |
73 | 77 | private static final String PLANNED = "planned";
|
| 78 | + private static final String PLANNED_TO = "planned-until"; |
| 79 | + private static final String PLANNED_FROM = "planned-from"; |
74 | 80 |
|
75 | 81 | private static final String SORT_BY = "sort-by";
|
76 | 82 | private static final String SORT_DIRECTION = "order";
|
77 | 83 |
|
| 84 | + private static final String INDEFINITE = ""; |
| 85 | + |
78 | 86 | private TaskService taskService;
|
79 | 87 |
|
80 | 88 | private TaskResourceAssembler taskResourceAssembler;
|
@@ -248,6 +256,8 @@ private TaskQuery applyFilterParams(TaskQuery taskQuery, MultiValueMap<String, S
|
248 | 256 | LOGGER.debug("Entry to applyFilterParams(taskQuery= {}, params= {})", taskQuery, params);
|
249 | 257 | }
|
250 | 258 |
|
| 259 | + checkForIllegalParamCombinations(params); |
| 260 | + |
251 | 261 | // apply filters
|
252 | 262 | if (params.containsKey(NAME)) {
|
253 | 263 | String[] names = extractCommaSeparatedFields(params.get(NAME));
|
@@ -280,22 +290,7 @@ private TaskQuery applyFilterParams(TaskQuery taskQuery, MultiValueMap<String, S
|
280 | 290 | params.remove(WORKBASKET_ID);
|
281 | 291 | }
|
282 | 292 | if (params.containsKey(WORKBASKET_KEY)) {
|
283 |
| - String[] domains = null; |
284 |
| - if (params.get(DOMAIN) != null) { |
285 |
| - domains = extractCommaSeparatedFields(params.get(DOMAIN)); |
286 |
| - } |
287 |
| - if (domains == null || domains.length != 1) { |
288 |
| - throw new InvalidArgumentException( |
289 |
| - "workbasket-key requires excactly one domain as second parameter."); |
290 |
| - } |
291 |
| - String[] workbasketKeys = extractCommaSeparatedFields(params.get(WORKBASKET_KEY)); |
292 |
| - KeyDomain[] keyDomains = new KeyDomain[workbasketKeys.length]; |
293 |
| - for (int i = 0; i < workbasketKeys.length; i++) { |
294 |
| - keyDomains[i] = new KeyDomain(workbasketKeys[i], domains[0]); |
295 |
| - } |
296 |
| - taskQuery.workbasketKeyDomainIn(keyDomains); |
297 |
| - params.remove(WORKBASKET_KEY); |
298 |
| - params.remove(DOMAIN); |
| 293 | + updateTaskQueryWithWorkbasketKey(taskQuery,params); |
299 | 294 | }
|
300 | 295 | if (params.containsKey(OWNER)) {
|
301 | 296 | String[] owners = extractCommaSeparatedFields(params.get(OWNER));
|
@@ -330,13 +325,195 @@ private TaskQuery applyFilterParams(TaskQuery taskQuery, MultiValueMap<String, S
|
330 | 325 | params.remove(POR_VALUE);
|
331 | 326 | }
|
332 | 327 |
|
| 328 | + if (params.containsKey(PLANNED)) { |
| 329 | + updateTaskQueryWithPlannedOrDueTimeIntervals(taskQuery, params, PLANNED); |
| 330 | + } |
| 331 | + |
| 332 | + if (params.containsKey(DUE)) { |
| 333 | + updateTaskQueryWithPlannedOrDueTimeIntervals(taskQuery, params, DUE); |
| 334 | + } |
| 335 | + |
| 336 | + if (params.containsKey(PLANNED_FROM) && params.containsKey(PLANNED_TO)) { |
| 337 | + updateTaskQueryWithPlannedOrDueTimeInterval(taskQuery, params, PLANNED_FROM, PLANNED_TO); |
| 338 | + |
| 339 | + } else if (params.containsKey(PLANNED_FROM) && !params.containsKey(PLANNED_TO)) { |
| 340 | + |
| 341 | + TimeInterval timeInterval = createIndefiniteTimeIntervalFromParam(params, PLANNED_FROM); |
| 342 | + updateTaskQueryWithIndefiniteTimeInterval(taskQuery, params, PLANNED_FROM, timeInterval); |
| 343 | + |
| 344 | + } else if (!params.containsKey(PLANNED_FROM) && params.containsKey(PLANNED_TO)) { |
| 345 | + |
| 346 | + TimeInterval timeInterval = createIndefiniteTimeIntervalFromParam(params, PLANNED_TO); |
| 347 | + updateTaskQueryWithIndefiniteTimeInterval(taskQuery, params, PLANNED_TO, timeInterval); |
| 348 | + } |
| 349 | + |
| 350 | + if (params.containsKey(DUE_FROM) && params.containsKey(DUE_TO)) { |
| 351 | + updateTaskQueryWithPlannedOrDueTimeInterval(taskQuery, params, DUE_FROM, DUE_TO); |
| 352 | + |
| 353 | + } else if (params.containsKey(DUE_FROM) && !params.containsKey(DUE_TO)) { |
| 354 | + |
| 355 | + TimeInterval indefiniteTimeInterval = createIndefiniteTimeIntervalFromParam(params, DUE_FROM); |
| 356 | + updateTaskQueryWithIndefiniteTimeInterval( |
| 357 | + taskQuery, params, DUE_FROM, indefiniteTimeInterval); |
| 358 | + |
| 359 | + } else if (!params.containsKey(DUE_FROM) && params.containsKey(DUE_TO)) { |
| 360 | + |
| 361 | + TimeInterval timeInterval = createIndefiniteTimeIntervalFromParam(params, DUE_TO); |
| 362 | + updateTaskQueryWithIndefiniteTimeInterval(taskQuery, params, DUE_TO, timeInterval); |
| 363 | + } |
| 364 | + |
333 | 365 | if (LOGGER.isDebugEnabled()) {
|
334 | 366 | LOGGER.debug("Exit from applyFilterParams(), returning {}", taskQuery);
|
335 | 367 | }
|
336 | 368 |
|
337 | 369 | return taskQuery;
|
338 | 370 | }
|
339 | 371 |
|
| 372 | + private void updateTaskQueryWithWorkbasketKey(TaskQuery taskQuery, |
| 373 | + MultiValueMap<String, String> params) |
| 374 | + throws InvalidArgumentException { |
| 375 | + |
| 376 | + String[] domains = null; |
| 377 | + if (params.get(DOMAIN) != null) { |
| 378 | + domains = extractCommaSeparatedFields(params.get(DOMAIN)); |
| 379 | + } |
| 380 | + if (domains == null || domains.length != 1) { |
| 381 | + throw new InvalidArgumentException( |
| 382 | + "workbasket-key requires excactly one domain as second parameter."); |
| 383 | + } |
| 384 | + String[] workbasketKeys = extractCommaSeparatedFields(params.get(WORKBASKET_KEY)); |
| 385 | + KeyDomain[] keyDomains = new KeyDomain[workbasketKeys.length]; |
| 386 | + for (int i = 0; i < workbasketKeys.length; i++) { |
| 387 | + keyDomains[i] = new KeyDomain(workbasketKeys[i], domains[0]); |
| 388 | + } |
| 389 | + taskQuery.workbasketKeyDomainIn(keyDomains); |
| 390 | + params.remove(WORKBASKET_KEY); |
| 391 | + params.remove(DOMAIN); |
| 392 | + |
| 393 | + } |
| 394 | + |
| 395 | + private void checkForIllegalParamCombinations(MultiValueMap<String, String> params) { |
| 396 | + |
| 397 | + if (params.containsKey(PLANNED) |
| 398 | + && (params.containsKey(PLANNED_FROM) || params.containsKey(PLANNED_TO))) { |
| 399 | + |
| 400 | + throw new IllegalArgumentException( |
| 401 | + "It is prohibited to use the param \"" |
| 402 | + + PLANNED |
| 403 | + + "\" in combination with the params \"" |
| 404 | + + PLANNED_FROM |
| 405 | + + "\" and / or \"" |
| 406 | + + PLANNED_TO |
| 407 | + + "\""); |
| 408 | + } |
| 409 | + |
| 410 | + if (params.containsKey(DUE) && (params.containsKey(DUE_FROM) || params.containsKey(DUE_TO))) { |
| 411 | + |
| 412 | + throw new IllegalArgumentException( |
| 413 | + "It is prohibited to use the param \"" |
| 414 | + + DUE |
| 415 | + + "\" in combination with the params \"" |
| 416 | + + PLANNED_FROM |
| 417 | + + "\" and / or \"" |
| 418 | + + PLANNED_TO |
| 419 | + + "\""); |
| 420 | + } |
| 421 | + } |
| 422 | + |
| 423 | + private void updateTaskQueryWithIndefiniteTimeInterval( |
| 424 | + TaskQuery taskQuery, |
| 425 | + MultiValueMap<String, String> params, |
| 426 | + String param, |
| 427 | + TimeInterval timeInterval) { |
| 428 | + |
| 429 | + if (param.equals(PLANNED_FROM) || param.equals(PLANNED_TO)) { |
| 430 | + taskQuery.plannedWithin(timeInterval); |
| 431 | + |
| 432 | + } else { |
| 433 | + taskQuery.dueWithin(timeInterval); |
| 434 | + } |
| 435 | + params.remove(param); |
| 436 | + } |
| 437 | + |
| 438 | + private TimeInterval createIndefiniteTimeIntervalFromParam( |
| 439 | + MultiValueMap<String, String> params, String param) { |
| 440 | + |
| 441 | + if (param.equals(PLANNED_FROM) || param.equals(DUE_FROM)) { |
| 442 | + |
| 443 | + return new TimeInterval(Instant.parse(params.get(param).get(0)), null); |
| 444 | + |
| 445 | + } else { |
| 446 | + |
| 447 | + return new TimeInterval(null, Instant.parse(params.get(param).get(0))); |
| 448 | + } |
| 449 | + } |
| 450 | + |
| 451 | + private void updateTaskQueryWithPlannedOrDueTimeInterval( |
| 452 | + TaskQuery taskQuery, |
| 453 | + MultiValueMap<String, String> params, |
| 454 | + String plannedFromOrDueFrom, |
| 455 | + String plannedToOrDueTo) { |
| 456 | + |
| 457 | + TimeInterval timeInterval = |
| 458 | + new TimeInterval( |
| 459 | + Instant.parse(params.get(plannedFromOrDueFrom).get(0)), |
| 460 | + Instant.parse(params.get(plannedToOrDueTo).get(0))); |
| 461 | + |
| 462 | + taskQuery.plannedWithin(timeInterval); |
| 463 | + |
| 464 | + params.remove(plannedToOrDueTo); |
| 465 | + params.remove(plannedFromOrDueFrom); |
| 466 | + } |
| 467 | + |
| 468 | + private void updateTaskQueryWithPlannedOrDueTimeIntervals( |
| 469 | + TaskQuery taskQuery, MultiValueMap<String, String> params, String plannedOrDue) { |
| 470 | + |
| 471 | + String[] instants = extractCommaSeparatedFields(params.get(plannedOrDue)); |
| 472 | + |
| 473 | + TimeInterval[] timeIntervals = extractTimeIntervals(instants); |
| 474 | + |
| 475 | + taskQuery.plannedWithin(timeIntervals); |
| 476 | + |
| 477 | + params.remove(plannedOrDue); |
| 478 | + } |
| 479 | + |
| 480 | + private TimeInterval[] extractTimeIntervals(String[] instants) { |
| 481 | + |
| 482 | + List<TimeInterval> timeIntervalsList = new ArrayList<>(); |
| 483 | + |
| 484 | + for (int i = 0; i < instants.length - 1; i += 2) { |
| 485 | + |
| 486 | + TimeInterval timeInterval = determineTimeInterval(instants, i); |
| 487 | + |
| 488 | + if (timeInterval != null) { |
| 489 | + |
| 490 | + timeIntervalsList.add(timeInterval); |
| 491 | + } |
| 492 | + } |
| 493 | + |
| 494 | + TimeInterval[] timeIntervalArray = new TimeInterval[timeIntervalsList.size()]; |
| 495 | + |
| 496 | + return timeIntervalsList.toArray(timeIntervalArray); |
| 497 | + } |
| 498 | + |
| 499 | + private TimeInterval determineTimeInterval(String[] instants, int i) { |
| 500 | + |
| 501 | + if (!instants[i].equals(INDEFINITE) && !instants[i + 1].equals(INDEFINITE)) { |
| 502 | + |
| 503 | + return new TimeInterval(Instant.parse(instants[i]), Instant.parse(instants[i + 1])); |
| 504 | + |
| 505 | + } else if (instants[i].equals(INDEFINITE) && !instants[i + 1].equals(INDEFINITE)) { |
| 506 | + |
| 507 | + return new TimeInterval(null, Instant.parse(instants[i + 1])); |
| 508 | + |
| 509 | + } else if (!instants[i].equals(INDEFINITE) && instants[i + 1].equals(INDEFINITE)) { |
| 510 | + |
| 511 | + return new TimeInterval(Instant.parse(instants[i]), null); |
| 512 | + } |
| 513 | + |
| 514 | + return null; |
| 515 | + } |
| 516 | + |
340 | 517 | private TaskQuery applySortingParams(TaskQuery taskQuery, MultiValueMap<String, String> params)
|
341 | 518 | throws InvalidArgumentException {
|
342 | 519 | if (LOGGER.isDebugEnabled()) {
|
|
0 commit comments