/* fEMR - fast Electronic Medical Records Copyright (C) 2014 Team fEMR fEMR is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. fEMR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with fEMR. If not, see <http://www.gnu.org/licenses/>. If you have any questions, contact <info@teamfemr.org>. */ package femr.business.services.system; import com.avaje.ebean.ExpressionList; import com.avaje.ebean.Query; import com.google.inject.Inject; import com.google.inject.name.Named; import femr.business.helpers.QueryProvider; import femr.business.services.core.IMissionTripService; import femr.common.IItemModelMapper; import femr.common.dtos.ServiceResponse; import femr.common.models.*; import femr.data.IDataModelMapper; import femr.data.daos.IRepository; import femr.data.daos.core.IUserRepository; import femr.data.models.core.*; import femr.data.models.mysql.*; import femr.util.stringhelpers.StringUtils; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; public class MissionTripService implements IMissionTripService { private final IRepository<IMissionCity> missionCityRepository; private final IRepository<IMissionCountry> missionCountryRepository; private final IRepository<IMissionTeam> missionTeamRepository; private final IRepository<IMissionTrip> missionTripRepository; private final IUserRepository userRepository; private final IDataModelMapper dataModelMapper; private final IItemModelMapper itemModelMapper; @Inject public MissionTripService(IRepository<IMissionCity> missionCityRepository, IRepository<IMissionCountry> missionCountryRepository, IRepository<IMissionTeam> missionTeamRepository, IRepository<IMissionTrip> missionTripRepository, IUserRepository userRepository, IDataModelMapper dataModelMapper, @Named("identified") IItemModelMapper itemModelMapper) { this.missionCityRepository = missionCityRepository; this.missionCountryRepository = missionCountryRepository; this.missionTripRepository = missionTripRepository; this.missionTeamRepository = missionTeamRepository; this.userRepository = userRepository; this.dataModelMapper = dataModelMapper; this.itemModelMapper = itemModelMapper; } /** * {@inheritDoc} */ public ServiceResponse<MissionTripItem> addUsersToTrip(int tripId, List<Integer> userIds) { ServiceResponse<MissionTripItem> response = new ServiceResponse<>(); if (userIds == null || userIds.size() == 0) { response.addError("", "no user ids were received"); return response; } ExpressionList<MissionTrip> expressionList = QueryProvider.getMissionTripQuery() .where() .eq("id", tripId); try { IMissionTrip missionTrip = missionTripRepository.findOne(expressionList); //identify duplicates List<Integer> duplicates = new ArrayList<>(); missionTrip.getUsers() .stream() .filter(user -> userIds.contains(user.getId())) .forEach(user -> { duplicates.add(user.getId()); }); //add non duplicates to the team (users that don't already exist on the team) userIds .stream() .filter(id -> !duplicates.contains(id)) .forEach(id -> missionTrip.addUser(dataModelMapper.createUser(id))); missionTripRepository.update(missionTrip); response.setResponseObject(itemModelMapper.createMissionTripItem(missionTrip)); } catch (Exception ex) { response.addError("", ex.getMessage()); return response; } return response; } /** * {@inheritDoc} */ public ServiceResponse<MissionTripItem> removeUsersFromTrip(int tripId, List<Integer> userIds) { ServiceResponse<MissionTripItem> response = new ServiceResponse<>(); if (userIds == null || userIds.size() == 0) { response.addError("", "no user ids were received"); return response; } ExpressionList<MissionTrip> expressionList = QueryProvider.getMissionTripQuery() .where() .eq("id", tripId); try { IMissionTrip missionTrip = missionTripRepository.findOne(expressionList); //identify duplicates for (Integer id : userIds) { missionTrip.removeUser(id); } missionTripRepository.update(missionTrip); response.setResponseObject(itemModelMapper.createMissionTripItem(missionTrip)); } catch (Exception ex) { response.addError("", ex.getMessage()); return response; } return response; } /** * {@inheritDoc} */ @Override public Optional<IMissionTrip> retrieveCurrentMissionTripForUser(int userId) { //TODO should this be moved to just be identified whenever a CurrentUser is retrieved? // This should be contained in the session service?? IUser user; Optional<IMissionTrip> newestTrip = Optional.empty(); try { user = userRepository.retrieveUserById(userId); newestTrip = user.getMissionTrips() .stream() .sorted((mt1, mt2) -> mt1.getEndDate() .compareTo(mt2.getEndDate())) .reduce((a, b) -> b); } catch (Exception ignored) { } return newestTrip; } /** * {@inheritDoc} */ @Override public ServiceResponse<List<CityItem>> retrieveAvailableCities() { ServiceResponse<List<CityItem>> response = new ServiceResponse<>(); List<CityItem> cities = new ArrayList<>(); Query<MissionCity> missionCityQuery = QueryProvider.getMissionCityQuery() .orderBy("name"); List<? extends IMissionCity> missionCities = missionCityRepository.find(missionCityQuery); for (IMissionCity mc : missionCities) { cities.add(itemModelMapper.createCityItem(mc.getName(), mc.getMissionCountry().getName())); } response.setResponseObject(cities); return response; } /** * {@inheritDoc} */ @Override public ServiceResponse<List<String>> retrieveAvailableCountries() { ServiceResponse<List<String>> response = new ServiceResponse<>(); List<String> countries = new ArrayList<>(); Query<MissionCountry> missionCountryQuery = QueryProvider.getMissionCountryQuery() .orderBy("name"); List<? extends IMissionCountry> missionCountries = missionCountryRepository.find(missionCountryQuery); for (IMissionCountry mc : missionCountries) { countries.add(mc.getName()); } response.setResponseObject(countries); return response; } /** * {@inheritDoc} */ @Override public ServiceResponse<List<MissionItem>> retrieveAllTripInformation() { ServiceResponse<List<MissionItem>> response = new ServiceResponse<>(); List<MissionItem> missionItems = new ArrayList<>(); try { //start by getting all available mission teams. If you start by getting all the trips then //you might miss some teams that don't have a trip, yet. List<? extends IMissionTeam> missionTeams = missionTeamRepository.findAll(MissionTeam.class); List<MissionTripItem> missionTripItems; for (IMissionTeam missionTeam : missionTeams) { missionTripItems = new ArrayList<>(); missionTripItems.addAll(missionTeam.getMissionTrips() .stream() .map(itemModelMapper::createMissionTripItem) .collect(Collectors.toList())); missionItems.add(itemModelMapper.createMissionItem(missionTeam, missionTripItems)); } response.setResponseObject(missionItems); } catch (Exception ex) { response.addError("", ex.getMessage()); } return response; } /** * {@inheritDoc} */ @Override public ServiceResponse<MissionTripItem> retrieveAllTripInformationByTripId(int tripId) { ServiceResponse<MissionTripItem> response = new ServiceResponse<>(); MissionTripItem missionTripItem; try { ExpressionList<MissionTrip> missionTripExpressionList = QueryProvider.getMissionTripQuery() .where() .eq("id", tripId); IMissionTrip missionTrip = missionTripRepository.findOne(missionTripExpressionList); missionTripItem = itemModelMapper.createMissionTripItem(missionTrip); response.setResponseObject(missionTripItem); } catch (Exception ex) { response.addError("", ex.getMessage()); } return response; } /** * {@inheritDoc} */ @Override public ServiceResponse<List<MissionTripItem>> retrieveAllTripInformationByUserId(int userId) { ServiceResponse<List<MissionTripItem>> response = new ServiceResponse<>(); List<MissionTripItem> missionTripItems = new ArrayList<>(); try { IUser user = userRepository.retrieveUserById(userId); //start by getting all available mission teams. If you start by getting all the trips then //you might miss some teams that don't have a trip, yet. missionTripItems.addAll(user.getMissionTrips() .stream() .map(itemModelMapper::createMissionTripItem) .collect(Collectors.toList())); response.setResponseObject(missionTripItems); } catch (Exception ex) { response.addError("", ex.getMessage()); } return response; } /** * {@inheritDoc} */ public ServiceResponse<TeamItem> createNewTeam(TeamItem teamItem) { ServiceResponse<TeamItem> response = new ServiceResponse<>(); if (teamItem == null || StringUtils.isNullOrWhiteSpace(teamItem.getName())) { response.addError("", "team must have a name"); } else { try { IMissionTeam missionTeam = dataModelMapper.createMissionTeam(teamItem.getName(), teamItem.getLocation(), teamItem.getDescription()); missionTeam = missionTeamRepository.create(missionTeam); response.setResponseObject(itemModelMapper.createTeamItem(missionTeam.getName(), missionTeam.getLocation(), missionTeam.getDescription())); } catch (Exception ex) { response.addError("", ex.getMessage()); } } return response; } /** * {@inheritDoc} */ public ServiceResponse<TripItem> createNewTrip(TripItem tripItem) { ServiceResponse<TripItem> response = new ServiceResponse<>(); if (tripItem == null || StringUtils.isNullOrWhiteSpace(tripItem.getTeamName()) || StringUtils.isNullOrWhiteSpace(tripItem.getTripCity()) || StringUtils.isNullOrWhiteSpace(tripItem.getTripCountry()) || tripItem.getTripStartDate() == null || tripItem.getTripEndDate() == null) { response.addError("", "you're missing required fields, try again"); } else { try { ExpressionList<MissionTeam> missionTeamExpressionList = QueryProvider.getMissionTeamQuery() .where() .eq("name", tripItem.getTeamName()); IMissionTeam missionTeam = missionTeamRepository.findOne(missionTeamExpressionList); ExpressionList<MissionCountry> missionCountryExpressionList = QueryProvider.getMissionCountryQuery() .where() .eq("name", tripItem.getTripCountry()); IMissionCountry missionCountry = missionCountryRepository.findOne(missionCountryExpressionList); if (missionCountry == null) { //make sure we have a country to work with response.addError("", "country does not exist"); } else if (missionTeam == null) { //make sure we have a team to work with response.addError("", "team does not exist"); } else { ExpressionList<MissionCity> missionCityExpressionList = QueryProvider.getMissionCityQuery() .where() .eq("name", tripItem.getTripCity()) .eq("missionCountry", missionCountry); IMissionCity missionCity = missionCityRepository.findOne(missionCityExpressionList); if (missionCity == null) { //city doesn't exist missionCity = dataModelMapper.createMissionCity(tripItem.getTripCity(), missionCountry); missionCity = missionCityRepository.create(missionCity); } IMissionTrip missionTrip = dataModelMapper.createMissionTrip(tripItem.getTripStartDate(), tripItem.getTripEndDate(), missionCity, missionTeam); missionTrip = missionTripRepository.create(missionTrip); response.setResponseObject(itemModelMapper.createTripItem(missionTrip.getMissionTeam().getName(), missionTrip.getMissionCity().getName(), missionTrip.getMissionCity().getMissionCountry().getName(), missionTrip.getStartDate(), missionTrip.getEndDate())); } } catch (Exception ex) { response.addError("", ex.getMessage()); } } return response; } /** * {@inheritDoc} */ public ServiceResponse<CityItem> createNewCity(String cityName, String countryName) { ServiceResponse<CityItem> response = new ServiceResponse<>(); if (cityName == null || StringUtils.isNullOrWhiteSpace(cityName)){ response.addError("", "city must have a name"); return response; } if (countryName == null || StringUtils.isNullOrWhiteSpace(countryName)){ response.addError("", "country must have a name"); return response; } ExpressionList<MissionCountry> missionCountryExpressionList = QueryProvider.getMissionCountryQuery() .where() .eq("name", countryName); try { IMissionCountry missionCountry = missionCountryRepository.findOne(missionCountryExpressionList); if (missionCountry == null) { response.addError("", "that country does not exist"); } else { //check for duplicate List<? extends IMissionCity> missionCities = missionCityRepository.findAll(MissionCity.class); boolean isDuplicate = false; for (IMissionCity mc : missionCities) { if (mc.getName().toUpperCase().equals(cityName.toUpperCase())) { isDuplicate = true; response.addError("", "duplicate city"); } } if (!isDuplicate) { IMissionCity missionCity = dataModelMapper.createMissionCity(cityName, missionCountry); missionCity = missionCityRepository.create(missionCity); response.setResponseObject(itemModelMapper.createCityItem(missionCity.getName(), missionCity.getMissionCountry().getName())); } } } catch (Exception ex) { response.addError("", "there was an issue saving the city"); } return response; } }