1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portlet.polls.lar;
24  
25  import com.liferay.portal.PortalException;
26  import com.liferay.portal.SystemException;
27  import com.liferay.portal.kernel.log.Log;
28  import com.liferay.portal.kernel.log.LogFactoryUtil;
29  import com.liferay.portal.kernel.util.CalendarFactoryUtil;
30  import com.liferay.portal.kernel.util.MapUtil;
31  import com.liferay.portal.kernel.xml.Document;
32  import com.liferay.portal.kernel.xml.Element;
33  import com.liferay.portal.kernel.xml.SAXReaderUtil;
34  import com.liferay.portal.lar.BasePortletDataHandler;
35  import com.liferay.portal.lar.PortletDataContext;
36  import com.liferay.portal.lar.PortletDataException;
37  import com.liferay.portal.lar.PortletDataHandlerBoolean;
38  import com.liferay.portal.lar.PortletDataHandlerControl;
39  import com.liferay.portal.lar.PortletDataHandlerKeys;
40  import com.liferay.portal.service.ServiceContext;
41  import com.liferay.portal.util.PortletKeys;
42  import com.liferay.portlet.polls.DuplicateVoteException;
43  import com.liferay.portlet.polls.NoSuchChoiceException;
44  import com.liferay.portlet.polls.NoSuchQuestionException;
45  import com.liferay.portlet.polls.model.PollsChoice;
46  import com.liferay.portlet.polls.model.PollsQuestion;
47  import com.liferay.portlet.polls.model.PollsVote;
48  import com.liferay.portlet.polls.service.PollsChoiceLocalServiceUtil;
49  import com.liferay.portlet.polls.service.PollsQuestionLocalServiceUtil;
50  import com.liferay.portlet.polls.service.PollsVoteLocalServiceUtil;
51  import com.liferay.portlet.polls.service.persistence.PollsChoiceFinderUtil;
52  import com.liferay.portlet.polls.service.persistence.PollsChoiceUtil;
53  import com.liferay.portlet.polls.service.persistence.PollsQuestionUtil;
54  import com.liferay.portlet.polls.service.persistence.PollsVoteUtil;
55  
56  import java.util.Calendar;
57  import java.util.Date;
58  import java.util.List;
59  import java.util.Map;
60  
61  import javax.portlet.PortletPreferences;
62  
63  /**
64   * <a href="PollsPortletDataHandlerImpl.java.html"><b><i>View Source</i></b></a>
65   *
66   * @author Bruno Farache
67   *
68   */
69  public class PollsPortletDataHandlerImpl extends BasePortletDataHandler {
70  
71      public PortletPreferences deleteData(
72              PortletDataContext context, String portletId,
73              PortletPreferences preferences)
74          throws PortletDataException {
75  
76          try {
77              if (!context.addPrimaryKey(
78                      PollsPortletDataHandlerImpl.class, "deleteData")) {
79  
80                  PollsQuestionLocalServiceUtil.deleteQuestions(
81                      context.getGroupId());
82              }
83  
84              return null;
85          }
86          catch (Exception e) {
87              throw new PortletDataException(e);
88          }
89      }
90  
91      public String exportData(
92              PortletDataContext context, String portletId,
93              PortletPreferences preferences)
94          throws PortletDataException {
95  
96          try {
97              Document doc = SAXReaderUtil.createDocument();
98  
99              Element root = doc.addElement("polls-data");
100 
101             root.addAttribute("group-id", String.valueOf(context.getGroupId()));
102 
103             Element questionsEl = root.addElement("questions");
104             Element choicesEl = root.addElement("choices");
105             Element votesEl = root.addElement("votes");
106 
107             List<PollsQuestion> questions = PollsQuestionUtil.findByGroupId(
108                 context.getGroupId());
109 
110             for (PollsQuestion question : questions) {
111                 exportQuestion(
112                     context, questionsEl, choicesEl, votesEl, question);
113             }
114 
115             return doc.formattedString();
116         }
117         catch (Exception e) {
118             throw new PortletDataException(e);
119         }
120     }
121 
122     public PortletDataHandlerControl[] getExportControls() {
123         return new PortletDataHandlerControl[] {_questions, _votes};
124     }
125 
126     public PortletDataHandlerControl[] getImportControls() {
127         return new PortletDataHandlerControl[] {_questions, _votes};
128     }
129 
130     public PortletPreferences importData(
131             PortletDataContext context, String portletId,
132             PortletPreferences preferences, String data)
133         throws PortletDataException {
134 
135         try {
136             Document doc = SAXReaderUtil.read(data);
137 
138             Element root = doc.getRootElement();
139 
140             List<Element> questionEls = root.element("questions").elements(
141                 "question");
142 
143             Map<Long, Long> questionPKs =
144                 (Map<Long, Long>)context.getNewPrimaryKeysMap(
145                     PollsQuestion.class);
146 
147             for (Element questionEl : questionEls) {
148                 String path = questionEl.attributeValue("path");
149 
150                 if (!context.isPathNotProcessed(path)) {
151                     continue;
152                 }
153 
154                 PollsQuestion question =
155                     (PollsQuestion)context.getZipEntryAsObject(path);
156 
157                 importQuestion(context, questionPKs, question);
158             }
159 
160             List<Element> choiceEls = root.element("choices").elements(
161                 "choice");
162 
163             Map<Long, Long> choicePKs =
164                 (Map<Long, Long>)context.getNewPrimaryKeysMap(
165                     PollsChoice.class);
166 
167             for (Element choiceEl : choiceEls) {
168                 String path = choiceEl.attributeValue("path");
169 
170                 if (!context.isPathNotProcessed(path)) {
171                     continue;
172                 }
173 
174                 PollsChoice choice = (PollsChoice)context.getZipEntryAsObject(
175                     path);
176 
177                 importChoice(context, questionPKs, choicePKs, choice);
178             }
179 
180             if (context.getBooleanParameter(_NAMESPACE, "votes")) {
181                 List<Element> voteEls = root.element("votes").elements("vote");
182 
183                 for (Element voteEl : voteEls) {
184                     String path = voteEl.attributeValue("path");
185 
186                     if (!context.isPathNotProcessed(path)) {
187                         continue;
188                     }
189 
190                     PollsVote vote = (PollsVote)context.getZipEntryAsObject(
191                         path);
192 
193                     importVote(context, questionPKs, choicePKs, vote);
194                 }
195             }
196 
197             return null;
198         }
199         catch (Exception e) {
200             throw new PortletDataException(e);
201         }
202     }
203 
204     public boolean isAlwaysExportable() {
205         return _ALWAYS_EXPORTABLE;
206     }
207 
208     protected void exportChoice(
209             PortletDataContext context, Element questionsEl, PollsChoice choice)
210         throws SystemException {
211 
212         String path = getChoicePath(context, choice);
213 
214         if (!context.isPathNotProcessed(path)) {
215             return;
216         }
217 
218         Element choiceEl = questionsEl.addElement("choice");
219 
220         choiceEl.addAttribute("path", path);
221 
222         context.addZipEntry(path, choice);
223     }
224 
225     protected void exportQuestion(
226             PortletDataContext context, Element questionsEl, Element choicesEl,
227             Element votesEl, PollsQuestion question)
228         throws SystemException {
229 
230         if (!context.isWithinDateRange(question.getModifiedDate())) {
231             return;
232         }
233 
234         String path = getQuestionPath(context, question);
235 
236         if (!context.isPathNotProcessed(path)) {
237             return;
238         }
239 
240         Element questionEl = questionsEl.addElement("question");
241 
242         questionEl.addAttribute("path", path);
243 
244         question.setUserUuid(question.getUserUuid());
245 
246         List<PollsChoice> choices = PollsChoiceUtil.findByQuestionId(
247             question.getQuestionId());
248 
249         for (PollsChoice choice : choices) {
250             exportChoice(context, choicesEl, choice);
251         }
252 
253         if (context.getBooleanParameter(_NAMESPACE, "votes")) {
254             List<PollsVote> votes = PollsVoteUtil.findByQuestionId(
255                 question.getQuestionId());
256 
257             for (PollsVote vote : votes) {
258                 exportVote(context, votesEl, vote);
259             }
260         }
261 
262         context.addZipEntry(path, question);
263     }
264 
265     protected void exportVote(
266             PortletDataContext context, Element questionsEl, PollsVote vote)
267         throws SystemException {
268 
269         String path = getVotePath(context, vote);
270 
271         if (!context.isPathNotProcessed(path)) {
272             return;
273         }
274 
275         Element voteEl = questionsEl.addElement("vote");
276 
277         voteEl.addAttribute("path", path);
278 
279         context.addZipEntry(path, vote);
280     }
281 
282     protected void importChoice(
283             PortletDataContext context, Map<Long, Long> questionPKs,
284             Map<Long, Long> choicePKs, PollsChoice choice)
285         throws Exception {
286 
287         long questionId = MapUtil.getLong(
288             questionPKs, choice.getQuestionId(), choice.getQuestionId());
289 
290         PollsChoice existingChoice = null;
291 
292         try {
293             PollsQuestionUtil.findByPrimaryKey(questionId);
294 
295             if (context.getDataStrategy().equals(
296                     PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
297 
298                 try {
299                     existingChoice = PollsChoiceFinderUtil.findByUuid_G(
300                         choice.getUuid(), context.getGroupId());
301 
302                     existingChoice = PollsChoiceLocalServiceUtil.updateChoice(
303                         existingChoice.getChoiceId(), questionId,
304                         choice.getName(), choice.getDescription());
305                 }
306                 catch (NoSuchChoiceException nsce) {
307                     existingChoice = PollsChoiceLocalServiceUtil.addChoice(
308                         choice.getUuid(), questionId, choice.getName(),
309                         choice.getDescription());
310                 }
311             }
312             else {
313                 existingChoice = PollsChoiceLocalServiceUtil.addChoice(
314                     questionId, choice.getName(), choice.getDescription());
315             }
316 
317             choicePKs.put(choice.getChoiceId(), existingChoice.getChoiceId());
318         }
319         catch (NoSuchQuestionException nsqe) {
320             _log.error(
321                 "Could not find the question for choice " +
322                     choice.getChoiceId());
323         }
324     }
325 
326     protected void importQuestion(
327             PortletDataContext context, Map<Long, Long> questionPKs,
328             PollsQuestion question)
329         throws SystemException, PortalException {
330 
331         long userId = context.getUserId(question.getUserUuid());
332 
333         Date expirationDate = question.getExpirationDate();
334 
335         int expirationMonth = 0;
336         int expirationDay = 0;
337         int expirationYear = 0;
338         int expirationHour = 0;
339         int expirationMinute = 0;
340         boolean neverExpire = true;
341 
342         if (expirationDate != null) {
343             Calendar expirationCal = CalendarFactoryUtil.getCalendar();
344 
345             expirationCal.setTime(expirationDate);
346 
347             expirationMonth = expirationCal.get(Calendar.MONTH);
348             expirationDay = expirationCal.get(Calendar.DATE);
349             expirationYear = expirationCal.get(Calendar.YEAR);
350             expirationHour = expirationCal.get(Calendar.HOUR);
351             expirationMinute = expirationCal.get(Calendar.MINUTE);
352             neverExpire = false;
353 
354             if (expirationCal.get(Calendar.AM_PM) == Calendar.PM) {
355                 expirationHour += 12;
356             }
357         }
358 
359         ServiceContext serviceContext = new ServiceContext();
360 
361         serviceContext.setAddCommunityPermissions(true);
362         serviceContext.setAddGuestPermissions(true);
363         serviceContext.setScopeGroupId(context.getScopeGroupId());
364 
365         PollsQuestion existingQuestion = null;
366 
367         if (context.getDataStrategy().equals(
368                 PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
369 
370             existingQuestion =  PollsQuestionUtil.fetchByUUID_G(
371                 question.getUuid(), context.getGroupId());
372 
373             if (existingQuestion == null) {
374                 existingQuestion = PollsQuestionLocalServiceUtil.addQuestion(
375                     question.getUuid(), userId, question.getTitle(),
376                     question.getDescription(), expirationMonth, expirationDay,
377                     expirationYear, expirationHour, expirationMinute,
378                     neverExpire, null, serviceContext);
379             }
380             else {
381                 existingQuestion = PollsQuestionLocalServiceUtil.updateQuestion(
382                     userId, existingQuestion.getQuestionId(),
383                     question.getTitle(), question.getDescription(),
384                     expirationMonth, expirationDay, expirationYear,
385                     expirationHour, expirationMinute, neverExpire);
386             }
387         }
388         else {
389             existingQuestion = PollsQuestionLocalServiceUtil.addQuestion(
390                 userId, question.getTitle(), question.getDescription(),
391                 expirationMonth, expirationDay, expirationYear, expirationHour,
392                 expirationMinute, neverExpire, null, serviceContext);
393         }
394 
395         questionPKs.put(
396             question.getQuestionId(), existingQuestion.getQuestionId());
397     }
398 
399     protected void importVote(
400             PortletDataContext context, Map<Long, Long> questionPKs,
401             Map<Long, Long> choicePKs, PollsVote vote)
402         throws Exception {
403 
404         long userId = context.getUserId(vote.getUserUuid());
405         long questionId = MapUtil.getLong(
406             questionPKs, vote.getQuestionId(), vote.getQuestionId());
407         long choiceId = MapUtil.getLong(
408             choicePKs, vote.getChoiceId(), vote.getChoiceId());
409 
410         try {
411             PollsQuestionUtil.findByPrimaryKey(questionId);
412             PollsChoiceUtil.findByPrimaryKey(choiceId);
413 
414             PollsVoteLocalServiceUtil.addVote(
415                 userId, questionId, choiceId);
416         }
417         catch (DuplicateVoteException dve) {
418         }
419         catch (NoSuchQuestionException nsqe) {
420             _log.error(
421                 "Could not find the question for vote " + vote.getVoteId());
422         }
423         catch (NoSuchChoiceException nsve) {
424             _log.error(
425                 "Could not find the choice for vote " + vote.getVoteId());
426         }
427     }
428 
429     protected String getChoicePath(
430         PortletDataContext context, PollsChoice choice) {
431 
432         StringBuilder sb = new StringBuilder();
433 
434         sb.append(context.getPortletPath(PortletKeys.POLLS));
435         sb.append("/questions/");
436         sb.append(choice.getQuestionId());
437         sb.append("/choices/");
438         sb.append(choice.getChoiceId());
439         sb.append(".xml");
440 
441         return sb.toString();
442     }
443 
444     protected String getQuestionPath(
445         PortletDataContext context, PollsQuestion question) {
446 
447         StringBuilder sb = new StringBuilder();
448 
449         sb.append(context.getPortletPath(PortletKeys.POLLS));
450         sb.append("/questions/");
451         sb.append(question.getQuestionId());
452         sb.append(".xml");
453 
454         return sb.toString();
455     }
456 
457     protected String getVotePath(PortletDataContext context, PollsVote vote) {
458         StringBuilder sb = new StringBuilder();
459 
460         sb.append(context.getPortletPath(PortletKeys.POLLS));
461         sb.append("/questions/");
462         sb.append(vote.getQuestionId());
463         sb.append("/votes/");
464         sb.append(vote.getVoteId());
465         sb.append(".xml");
466 
467         return sb.toString();
468     }
469 
470     private static final boolean _ALWAYS_EXPORTABLE = true;
471 
472     private static final String _NAMESPACE = "polls";
473 
474     private static final PortletDataHandlerBoolean _questions =
475         new PortletDataHandlerBoolean(_NAMESPACE, "questions", true, true);
476 
477     private static final PortletDataHandlerBoolean _votes =
478         new PortletDataHandlerBoolean(_NAMESPACE, "votes");
479 
480     private static Log _log =
481         LogFactoryUtil.getLog(PollsPortletDataHandlerImpl.class);
482 
483 }