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.log.Log;
20  import com.liferay.portal.kernel.log.LogFactoryUtil;
21  import com.liferay.portal.kernel.util.CalendarFactoryUtil;
22  import com.liferay.portal.kernel.util.MapUtil;
23  import com.liferay.portal.kernel.util.StringBundler;
24  import com.liferay.portal.kernel.xml.Document;
25  import com.liferay.portal.kernel.xml.Element;
26  import com.liferay.portal.kernel.xml.SAXReaderUtil;
27  import com.liferay.portal.lar.BasePortletDataHandler;
28  import com.liferay.portal.lar.PortletDataContext;
29  import com.liferay.portal.lar.PortletDataException;
30  import com.liferay.portal.lar.PortletDataHandlerBoolean;
31  import com.liferay.portal.lar.PortletDataHandlerControl;
32  import com.liferay.portal.lar.PortletDataHandlerKeys;
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 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.addZipEntry(path, question);
102     }
103 
104     public static void importChoice(
105             PortletDataContext context, Map<Long, Long> questionPKs,
106             Map<Long, Long> choicePKs, PollsChoice choice)
107         throws Exception {
108 
109         long questionId = MapUtil.getLong(
110             questionPKs, choice.getQuestionId(), choice.getQuestionId());
111 
112         PollsChoice existingChoice = null;
113 
114         try {
115             PollsQuestionUtil.findByPrimaryKey(questionId);
116 
117             if (context.getDataStrategy().equals(
118                     PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
119 
120                 try {
121                     existingChoice = PollsChoiceFinderUtil.findByUuid_G(
122                         choice.getUuid(), context.getGroupId());
123 
124                     existingChoice = PollsChoiceLocalServiceUtil.updateChoice(
125                         existingChoice.getChoiceId(), questionId,
126                         choice.getName(), choice.getDescription());
127                 }
128                 catch (NoSuchChoiceException nsce) {
129                     existingChoice = PollsChoiceLocalServiceUtil.addChoice(
130                         choice.getUuid(), questionId, choice.getName(),
131                         choice.getDescription());
132                 }
133             }
134             else {
135                 existingChoice = PollsChoiceLocalServiceUtil.addChoice(
136                     null, questionId, choice.getName(),
137                     choice.getDescription());
138             }
139 
140             choicePKs.put(choice.getChoiceId(), existingChoice.getChoiceId());
141         }
142         catch (NoSuchQuestionException nsqe) {
143             _log.error(
144                 "Could not find the question for choice " +
145                     choice.getChoiceId());
146         }
147     }
148 
149     public static void importQuestion(
150             PortletDataContext context, Map<Long, Long> questionPKs,
151             PollsQuestion question)
152         throws SystemException, PortalException {
153 
154         long userId = context.getUserId(question.getUserUuid());
155 
156         Date expirationDate = question.getExpirationDate();
157 
158         int expirationMonth = 0;
159         int expirationDay = 0;
160         int expirationYear = 0;
161         int expirationHour = 0;
162         int expirationMinute = 0;
163         boolean neverExpire = true;
164 
165         if (expirationDate != null) {
166             Calendar expirationCal = CalendarFactoryUtil.getCalendar();
167 
168             expirationCal.setTime(expirationDate);
169 
170             expirationMonth = expirationCal.get(Calendar.MONTH);
171             expirationDay = expirationCal.get(Calendar.DATE);
172             expirationYear = expirationCal.get(Calendar.YEAR);
173             expirationHour = expirationCal.get(Calendar.HOUR);
174             expirationMinute = expirationCal.get(Calendar.MINUTE);
175             neverExpire = false;
176 
177             if (expirationCal.get(Calendar.AM_PM) == Calendar.PM) {
178                 expirationHour += 12;
179             }
180         }
181 
182         ServiceContext serviceContext = new ServiceContext();
183 
184         serviceContext.setAddCommunityPermissions(true);
185         serviceContext.setAddGuestPermissions(true);
186         serviceContext.setScopeGroupId(context.getScopeGroupId());
187 
188         PollsQuestion existingQuestion = null;
189 
190         if (context.getDataStrategy().equals(
191                 PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
192 
193             existingQuestion =  PollsQuestionUtil.fetchByUUID_G(
194                 question.getUuid(), context.getGroupId());
195 
196             if (existingQuestion == null) {
197                 existingQuestion = PollsQuestionLocalServiceUtil.addQuestion(
198                     question.getUuid(), userId, question.getTitleMap(),
199                     question.getDescriptionMap(), expirationMonth,
200                     expirationDay, expirationYear, expirationHour,
201                     expirationMinute, neverExpire, null, serviceContext);
202             }
203             else {
204                 existingQuestion = PollsQuestionLocalServiceUtil.updateQuestion(
205                     userId, existingQuestion.getQuestionId(),
206                     question.getTitleMap(), question.getDescriptionMap(),
207                     expirationMonth, expirationDay, expirationYear,
208                     expirationHour, expirationMinute, neverExpire);
209             }
210         }
211         else {
212             existingQuestion = PollsQuestionLocalServiceUtil.addQuestion(
213                 null, userId, question.getTitleMap(),
214                 question.getDescriptionMap(), expirationMonth, expirationDay,
215                 expirationYear, expirationHour, expirationMinute, neverExpire,
216                 null, serviceContext);
217         }
218 
219         questionPKs.put(
220             question.getQuestionId(), existingQuestion.getQuestionId());
221     }
222 
223     public static void importVote(
224             PortletDataContext context, Map<Long, Long> questionPKs,
225             Map<Long, Long> choicePKs, PollsVote vote)
226         throws Exception {
227 
228         long userId = context.getUserId(vote.getUserUuid());
229         long questionId = MapUtil.getLong(
230             questionPKs, vote.getQuestionId(), vote.getQuestionId());
231         long choiceId = MapUtil.getLong(
232             choicePKs, vote.getChoiceId(), vote.getChoiceId());
233 
234         try {
235             PollsQuestionUtil.findByPrimaryKey(questionId);
236             PollsChoiceUtil.findByPrimaryKey(choiceId);
237 
238             PollsVoteLocalServiceUtil.addVote(
239                 userId, questionId, choiceId);
240         }
241         catch (DuplicateVoteException dve) {
242         }
243         catch (NoSuchQuestionException nsqe) {
244             _log.error(
245                 "Could not find the question for vote " + vote.getVoteId());
246         }
247         catch (NoSuchChoiceException nsve) {
248             _log.error(
249                 "Could not find the choice for vote " + vote.getVoteId());
250         }
251     }
252 
253     public PortletPreferences deleteData(
254             PortletDataContext context, String portletId,
255             PortletPreferences preferences)
256         throws PortletDataException {
257 
258         try {
259             if (!context.addPrimaryKey(
260                     PollsPortletDataHandlerImpl.class, "deleteData")) {
261 
262                 PollsQuestionLocalServiceUtil.deleteQuestions(
263                     context.getGroupId());
264             }
265 
266             return null;
267         }
268         catch (Exception e) {
269             throw new PortletDataException(e);
270         }
271     }
272 
273     public String exportData(
274             PortletDataContext context, String portletId,
275             PortletPreferences preferences)
276         throws PortletDataException {
277 
278         try {
279             Document doc = SAXReaderUtil.createDocument();
280 
281             Element root = doc.addElement("polls-data");
282 
283             root.addAttribute("group-id", String.valueOf(context.getGroupId()));
284 
285             Element questionsEl = root.addElement("questions");
286             Element choicesEl = root.addElement("choices");
287             Element votesEl = root.addElement("votes");
288 
289             List<PollsQuestion> questions = PollsQuestionUtil.findByGroupId(
290                 context.getGroupId());
291 
292             for (PollsQuestion question : questions) {
293                 exportQuestion(
294                     context, questionsEl, choicesEl, votesEl, question);
295             }
296 
297             return doc.formattedString();
298         }
299         catch (Exception e) {
300             throw new PortletDataException(e);
301         }
302     }
303 
304     public PortletDataHandlerControl[] getExportControls() {
305         return new PortletDataHandlerControl[] {_questions, _votes};
306     }
307 
308     public PortletDataHandlerControl[] getImportControls() {
309         return new PortletDataHandlerControl[] {_questions, _votes};
310     }
311 
312     public PortletPreferences importData(
313             PortletDataContext context, String portletId,
314             PortletPreferences preferences, String data)
315         throws PortletDataException {
316 
317         try {
318             Document doc = SAXReaderUtil.read(data);
319 
320             Element root = doc.getRootElement();
321 
322             List<Element> questionEls = root.element("questions").elements(
323                 "question");
324 
325             Map<Long, Long> questionPKs =
326                 (Map<Long, Long>)context.getNewPrimaryKeysMap(
327                     PollsQuestion.class);
328 
329             for (Element questionEl : questionEls) {
330                 String path = questionEl.attributeValue("path");
331 
332                 if (!context.isPathNotProcessed(path)) {
333                     continue;
334                 }
335 
336                 PollsQuestion question =
337                     (PollsQuestion)context.getZipEntryAsObject(path);
338 
339                 importQuestion(context, questionPKs, question);
340             }
341 
342             List<Element> choiceEls = root.element("choices").elements(
343                 "choice");
344 
345             Map<Long, Long> choicePKs =
346                 (Map<Long, Long>)context.getNewPrimaryKeysMap(
347                     PollsChoice.class);
348 
349             for (Element choiceEl : choiceEls) {
350                 String path = choiceEl.attributeValue("path");
351 
352                 if (!context.isPathNotProcessed(path)) {
353                     continue;
354                 }
355 
356                 PollsChoice choice = (PollsChoice)context.getZipEntryAsObject(
357                     path);
358 
359                 importChoice(context, questionPKs, choicePKs, choice);
360             }
361 
362             if (context.getBooleanParameter(_NAMESPACE, "votes")) {
363                 List<Element> voteEls = root.element("votes").elements("vote");
364 
365                 for (Element voteEl : voteEls) {
366                     String path = voteEl.attributeValue("path");
367 
368                     if (!context.isPathNotProcessed(path)) {
369                         continue;
370                     }
371 
372                     PollsVote vote = (PollsVote)context.getZipEntryAsObject(
373                         path);
374 
375                     importVote(context, questionPKs, choicePKs, vote);
376                 }
377             }
378 
379             return null;
380         }
381         catch (Exception e) {
382             throw new PortletDataException(e);
383         }
384     }
385 
386     public boolean isAlwaysExportable() {
387         return _ALWAYS_EXPORTABLE;
388     }
389 
390     protected static void exportChoice(
391             PortletDataContext context, Element questionsEl, PollsChoice choice)
392         throws SystemException {
393 
394         String path = getChoicePath(context, choice);
395 
396         if (!context.isPathNotProcessed(path)) {
397             return;
398         }
399 
400         Element choiceEl = questionsEl.addElement("choice");
401 
402         choiceEl.addAttribute("path", path);
403 
404         context.addZipEntry(path, choice);
405     }
406 
407     protected static void exportVote(
408             PortletDataContext context, Element questionsEl, PollsVote vote)
409         throws SystemException {
410 
411         String path = getVotePath(context, vote);
412 
413         if (!context.isPathNotProcessed(path)) {
414             return;
415         }
416 
417         Element voteEl = questionsEl.addElement("vote");
418 
419         voteEl.addAttribute("path", path);
420 
421         context.addZipEntry(path, vote);
422     }
423 
424     protected static String getChoicePath(
425         PortletDataContext context, PollsChoice choice) {
426 
427         StringBundler sb = new StringBundler(6);
428 
429         sb.append(context.getPortletPath(PortletKeys.POLLS));
430         sb.append("/questions/");
431         sb.append(choice.getQuestionId());
432         sb.append("/choices/");
433         sb.append(choice.getChoiceId());
434         sb.append(".xml");
435 
436         return sb.toString();
437     }
438 
439     protected static String getQuestionPath(
440         PortletDataContext context, PollsQuestion question) {
441 
442         StringBundler sb = new StringBundler(4);
443 
444         sb.append(context.getPortletPath(PortletKeys.POLLS));
445         sb.append("/questions/");
446         sb.append(question.getQuestionId());
447         sb.append(".xml");
448 
449         return sb.toString();
450     }
451 
452     protected static String getVotePath(
453         PortletDataContext context, PollsVote vote) {
454 
455         StringBundler sb = new StringBundler(6);
456 
457         sb.append(context.getPortletPath(PortletKeys.POLLS));
458         sb.append("/questions/");
459         sb.append(vote.getQuestionId());
460         sb.append("/votes/");
461         sb.append(vote.getVoteId());
462         sb.append(".xml");
463 
464         return sb.toString();
465     }
466 
467     private static final boolean _ALWAYS_EXPORTABLE = true;
468 
469     private static final String _NAMESPACE = "polls";
470 
471     private static final PortletDataHandlerBoolean _questions =
472         new PortletDataHandlerBoolean(_NAMESPACE, "questions", true, true);
473 
474     private static final PortletDataHandlerBoolean _votes =
475         new PortletDataHandlerBoolean(_NAMESPACE, "votes");
476 
477     private static Log _log = LogFactoryUtil.getLog(
478         PollsPortletDataHandlerImpl.class);
479 
480 }