public Map<User, Integer> getUnassignedWorkersMap(Project project) {
   Map<User, Integer> unassignedHasWork = new HashMap<User, Integer>();
   Collection<BacklogItem> blis = getBlisInProjectAndItsIterations(project);
   Collection<User> assignees = backlogBusiness.getUsers(project, true);
   Set<User> workers = new HashSet<User>();
   for (BacklogItem bli : blis) workers.addAll(bli.getResponsibles());
   for (User worker : workers) unassignedHasWork.put(worker, assignees.contains(worker) ? 0 : 1);
   return unassignedHasWork;
 }
 public void resetBliOrigEstAndEffortLeft(int backlogItemId) throws ObjectNotFoundException {
   BacklogItem backlogItem = backlogItemDAO.get(backlogItemId);
   if (backlogItem == null) {
     throw new ObjectNotFoundException("backlogItem.notFound");
   } else {
     // Set effort left and original estimate to null
     backlogItem.setEffortLeft(null);
     backlogItem.setOriginalEstimate(null);
     backlogItemDAO.store(backlogItem);
     historyBusiness.updateBacklogHistory(backlogItem.getBacklog().getId());
   }
 }
 public void setTasksToDone(int backlogItemId) throws ObjectNotFoundException {
   BacklogItem backlogItem = backlogItemDAO.get(backlogItemId);
   if (backlogItem == null) {
     throw new ObjectNotFoundException("backlogItem.notFound");
   } else {
     Map<Integer, State> doneStates = new HashMap<Integer, State>();
     for (Task t : backlogItem.getTasks()) {
       doneStates.put(t.getId(), State.DONE);
     }
     taskBusiness.updateMultipleTasks(backlogItem, doneStates, new HashMap<Integer, String>());
   }
 }
  public void removeBacklogItem(int backlogItemId) throws ObjectNotFoundException {
    BacklogItem backlogItem = backlogItemDAO.get(backlogItemId);

    if (backlogItem == null) {
      throw new ObjectNotFoundException("Backlog item with given id was not found.");
    }

    // Remove all hourEntries related to this backlogItem
    hourEntryBusiness.removeHourEntriesByParent(backlogItem);
    // Store backlog to be able to update its history
    Backlog backlog = backlogItem.getBacklog();
    backlog.getBacklogItems().remove(backlogItem);
    backlogItemDAO.remove(backlogItem);
    // Update backlog history for item's backlog
    historyBusiness.updateBacklogHistory(backlog.getId());
  }
 // TODO: write test
 public List<BacklogItem> getBacklogItemsByBacklog(Backlog backlog) {
   if (backlog != null) {
     List<BacklogItem> items = backlogItemDAO.getBacklogItemsByBacklog(backlog);
     Collections.sort(items, new BacklogItemComparator(new BacklogItemPriorityComparator()));
     // do we need to load spent effort sums
     if (settingBusiness.isHourReportingEnabled()) {
       Map<BacklogItem, AFTime> spentEffort = hourEntryBusiness.getSumsByBacklog(backlog);
       for (BacklogItem item : items) {
         if (spentEffort.containsKey(item)) {
           item.setEffortSpent(spentEffort.get(item));
         }
       }
     }
     return items;
   }
   return null;
 }
  public void moveItemToBacklog(BacklogItem item, Backlog backlog, boolean ignoreIterationGoal) {

    Backlog oldBacklog = item.getBacklog();
    oldBacklog.getBacklogItems().remove(item);
    item.setBacklog(backlog);
    backlog.getBacklogItems().add(item);
    historyBusiness.updateBacklogHistory(oldBacklog.getId());
    historyBusiness.updateBacklogHistory(backlog.getId());

    if (item.getIterationGoal() != null && !ignoreIterationGoal) {
      item.getIterationGoal().getBacklogItems().remove(item);
      item.setIterationGoal(null);
    }

    if (!backlogBusiness.isUnderSameProduct(oldBacklog, backlog)) {
      // remove only product themes
      Collection<BusinessTheme> removeThese = new ArrayList<BusinessTheme>();
      ;
      for (BusinessTheme theme : item.getBusinessThemes()) {
        if (!theme.isGlobal()) {
          removeThese.add(theme);
        }
      }
      for (BusinessTheme theme : removeThese) {
        item.getBusinessThemes().remove(theme);
      }
    }
  }
 public List<BacklogItem> getBacklogItemsByBacklogWithCache(Backlog backlog) {
   List<BacklogItem> items = this.getBacklogItemsByBacklog(backlog);
   Map<BacklogItem, List<BacklogItemResponsibleContainer>> userData =
       this.getResponsiblesByBacklog(backlog);
   Map<BacklogItem, TodoMetrics> todoMetrics = this.getTasksByBacklog(backlog);
   Map<BacklogItem, List<BusinessTheme>> themes =
       this.businessThemeBusiness.getBacklogItemBusinessThemesByBacklog(backlog);
   for (BacklogItem item : items) {
     if (userData.get(item) != null) {
       item.setUserData(userData.get(item));
     }
     if (todoMetrics.get(item) != null) {
       item.setTodoMetrics(todoMetrics.get(item));
     }
     if (themes.get(item) != null) {
       item.setBusinessThemes(themes.get(item));
     }
   }
   return items;
 }
 public BacklogItem createBacklogItemFromTodo(int todoId) {
   BacklogItem backlogItem = new BacklogItem();
   Task data = taskBusiness.getTask(todoId);
   if (data != null) {
     backlogItem.setName(data.getName());
     backlogItem.setState(data.getState());
     backlogItem.setBacklog(data.getBacklogItem().getBacklog());
     backlogItem.setIterationGoal(data.getBacklogItem().getIterationGoal());
     backlogItem.setPriority(data.getBacklogItem().getPriority());
     backlogItem.setResponsibles(data.getBacklogItem().getResponsibles());
     backlogItem.setBusinessThemes(data.getBacklogItem().getBusinessThemes());
   }
   return backlogItem;
 }
 public void setBacklogItemIterationGoal(BacklogItem item, IterationGoal iterationGoal) {
   if (iterationGoal != null && item.getBacklog() == iterationGoal.getIteration()) {
     if (item.getIterationGoal() != null) {
       item.getIterationGoal().getBacklogItems().remove(item);
     }
     item.setIterationGoal(iterationGoal);
     iterationGoal.getBacklogItems().add(item);
   } else {
     if (item.getIterationGoal() != null) {
       item.getIterationGoal().getBacklogItems().remove(item);
     }
     item.setIterationGoal(null);
   }
 }
  /** {@inheritDoc} */
  public List<User> getPossibleResponsibles(BacklogItem bli) {
    Set<User> userSet = new HashSet<User>();

    // Get all enabled users
    userSet.addAll(userBusiness.getEnabledUsers());

    // Get all previous responsibles
    if (bli != null) {
      userSet.addAll(bli.getResponsibles());
    }

    // Create the list and sort it
    List<User> userList = new ArrayList<User>(userSet);
    Collections.sort(userList, new UserComparator());

    return userList;
  }
  public void updateBacklogItemStatePriorityAndEffortLeft(
      int backlogItemId, State newState, AFTime newEffortLeft, Priority newPriority)
      throws ObjectNotFoundException {
    BacklogItem backlogItem = backlogItemDAO.get(backlogItemId);
    if (backlogItem == null) {
      throw new ObjectNotFoundException("backlogItem.notFound");
    }

    /*
     * Set the effort left as original estimate if backlog item's
     * original estimate is null in database
     */
    if (backlogItem.getOriginalEstimate() == null) {
      backlogItem.setEffortLeft(newEffortLeft);
      backlogItem.setOriginalEstimate(newEffortLeft);
    } else if (backlogItem.getEffortLeft() != null && newEffortLeft == null) {
      backlogItem.setEffortLeft(new AFTime(0));
    } else {
      backlogItem.setEffortLeft(newEffortLeft);
    }

    backlogItem.setState(newState);
    backlogItem.setPriority(newPriority);
    // set effortleft to 0 if state changed to done
    if (newState == State.DONE) backlogItem.setEffortLeft(new AFTime(0));

    backlogItemDAO.store(backlogItem);
    historyBusiness.updateBacklogHistory(backlogItem.getBacklog().getId());
  }
  public BacklogItem storeBacklogItem(
      BacklogItem storable,
      Backlog backlog,
      BacklogItem dataItem,
      Set<User> responsibles,
      IterationGoal iterationGoal) {

    boolean historyUpdated = false;

    if (backlog == null) {
      throw new IllegalArgumentException("Backlog must not be null.");
    }
    if (dataItem == null) {
      throw new IllegalArgumentException("No data given.");
    }
    if (storable == null) {
      storable = new BacklogItem();
      storable.setCreatedDate(Calendar.getInstance().getTime());
      try {
        storable.setCreator(SecurityUtil.getLoggedUser()); // may fail if request is multithreaded
      } catch (Exception e) {
      } // however, saving item should not fail.
    }
    storable.setDescription(dataItem.getDescription());
    storable.setEffortLeft(dataItem.getEffortLeft());
    storable.setName(dataItem.getName());
    if (storable.getOriginalEstimate() == null) {
      if (dataItem.getOriginalEstimate() == null) {
        storable.setOriginalEstimate(dataItem.getEffortLeft());
      } else {
        storable.setOriginalEstimate(dataItem.getOriginalEstimate());
      }
    }
    storable.setPriority(dataItem.getPriority());
    storable.setState(dataItem.getState());

    if (dataItem.getState() == State.DONE) {
      storable.setEffortLeft(new AFTime(0));
    } else if (dataItem.getEffortLeft() == null) {
      storable.setEffortLeft(storable.getOriginalEstimate());
    }

    Backlog originalBacklog = storable.getBacklog();
    boolean isBeingMoved = false;

    if (storable.getBacklog() != null && storable.getBacklog() != backlog) {
      isBeingMoved = true;
      this.moveItemToBacklog(storable, backlog, false);
      historyUpdated = true;
    } else if (storable.getBacklog() == null) {
      storable.setBacklog(backlog);
    }

    storable.setResponsibles(responsibles);

    if (iterationGoal == null && isBeingMoved) {
      // Down stepping from Product/Project Story to Iteration Task
      boolean isTargetIteration = backlog instanceof fi.hut.soberit.agilefant.model.Iteration;
      boolean isSourceIteration =
          originalBacklog instanceof fi.hut.soberit.agilefant.model.Iteration;
      if (isTargetIteration && !isSourceIteration) {
        // Not using iterationGoalBusiness because of circular dependency in Spring.
        iterationGoal = new IterationGoal();
        iterationGoal.setName(storable.getName());
        iterationGoal.setIteration((Iteration) backlog);
        iterationGoalDAO.store(iterationGoal);
      }
    }

    this.setBacklogItemIterationGoal(storable, iterationGoal);
    BacklogItem persisted;

    if (storable.getId() == 0) {
      int persistedId = (Integer) backlogItemDAO.create(storable);
      persisted = backlogItemDAO.get(persistedId);
    } else {
      backlogItemDAO.store(storable);
      persisted = storable;
    }
    if (!historyUpdated) {
      historyBusiness.updateBacklogHistory(backlog.getId());
    }
    return persisted;
  }
  private void fillProjectPortfolioData(ProjectPortfolioData data) {
    HashMap<Project, String> userDataMap = new HashMap<Project, String>();
    HashMap<Project, Integer> unassignedUserDataMap = new HashMap<Project, Integer>();
    HashMap<Project, String> summaryLoadLeftMap = new HashMap<Project, String>();
    HashMap<String, String> loadLeftData = new HashMap<String, String>();
    HashMap<String, String> userOverheads = new HashMap<String, String>();
    HashMap<String, String> totalUserOverheads = new HashMap<String, String>();
    HashMap<String, Integer> unassignedUsersMap = new HashMap<String, Integer>();
    Map<Project, List<User>> assignmentMap = new HashMap<Project, List<User>>(0);
    Map<Project, List<User>> nonAssignmentMap = new HashMap<Project, List<User>>(0);
    Set<String> keySet = new HashSet<String>();

    Map<String, Integer> unassignedBlisMap = new HashMap<String, Integer>();

    Collection<Project> projects = projectDAO.getOngoingProjects();

    // Go trough all projects and bli:s
    for (Project pro : projects) {
      int assignedUsers = backlogBusiness.getNumberOfAssignedUsers(pro);
      int unestimatedBlis = 0;
      AFTime ongoingBliLoadLeft = new AFTime(0);
      Set<User> allUsers = new HashSet<User>(this.backlogBusiness.getUsers(pro, true));
      HashSet<User> projectAssignments =
          new HashSet<User>(this.backlogBusiness.getUsers(pro, true));
      List<User> nonAssignedUsers = new ArrayList<User>();
      /*
       * ArrayList<User> assignments = new ArrayList<User>(
       * this.backlogBusiness.getUsers(pro, true));
       */
      Collection<BacklogItem> blis = getBlisInProjectAndItsIterations(pro);

      // Get overheads for users in this project
      for (Assignment ass : pro.getAssignments()) {
        if (ass.getDeltaOverhead() != null) {
          userOverheads.put(
              pro.getId() + "-" + ass.getUser().getId(), ass.getDeltaOverhead().toString());
          AFTime total = new AFTime(0);
          if (pro.getDefaultOverhead() != null) {
            total.add(pro.getDefaultOverhead());
          }
          total.add(ass.getDeltaOverhead());
          totalUserOverheads.put(pro.getId() + "-" + ass.getUser().getId(), total.toString());
        } else {
          if (pro.getDefaultOverhead() != null) {
            totalUserOverheads.put(
                pro.getId() + "-" + ass.getUser().getId(), pro.getDefaultOverhead().toString());
          } else {
            totalUserOverheads.put(pro.getId() + "-" + ass.getUser().getId(), "");
          }
        }
      }

      for (BacklogItem bli : blis) {
        if (bli.getResponsibles() != null) {
          ArrayList<User> responsibles = new ArrayList<User>(bli.getResponsibles());

          if (bli.getEffortLeft() == null) {
            unestimatedBlis++;
            allUsers.addAll(bli.getResponsibles());
          } else if (bli.getEffortLeft().getTime() != 0) {
            ongoingBliLoadLeft.add(bli.getEffortLeft());
            allUsers.addAll(bli.getResponsibles());
          }

          for (User resp : responsibles) {

            keySet.add(pro.getId() + "-" + resp.getId());

            // Calculate and add effort from bli to user(s) assigned
            // Uses projectID-UserId as map key
            String effortForUsr = loadLeftData.get(pro.getId() + "-" + resp.getId());
            if (effortForUsr != null) {
              AFTime usrLoadLeft = new AFTime(effortForUsr);
              if (bli.getEffortLeft() != null) {
                // Add effort to this user: (bli effort / number
                // of people assigned)
                AFTime newEffort = new AFTime(bli.getEffortLeft().getTime() / responsibles.size());
                usrLoadLeft.add(newEffort);
                loadLeftData.put(pro.getId() + "-" + resp.getId(), usrLoadLeft.toString());
              }
            } else { // no effort for user, create one
              if (bli.getEffortLeft() != null) {
                AFTime t = new AFTime(bli.getEffortLeft().getTime() / responsibles.size());
                loadLeftData.put(pro.getId() + "-" + resp.getId(), t.toString());
              }
            }

            // Check whether user is responsible for a bli in the
            // project but is currently not assigned to it

            if (!projectAssignments.contains(resp) && bli.getEffortLeft() == null) {
              unassignedUsersMap.put(pro.getId() + "-" + resp.getId(), 1);
              if (!nonAssignedUsers.contains(resp)) {
                nonAssignedUsers.add(resp);
              }
            } else if (!projectAssignments.contains(resp) && bli.getEffortLeft().getTime() != 0) {
              unassignedUsersMap.put(pro.getId() + "-" + resp.getId(), 1);
              if (!nonAssignedUsers.contains(resp)) {
                nonAssignedUsers.add(resp);
              }
            }
            if (bli.getEffortLeft() == null) {
              int numberOfUnestimatedBlis = 1;
              if (unassignedBlisMap.get(pro.getId() + "-" + resp.getId()) != null) {
                numberOfUnestimatedBlis =
                    unassignedBlisMap.get(pro.getId() + "-" + resp.getId()) + 1;
              }
              unassignedBlisMap.put(pro.getId() + "-" + resp.getId(), numberOfUnestimatedBlis);
            }
          }
        }
      }
      int unassignedUsers = allUsers.size() - assignedUsers;

      String userDataString = "" + assignedUsers;
      EffortSumData loadData = new EffortSumData();
      loadData.setEffortHours(ongoingBliLoadLeft);
      loadData.setNonEstimatedItems(unestimatedBlis);
      String loadLeftString = loadData.toString();

      summaryLoadLeftMap.put(pro, loadLeftString);
      userDataMap.put(pro, userDataString);
      unassignedUserDataMap.put(pro, unassignedUsers);
      assignmentMap.put(pro, new ArrayList<User>(this.backlogBusiness.getUsers(pro, true)));
      nonAssignmentMap.put(pro, nonAssignedUsers);
    }

    for (String key : keySet) {
      String value = loadLeftData.get(key);
      // Fetch aftime-value and non-estimated items to a
      // EffortSumData-object to get correct output string.
      AFTime aftimeValue = new AFTime(0);
      if (value != null) aftimeValue = new AFTime(value);

      int userUnestimatedBlis = 0;
      if (unassignedBlisMap.get(key) != null) userUnestimatedBlis += unassignedBlisMap.get(key);

      EffortSumData sumData = new EffortSumData();
      sumData.setEffortHours(aftimeValue);
      sumData.setNonEstimatedItems(userUnestimatedBlis);

      value = sumData.toString();

      loadLeftData.put(key, value);
    }

    data.setUnassignedUsers(unassignedUsersMap);
    data.setAssignedUsers(assignmentMap);
    data.setSummaryUserData(userDataMap);
    data.setSummaryUnassignedUserData(unassignedUserDataMap);
    data.setSummaryLoadLeftData(summaryLoadLeftMap);
    data.setLoadLefts(loadLeftData);
    data.setUserOverheads(userOverheads);
    data.setTotalUserOverheads(totalUserOverheads);
    data.setNonAssignedUsers(nonAssignmentMap);
  }