1   /**
2    * Copyright (c) 2000-2008 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.lar.PortletDataContext;
28  import com.liferay.portal.kernel.lar.PortletDataException;
29  import com.liferay.portal.kernel.lar.PortletDataHandler;
30  import com.liferay.portal.kernel.lar.PortletDataHandlerBoolean;
31  import com.liferay.portal.kernel.lar.PortletDataHandlerControl;
32  import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
33  import com.liferay.portal.kernel.util.CalendarFactoryUtil;
34  import com.liferay.portal.util.DocumentUtil;
35  import com.liferay.portal.util.PortletKeys;
36  import com.liferay.portlet.polls.DuplicateVoteException;
37  import com.liferay.portlet.polls.NoSuchChoiceException;
38  import com.liferay.portlet.polls.NoSuchQuestionException;
39  import com.liferay.portlet.polls.model.PollsChoice;
40  import com.liferay.portlet.polls.model.PollsQuestion;
41  import com.liferay.portlet.polls.model.PollsVote;
42  import com.liferay.portlet.polls.service.PollsChoiceLocalServiceUtil;
43  import com.liferay.portlet.polls.service.PollsQuestionLocalServiceUtil;
44  import com.liferay.portlet.polls.service.PollsVoteLocalServiceUtil;
45  import com.liferay.portlet.polls.service.persistence.PollsChoiceFinderUtil;
46  import com.liferay.portlet.polls.service.persistence.PollsChoiceUtil;
47  import com.liferay.portlet.polls.service.persistence.PollsQuestionUtil;
48  import com.liferay.portlet.polls.service.persistence.PollsVoteUtil;
49  import com.liferay.util.MapUtil;
50  import com.liferay.util.xml.XMLFormatter;
51  
52  import java.util.Calendar;
53  import java.util.Date;
54  import java.util.List;
55  import java.util.Map;
56  
57  import javax.portlet.PortletPreferences;
58  
59  import org.apache.commons.logging.Log;
60  import org.apache.commons.logging.LogFactory;
61  
62  import org.dom4j.Document;
63  import org.dom4j.DocumentHelper;
64  import org.dom4j.Element;
65  
66  /**
67   * <a href="PollsPortletDataHandlerImpl.java.html"><b><i>View Source</i></b></a>
68   *
69   * @author Bruno Farache
70   *
71   */
72  public class PollsPortletDataHandlerImpl implements PortletDataHandler {
73  
74      public PortletPreferences deleteData(
75              PortletDataContext context, String portletId,
76              PortletPreferences prefs)
77          throws PortletDataException {
78  
79          try {
80              if (!context.addPrimaryKey(
81                      PollsPortletDataHandlerImpl.class, "deleteData")) {
82  
83                  PollsQuestionLocalServiceUtil.deleteQuestions(
84                      context.getGroupId());
85              }
86  
87              return null;
88          }
89          catch (Exception e) {
90              throw new PortletDataException(e);
91          }
92      }
93  
94      public String exportData(
95              PortletDataContext context, String portletId,
96              PortletPreferences prefs)
97          throws PortletDataException {
98  
99          try {
100             Document doc = DocumentHelper.createDocument();
101 
102             Element root = doc.addElement("polls-data");
103 
104             root.addAttribute("group-id", String.valueOf(context.getGroupId()));
105 
106             Element questionsEl = root.addElement("questions");
107             Element choicesEl = root.addElement("choices");
108             Element votesEl = root.addElement("votes");
109 
110             List<PollsQuestion> questions = PollsQuestionUtil.findByGroupId(
111                 context.getGroupId());
112 
113             for (PollsQuestion question : questions) {
114                 exportQuestion(
115                     context, questionsEl, choicesEl, votesEl, question);
116             }
117 
118             return XMLFormatter.toString(doc);
119         }
120         catch (Exception e) {
121             throw new PortletDataException(e);
122         }
123     }
124 
125     public PortletDataHandlerControl[] getExportControls() {
126         return new PortletDataHandlerControl[] {_questions, _votes};
127     }
128 
129     public PortletDataHandlerControl[] getImportControls() {
130         return new PortletDataHandlerControl[] {_questions, _votes};
131     }
132 
133     public PortletPreferences importData(
134             PortletDataContext context, String portletId,
135             PortletPreferences prefs, String data)
136         throws PortletDataException {
137 
138         try {
139             Document doc = DocumentUtil.readDocumentFromXML(data);
140 
141             Element root = doc.getRootElement();
142 
143             List<Element> questionEls = root.element("questions").elements(
144                 "question");
145 
146             Map<Long, Long> questionPKs = context.getNewPrimaryKeysMap(
147                 PollsQuestion.class);
148 
149             for (Element questionEl : questionEls) {
150                 String path = questionEl.attributeValue("path");
151 
152                 if (context.isPathNotProcessed(path)) {
153                     PollsQuestion question =
154                         (PollsQuestion)context.getZipEntryAsObject(path);
155 
156                     importQuestion(context, questionPKs, question);
157                 }
158             }
159 
160             List<Element> choiceEls = root.element("choices").elements(
161                 "choice");
162 
163             Map<Long, Long> choicePKs = context.getNewPrimaryKeysMap(
164                 PollsChoice.class);
165 
166             for (Element choiceEl : choiceEls) {
167                 String path = choiceEl.attributeValue("path");
168 
169                 if (context.isPathNotProcessed(path)) {
170                     PollsChoice choice =
171                         (PollsChoice)context.getZipEntryAsObject(path);
172 
173                     importChoice(context, questionPKs, choicePKs, choice);
174                 }
175             }
176 
177             if (context.getBooleanParameter(_NAMESPACE, "votes")) {
178                 List<Element> voteEls = root.element("votes").elements("vote");
179 
180                 for (Element voteEl : voteEls) {
181                     String path = voteEl.attributeValue("path");
182 
183                     if (context.isPathNotProcessed(path)) {
184                         PollsVote vote = (PollsVote)context.getZipEntryAsObject(
185                             path);
186 
187                         importVote(context, questionPKs, choicePKs, vote);
188                     }
189                 }
190             }
191 
192             return null;
193         }
194         catch (Exception e) {
195             throw new PortletDataException(e);
196         }
197     }
198 
199     public boolean isPublishToLiveByDefault() {
200         return false;
201     }
202 
203     protected void exportChoice(
204             PortletDataContext context, Element questionsEl, PollsChoice choice)
205         throws SystemException {
206 
207         String path = getChoicePath(context, choice);
208 
209         Element choiceEl = questionsEl.addElement("choice");
210 
211         choiceEl.addAttribute("path", path);
212 
213         if (context.isPathNotProcessed(path)) {
214             context.addZipEntry(path, choice);
215         }
216     }
217 
218     protected void exportQuestion(
219             PortletDataContext context, Element questionsEl, Element choicesEl,
220             Element votesEl, PollsQuestion question)
221         throws SystemException {
222 
223         if (!context.isWithinDateRange(question.getModifiedDate())) {
224             return;
225         }
226 
227         String path = getQuestionPath(context, question);
228 
229         Element questionEl = questionsEl.addElement("question");
230 
231         questionEl.addAttribute("path", path);
232 
233         if (context.isPathNotProcessed(path)) {
234             question.setUserUuid(question.getUserUuid());
235 
236             List<PollsChoice> choices = PollsChoiceUtil.findByQuestionId(
237                 question.getQuestionId());
238 
239             for (PollsChoice choice : choices) {
240                 exportChoice(context, choicesEl, choice);
241             }
242 
243             if (context.getBooleanParameter(_NAMESPACE, "votes")) {
244                 List<PollsVote> votes = PollsVoteUtil.findByQuestionId(
245                     question.getQuestionId());
246 
247                 for (PollsVote vote : votes) {
248                     exportVote(context, votesEl, vote);
249                 }
250             }
251 
252             context.addZipEntry(path, question);
253         }
254     }
255 
256     protected void exportVote(
257             PortletDataContext context, Element questionsEl, PollsVote vote)
258         throws SystemException {
259 
260         String path = getVotePath(context, vote);
261 
262         Element voteEl = questionsEl.addElement("vote");
263 
264         voteEl.addAttribute("path", path);
265 
266         if (context.isPathNotProcessed(path)) {
267             context.addZipEntry(path, vote);
268         }
269     }
270 
271     protected void importChoice(
272             PortletDataContext context, Map<Long, Long> questionPKs,
273             Map<Long, Long> choicePKs, PollsChoice choice)
274         throws Exception {
275 
276         long questionId = MapUtil.getLong(
277             questionPKs, choice.getQuestionId(), choice.getQuestionId());
278 
279         PollsChoice existingChoice = null;
280 
281         try {
282             PollsQuestionUtil.findByPrimaryKey(questionId);
283 
284             if (context.getDataStrategy().equals(
285                     PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
286 
287                 try {
288                     existingChoice = PollsChoiceFinderUtil.findByUuid_G(
289                         choice.getUuid(), context.getGroupId());
290 
291                     existingChoice = PollsChoiceLocalServiceUtil.updateChoice(
292                         existingChoice.getChoiceId(), questionId,
293                         choice.getName(), choice.getDescription());
294                 }
295                 catch (NoSuchChoiceException nsce) {
296                     existingChoice = PollsChoiceLocalServiceUtil.addChoice(
297                         choice.getUuid(), questionId, choice.getName(),
298                         choice.getDescription());
299                 }
300             }
301             else {
302                 existingChoice = PollsChoiceLocalServiceUtil.addChoice(
303                     questionId, choice.getName(), choice.getDescription());
304             }
305 
306             choicePKs.put(choice.getChoiceId(), existingChoice.getChoiceId());
307         }
308         catch (NoSuchQuestionException nsqe) {
309             _log.error(
310                 "Could not find the question for choice " +
311                     choice.getChoiceId());
312         }
313     }
314 
315     protected void importQuestion(
316             PortletDataContext context, Map<Long, Long> questionPKs,
317             PollsQuestion question)
318         throws SystemException, PortalException {
319 
320         long userId = context.getUserId(question.getUserUuid());
321         long plid = context.getPlid();
322 
323         Date expirationDate = question.getExpirationDate();
324 
325         int expirationMonth = 0;
326         int expirationDay = 0;
327         int expirationYear = 0;
328         int expirationHour = 0;
329         int expirationMinute = 0;
330         boolean neverExpire = true;
331 
332         if (expirationDate != null) {
333             Calendar expirationCal = CalendarFactoryUtil.getCalendar();
334 
335             expirationCal.setTime(expirationDate);
336 
337             expirationMonth = expirationCal.get(Calendar.MONTH);
338             expirationDay = expirationCal.get(Calendar.DATE);
339             expirationYear = expirationCal.get(Calendar.YEAR);
340             expirationHour = expirationCal.get(Calendar.HOUR);
341             expirationMinute = expirationCal.get(Calendar.MINUTE);
342             neverExpire = false;
343 
344             if (expirationCal.get(Calendar.AM_PM) == Calendar.PM) {
345                 expirationHour += 12;
346             }
347         }
348 
349         boolean addCommunityPermissions = true;
350         boolean addGuestPermissions = true;
351 
352         PollsQuestion existingQuestion = null;
353 
354         if (context.getDataStrategy().equals(
355                 PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
356 
357             existingQuestion =  PollsQuestionUtil.fetchByUUID_G(
358                 question.getUuid(), context.getGroupId());
359 
360             if (existingQuestion == null) {
361                 existingQuestion = PollsQuestionLocalServiceUtil.addQuestion(
362                     question.getUuid(), userId, plid, question.getTitle(),
363                     question.getDescription(), expirationMonth, expirationDay,
364                     expirationYear, expirationHour, expirationMinute,
365                     neverExpire, addCommunityPermissions, addGuestPermissions);
366             }
367             else {
368                 existingQuestion = PollsQuestionLocalServiceUtil.updateQuestion(
369                     userId, existingQuestion.getQuestionId(),
370                     question.getTitle(), question.getDescription(),
371                     expirationMonth, expirationDay, expirationYear,
372                     expirationHour, expirationMinute, neverExpire);
373             }
374         }
375         else {
376             existingQuestion = PollsQuestionLocalServiceUtil.addQuestion(
377                 userId, plid, question.getTitle(), question.getDescription(),
378                 expirationMonth, expirationDay, expirationYear, expirationHour,
379                 expirationMinute, neverExpire, addCommunityPermissions,
380                 addGuestPermissions);
381         }
382 
383         questionPKs.put(
384             question.getQuestionId(), existingQuestion.getQuestionId());
385     }
386 
387     protected void importVote(
388             PortletDataContext context, Map<Long, Long> questionPKs,
389             Map<Long, Long> choicePKs, PollsVote vote)
390         throws Exception {
391 
392         long userId = context.getUserId(vote.getUserUuid());
393         long questionId = MapUtil.getLong(
394             questionPKs, vote.getQuestionId(), vote.getQuestionId());
395         long choiceId = MapUtil.getLong(
396             choicePKs, vote.getChoiceId(), vote.getChoiceId());
397 
398         try {
399             PollsQuestionUtil.findByPrimaryKey(questionId);
400             PollsChoiceUtil.findByPrimaryKey(choiceId);
401 
402             PollsVoteLocalServiceUtil.addVote(
403                 userId, questionId, choiceId);
404         }
405         catch (DuplicateVoteException dve) {
406         }
407         catch (NoSuchQuestionException nsqe) {
408             _log.error(
409                 "Could not find the question for vote " + vote.getVoteId());
410         }
411         catch (NoSuchChoiceException nsve) {
412             _log.error(
413                 "Could not find the choice for vote " + vote.getVoteId());
414         }
415     }
416 
417     protected String getChoicePath(
418         PortletDataContext context, PollsChoice choice) {
419 
420         StringBuilder sb = new StringBuilder();
421 
422         sb.append(context.getPortletPath(PortletKeys.POLLS));
423         sb.append("/questions/");
424         sb.append(choice.getQuestionId());
425         sb.append("/choices/");
426         sb.append(choice.getChoiceId());
427         sb.append(".xml");
428 
429         return sb.toString();
430     }
431 
432     protected String getQuestionPath(
433         PortletDataContext context, PollsQuestion question) {
434 
435         StringBuilder sb = new StringBuilder();
436 
437         sb.append(context.getPortletPath(PortletKeys.POLLS));
438         sb.append("/questions/");
439         sb.append(question.getQuestionId());
440         sb.append(".xml");
441 
442         return sb.toString();
443     }
444 
445     protected String getVotePath(PortletDataContext context, PollsVote vote) {
446         StringBuilder sb = new StringBuilder();
447 
448         sb.append(context.getPortletPath(PortletKeys.POLLS));
449         sb.append("/questions/");
450         sb.append(vote.getQuestionId());
451         sb.append("/votes/");
452         sb.append(vote.getVoteId());
453         sb.append(".xml");
454 
455         return sb.toString();
456     }
457 
458     private static final String _NAMESPACE = "polls";
459 
460     private static final PortletDataHandlerBoolean _questions =
461         new PortletDataHandlerBoolean(_NAMESPACE, "questions", true, true);
462 
463     private static final PortletDataHandlerBoolean _votes =
464         new PortletDataHandlerBoolean(_NAMESPACE, "votes");
465 
466     private static Log _log =
467         LogFactory.getLog(PollsPortletDataHandlerImpl.class);
468 
469 }