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