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