View Javadoc
1   package fr.ifremer.dali.service.administration.campaign;
2   
3   /*-
4    * #%L
5    * Dali :: Core
6    * %%
7    * Copyright (C) 2014 - 2017 Ifremer
8    * %%
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU Affero General Public License as published by
11   * the Free Software Foundation, either version 3 of the License, or
12   * (at your option) any later version.
13   *
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Public License for more details.
18   *
19   * You should have received a copy of the GNU Affero General Public License
20   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21   * #L%
22   */
23  
24  import com.google.common.base.Joiner;
25  import fr.ifremer.dali.dao.data.survey.DaliCampaignDao;
26  import fr.ifremer.dali.dao.system.filter.DaliFilterDao;
27  import fr.ifremer.dali.dto.DaliBeans;
28  import fr.ifremer.dali.dto.SearchDateDTO;
29  import fr.ifremer.dali.dto.configuration.filter.FilterDTO;
30  import fr.ifremer.dali.dto.data.survey.CampaignDTO;
31  import fr.ifremer.dali.dto.enums.FilterTypeValues;
32  import fr.ifremer.dali.dto.enums.SearchDateValues;
33  import fr.ifremer.dali.service.DaliBusinessException;
34  import fr.ifremer.quadrige3.core.dao.data.survey.CampaignDao;
35  import fr.ifremer.quadrige3.core.dao.technical.Assert;
36  import fr.ifremer.quadrige3.core.security.AuthenticationInfo;
37  import fr.ifremer.quadrige3.core.vo.data.survey.CampaignVO;
38  import fr.ifremer.quadrige3.synchro.service.client.SynchroRestClientService;
39  import org.apache.commons.collections4.CollectionUtils;
40  import org.apache.commons.lang3.StringUtils;
41  import org.apache.commons.logging.Log;
42  import org.apache.commons.logging.LogFactory;
43  import org.springframework.stereotype.Service;
44  
45  import javax.annotation.Resource;
46  import java.util.*;
47  import java.util.stream.Collectors;
48  
49  /**
50   * @author peck7 on 02/08/2017.
51   */
52  @Service("daliCampaignService")
53  public class CampaignServiceImpl implements CampaignService {
54  
55      private static final Log LOG = LogFactory.getLog(CampaignServiceImpl.class);
56  
57      @Resource(name = "daliCampaignDao")
58      private DaliCampaignDao campaignDao;
59  
60      @Resource(name = "synchroRestClientService")
61      private SynchroRestClientService synchroRestClientService;
62  
63      @Resource(name = "daliFilterDao")
64      private DaliFilterDao filterDao;
65  
66      @Override
67      public List<CampaignDTO> getAllCampaigns() {
68          return campaignDao.getAllCampaigns();
69      }
70  
71      @Override
72      public List<CampaignDTO> findCampaignsByCriteria(String name,
73                                                       SearchDateDTO startDateSearch, Date startDate1, Date startDate2,
74                                                       SearchDateDTO endDateSearch, Date endDate1, Date endDate2) {
75  
76          // compute start date operation
77          boolean strictStartDate = false;
78          if (startDateSearch == null) {
79              startDate1 = startDate2 = null;
80          } else {
81              SearchDateValues startSearchDateValue = SearchDateValues.values()[startDateSearch.getId()];
82              switch (startSearchDateValue) {
83  
84                  case EQUALS:
85                      if (startDate1 == null) return null;
86                      startDate2 = startDate1;
87                      strictStartDate = true;
88                      break;
89                  case BETWEEN:
90                      if (startDate1 == null || startDate2 == null) return null;
91                      break;
92                  case BEFORE:
93                      strictStartDate = true;
94                  case BEFORE_OR_EQUALS:
95                      if (startDate1 == null) return null;
96                      startDate2 = startDate1;
97                      startDate1 = null;
98                      break;
99                  case AFTER:
100                     strictStartDate = true;
101                 case AFTER_OR_EQUALS:
102                     if (startDate1 == null) return null;
103                     startDate2 = null;
104                     break;
105             }
106         }
107 
108         // compute end date operation
109         boolean strictEndDate = false;
110         if (endDateSearch == null) {
111             endDate1 = endDate2 = null;
112         } else {
113             SearchDateValues endSearchDateValue = SearchDateValues.values()[endDateSearch.getId()];
114             switch (endSearchDateValue) {
115 
116                 case EQUALS:
117                     if (endDate1 == null) return null;
118                     endDate2 = endDate1;
119                     strictEndDate = true;
120                     break;
121                 case BETWEEN:
122                     if (endDate1 == null || endDate2 == null) return null;
123                     break;
124                 case BEFORE:
125                     strictEndDate = true;
126                 case BEFORE_OR_EQUALS:
127                     if (endDate1 == null) return null;
128                     endDate2 = endDate1;
129                     endDate1 = null;
130                     break;
131                 case AFTER:
132                     strictEndDate = true;
133                 case AFTER_OR_EQUALS:
134                     if (endDate1 == null) return null;
135                     endDate2 = null;
136                     break;
137             }
138         }
139 
140         return campaignDao.getCampaignsByCriteria(name, startDate1, startDate2, strictStartDate, endDate1, endDate2, strictEndDate, false);
141     }
142 
143     @Override
144     public List<CampaignDTO> findCampaignsIncludingDate(Date date) {
145 
146         return campaignDao.getCampaignsByCriteria(null, null, date, false, date, null, false, true);
147     }
148 
149     @Override
150     public boolean checkCampaignNameDuplicates(Integer id, String name) {
151         if (StringUtils.isBlank(name)) return false;
152 
153         List<CampaignDTO> campaigns = campaignDao.getCampaignsByName(name);
154         int nb = CollectionUtils.size(campaigns);
155         if (nb > 1) {
156             // multiple campaign have same name (upper case), should be already an error
157             LOG.warn(String.format("campaign with name '%s' already exists %s times in database", name, nb));
158             return true;
159         } else return nb == 1 && !CollectionUtils.extractSingleton(campaigns).getId().equals(id);
160 
161     }
162 
163     @Override
164     public void saveCampaigns(AuthenticationInfo authenticationInfo, Collection<? extends CampaignDTO> campaigns) {
165 
166         Assert.notNull(campaigns);
167 
168         List<CampaignDTO> dirtyCampaigns = campaigns.stream().filter(CampaignDTO::isDirty).collect(Collectors.toList());
169 
170         // Nothing to save
171         if (CollectionUtils.isEmpty(dirtyCampaigns)) return;
172 
173         Set<Integer> campaignIds = dirtyCampaigns.stream().map(campaign -> {
174 
175             // preconditions
176             Assert.notNull(campaign.getName());
177             Assert.notNull(campaign.getStartDate());
178             Assert.notNull(campaign.getManager());
179 
180             // save
181             campaignDao.saveCampaign(campaign);
182 
183             // Todo reporter à la fin
184             campaign.setDirty(false);
185 
186             return campaign.getId();
187         }).collect(Collectors.toSet());
188 
189         // save remote campaigns
190         List<CampaignVO> savedCampaigns = saveCampaignsOnServer(authenticationInfo, campaignIds);
191 
192         // map new id from VO to DTO
193         dirtyCampaigns.stream()
194                 // in case of new campaign, id is negative locally
195                 .filter(campaign -> campaign.getId() < 0)
196                 .forEach(campaign -> {
197                     // get previous temporary id
198                     int negativeCampaignId = campaign.getId();
199                     // find by name
200                     CampaignVO savedCampaign = DaliBeans.findByProperty(savedCampaigns, "campaignNm", campaign.getName());
201                     if (savedCampaign == null) {
202                         throw new DaliBusinessException(String.format("Unable to find saved campaign '%s'", campaign.getName()));
203                     }
204                     // affect correct id
205                     campaign.setId(savedCampaign.getCampaignId());
206                     // delete temp campaign
207                     campaignDao.remove(negativeCampaignId);
208                 });
209 
210     }
211 
212     private List<CampaignVO> saveCampaignsOnServer(AuthenticationInfo authenticationInfo, Set<Integer> campaignIds) {
213 
214         if (CollectionUtils.isEmpty(campaignIds)) return new ArrayList<>();
215 
216         if (LOG.isDebugEnabled()) {
217             LOG.debug(String.format("Sending campaigns [%s] to server", Joiner.on(',').join(campaignIds)));
218         }
219 
220         // Load VOs
221         List<CampaignVO> campaignsToSend = DaliBeans.transformCollection(campaignIds,
222                 campaignId -> (CampaignVO) campaignDao.load(CampaignDao.TRANSFORM_CAMPAIGNVO, campaignId));
223 
224         // send to server
225         List<CampaignVO> savedCampaigns = synchroRestClientService.saveCampaigns(authenticationInfo, campaignsToSend);
226 
227         if (LOG.isDebugEnabled()) {
228             LOG.debug(String.format("Saving campaigns [%s] from server response", Joiner.on(',').join(savedCampaigns)));
229         }
230 
231         // save locally
232         savedCampaigns.forEach(campaignDao::save);
233 
234         return savedCampaigns;
235     }
236 
237     @Override
238     public void deleteCampaign(AuthenticationInfo authenticationInfo, List<Integer> campaignIds) {
239 
240         if (CollectionUtils.isEmpty(campaignIds)) return;
241         for (Integer campaignId : campaignIds) {
242             campaignDao.remove(campaignId);
243         }
244 
245         deleteCampaignOnServer(authenticationInfo, campaignIds);
246     }
247 
248     @Override
249     public boolean isCampaignUsedByFilter(int campaignId) {
250 
251         // search the program in all existing context filters
252         List<FilterDTO> campaignFilters = filterDao.getAllContextFilters(null, FilterTypeValues.CAMPAIGN.getFilterTypeId());
253         if (CollectionUtils.isNotEmpty(campaignFilters)) {
254             for (FilterDTO campaignFilter : campaignFilters) {
255                 List<Integer> campaignIds = DaliBeans.transformCollection(filterDao.getFilteredElementsByFilterId(campaignFilter.getId()), DaliBeans.ID_MAPPER);
256                 if (campaignIds.contains(campaignId)) {
257                     return true;
258                 }
259             }
260         }
261         return false;
262 
263     }
264 
265     @Override
266     public long countSurveysWithCampaign(int campaignId) {
267         return Optional
268                 .ofNullable(campaignDao.countSurveyUsage(campaignId))
269                 .orElse(0L);
270     }
271 
272     private void deleteCampaignOnServer(AuthenticationInfo authenticationInfo, List<Integer> campaignIds) {
273 
274         // filter only positive ids
275         List<Integer> remoteIds = campaignIds.stream().filter(campaignId -> campaignId >= 0).collect(Collectors.toList());
276 
277         if (LOG.isDebugEnabled()) {
278             LOG.debug(String.format("Delete campaigns [%s] from server", Joiner.on(',').join(remoteIds)));
279         }
280 
281         // delete campaign from server (only positive ids)
282         synchroRestClientService.deleteCampaigns(authenticationInfo, remoteIds);
283 
284         if (LOG.isDebugEnabled()) {
285             LOG.debug(String.format("Campaigns [%s] deleted from server", Joiner.on(',').join(remoteIds)));
286         }
287     }
288 
289 }