private ProfessionalCalendarBO buildProfessionalCalendar(
      int idProfessional, Integer idCareSession) {
    ProfessionalEntity professional = professionalDao.findById(idProfessional);
    Validator.shouldBeFound(professional);

    CareSessionEntity careSession = null;

    if (idCareSession != null) {
      careSession = careSessionDao.findById(idCareSession);
      Validator.shouldBeFound(careSession);
    }

    List<ScheduleEntity> frees = new ArrayList();
    List<Pair<ScheduleEntity, AppointmentEntity>> taken = new ArrayList();

    List<ScheduleEntity> allSchedules =
        (idCareSession == null
            ? scheduleDao.findByProfessional(idProfessional)
            : scheduleDao.findByProfessionalByCareSession(idProfessional, idCareSession));
    List<AppointmentEntity> allAppointments =
        (idCareSession == null
            ? appointmentDao.findByProfessional(idProfessional)
            : appointmentDao.findByProfessionalByCareSession(idProfessional, idCareSession));

    // allAppointments should be a subset of allSchedules

    // put all the schedules into a hashmap (by id)
    HashMap<Integer, ScheduleEntity> sch = new HashMap();
    for (ScheduleEntity se : allSchedules) {
      sch.put(se.getId(), se);
    }

    // get the schedules related to appointments and put them in taken
    for (AppointmentEntity ae : allAppointments) {
      ScheduleEntity se = sch.remove(ae.getSchedule().getId());
      Pair<ScheduleEntity, AppointmentEntity> pair = new Pair(se, ae);
      taken.add(pair);
    }

    // put the remaining schedules from the hash into frees
    for (Map.Entry<Integer, ScheduleEntity> entry : sch.entrySet()) {
      frees.add(entry.getValue());
    }

    return new ProfessionalCalendarBO(careSession, professional, frees, taken);
  }