/**
   * Computes the tracking record based on map records.
   *
   * @param combination the combination
   * @throws Exception the exception
   */
  private void getTrackingRecord(WorkflowStatusCombination combination) throws Exception {
    System.out.println("Computing tracking record for combination: " + combination.toString());

    // reset the records
    resetRecords();

    // sleep 0.5s to allow transaction to complete
    Thread.sleep(500);

    Iterator<WorkflowStatus> statusIter = combination.getWorkflowStatusesAsList().iterator();

    // switch on size of combination
    switch (combination.getWorkflowStatuses().size()) {

        // always invalid
      case 1:
        mappingService.addMapRecord(createRecord(specialist, statusIter.next()));
        break;
        // Valid: REVISION + QA_NEEDED
      case 2:
        mappingService.addMapRecord(createRecord(specialist, statusIter.next()));
        mappingService.addMapRecord(createRecord(lead, statusIter.next()));
        break;
        // valid: REVISION + QA_NEEDED + Specialist/Lead editing/complete
      case 3:
        mappingService.addMapRecord(createRecord(specialist, statusIter.next()));
        mappingService.addMapRecord(createRecord(specialist, statusIter.next()));
        mappingService.addMapRecord(createRecord(lead, statusIter.next()));
        break;
      default:
        fail("Unexpected number of workflow statuses, combination = " + combination.toString());
    }

    // compute workflow
    workflowService.computeWorkflow(mapProject);

    // sleep 1s before retrieving tracking record
    Thread.sleep(1000);
    trackingRecord = workflowService.getTrackingRecord(mapProject, concept);
  }
  /**
   * Test illegal workflow status combinations.
   *
   * @throws Exception the exception
   */
  @Test
  public void testIllegalWorkflowStatusCombinations() throws Exception {

    // set of combinations to test
    Set<WorkflowStatusCombination> combinations = new HashSet<>();

    // maximum number to test
    int nResults = 10;

    // random number generator
    Random random = new Random();

    // extract the status values for convenience
    WorkflowStatus[] statuses = WorkflowStatus.values();

    // cycle over possible combinations of records
    for (int nRecords = 1; nRecords <= 4; nRecords++) {

      // maximum calculations for statuses and number of records
      // e.g. 6 statuses, 2 records -> 36 statuses
      int maxResults = statuses.length ^ (nRecords - 1);

      // while combinations less than max results and less than desired results
      while (combinations.size() < nResults && combinations.size() < maxResults) {

        // create a new random combination
        WorkflowStatusCombination combination = new WorkflowStatusCombination();
        for (int i = 0; i < nRecords; i++) {

          combination.addWorkflowStatus(statuses[random.nextInt(statuses.length)]);
        }
        if (!handler.isWorkflowCombinationInTrackingRecordStates(combination)) {
          combinations.add(combination);
        }
      }
    }

    // make sure the number of generated concepts is in desired range
    assertTrue(combinations.size() > 0 && combinations.size() <= nResults);

    // test the combinations
    for (WorkflowStatusCombination combination : combinations) {

      try {
        getTrackingRecord(combination);
      } catch (Exception e) {

        // if this tracking record contains a PUBLISHED or READY_FOR_PUBLICATION
        // record, ignore error, otherwise fail
        if (combination.getWorkflowStatuses().size() == 1
                && combination
                    .getWorkflowStatuses()
                    .keySet()
                    .iterator()
                    .next()
                    .equals(WorkflowStatus.READY_FOR_PUBLICATION)
            || combination
                .getWorkflowStatuses()
                .keySet()
                .iterator()
                .next()
                .equals(WorkflowStatus.PUBLISHED)) {
          // do nothing
        } else {
          fail("Error computing tracking record for combination " + combination.toString());
        }
      }
      assertTrue(!handler.validateTrackingRecord(trackingRecord).isValid());
    }
  }