001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.polls.lar;
016    
017    import com.liferay.portal.kernel.lar.BasePortletDataHandler;
018    import com.liferay.portal.kernel.lar.PortletDataContext;
019    import com.liferay.portal.kernel.lar.PortletDataHandlerBoolean;
020    import com.liferay.portal.kernel.lar.PortletDataHandlerControl;
021    import com.liferay.portal.kernel.util.CalendarFactoryUtil;
022    import com.liferay.portal.kernel.util.MapUtil;
023    import com.liferay.portal.kernel.util.StringBundler;
024    import com.liferay.portal.kernel.xml.Document;
025    import com.liferay.portal.kernel.xml.Element;
026    import com.liferay.portal.kernel.xml.SAXReaderUtil;
027    import com.liferay.portal.service.ServiceContext;
028    import com.liferay.portal.util.PortletKeys;
029    import com.liferay.portlet.polls.DuplicateVoteException;
030    import com.liferay.portlet.polls.model.PollsChoice;
031    import com.liferay.portlet.polls.model.PollsQuestion;
032    import com.liferay.portlet.polls.model.PollsVote;
033    import com.liferay.portlet.polls.service.PollsChoiceLocalServiceUtil;
034    import com.liferay.portlet.polls.service.PollsQuestionLocalServiceUtil;
035    import com.liferay.portlet.polls.service.PollsVoteLocalServiceUtil;
036    import com.liferay.portlet.polls.service.persistence.PollsChoiceFinderUtil;
037    import com.liferay.portlet.polls.service.persistence.PollsChoiceUtil;
038    import com.liferay.portlet.polls.service.persistence.PollsQuestionUtil;
039    import com.liferay.portlet.polls.service.persistence.PollsVoteUtil;
040    
041    import java.util.Calendar;
042    import java.util.Date;
043    import java.util.List;
044    import java.util.Map;
045    
046    import javax.portlet.PortletPreferences;
047    
048    /**
049     * @author Bruno Farache
050     * @author Marcellus Tavares
051     */
052    public class PollsPortletDataHandlerImpl extends BasePortletDataHandler {
053    
054            @Override
055            public PortletDataHandlerControl[] getExportControls() {
056                    return new PortletDataHandlerControl[] {_questions, _votes};
057            }
058    
059            @Override
060            public PortletDataHandlerControl[] getImportControls() {
061                    return new PortletDataHandlerControl[] {_questions, _votes};
062            }
063    
064            @Override
065            public boolean isAlwaysExportable() {
066                    return _ALWAYS_EXPORTABLE;
067            }
068    
069            protected static void exportChoice(
070                            PortletDataContext portletDataContext, Element questionsElement,
071                            PollsChoice choice)
072                    throws Exception {
073    
074                    String path = getChoicePath(portletDataContext, choice);
075    
076                    if (!portletDataContext.isPathNotProcessed(path)) {
077                            return;
078                    }
079    
080                    Element choiceElement = questionsElement.addElement("choice");
081    
082                    portletDataContext.addClassedModel(
083                            choiceElement, path, choice, _NAMESPACE);
084            }
085    
086            protected static void exportQuestion(
087                            PortletDataContext portletDataContext, Element questionsElement,
088                            Element choicesElement, Element votesElement,
089                            PollsQuestion question)
090                    throws Exception {
091    
092                    if (!portletDataContext.isWithinDateRange(question.getModifiedDate())) {
093                            return;
094                    }
095    
096                    String path = getQuestionPath(portletDataContext, question);
097    
098                    if (!portletDataContext.isPathNotProcessed(path)) {
099                            return;
100                    }
101    
102                    Element questionElement = questionsElement.addElement("question");
103    
104                    List<PollsChoice> choices = PollsChoiceUtil.findByQuestionId(
105                            question.getQuestionId());
106    
107                    for (PollsChoice choice : choices) {
108                            exportChoice(portletDataContext, choicesElement, choice);
109                    }
110    
111                    if (portletDataContext.getBooleanParameter(_NAMESPACE, "votes")) {
112                            List<PollsVote> votes = PollsVoteUtil.findByQuestionId(
113                                    question.getQuestionId());
114    
115                            for (PollsVote vote : votes) {
116                                    exportVote(portletDataContext, votesElement, vote);
117                            }
118                    }
119    
120                    portletDataContext.addClassedModel(
121                            questionElement, path, question, _NAMESPACE);
122            }
123    
124            protected static void exportVote(
125                            PortletDataContext portletDataContext, Element questionsElement,
126                            PollsVote vote)
127                    throws Exception {
128    
129                    String path = getVotePath(portletDataContext, vote);
130    
131                    if (!portletDataContext.isPathNotProcessed(path)) {
132                            return;
133                    }
134    
135                    Element voteElement = questionsElement.addElement("vote");
136    
137                    portletDataContext.addClassedModel(voteElement, path, vote, _NAMESPACE);
138            }
139    
140            protected static String getChoicePath(
141                    PortletDataContext portletDataContext, PollsChoice choice) {
142    
143                    StringBundler sb = new StringBundler(6);
144    
145                    sb.append(portletDataContext.getPortletPath(PortletKeys.POLLS));
146                    sb.append("/questions/");
147                    sb.append(choice.getQuestionId());
148                    sb.append("/choices/");
149                    sb.append(choice.getChoiceId());
150                    sb.append(".xml");
151    
152                    return sb.toString();
153            }
154    
155            protected static String getQuestionPath(
156                    PortletDataContext portletDataContext, PollsQuestion question) {
157    
158                    StringBundler sb = new StringBundler(4);
159    
160                    sb.append(portletDataContext.getPortletPath(PortletKeys.POLLS));
161                    sb.append("/questions/");
162                    sb.append(question.getQuestionId());
163                    sb.append(".xml");
164    
165                    return sb.toString();
166            }
167    
168            protected static String getVotePath(
169                    PortletDataContext portletDataContext, PollsVote vote) {
170    
171                    StringBundler sb = new StringBundler(6);
172    
173                    sb.append(portletDataContext.getPortletPath(PortletKeys.POLLS));
174                    sb.append("/questions/");
175                    sb.append(vote.getQuestionId());
176                    sb.append("/votes/");
177                    sb.append(vote.getVoteId());
178                    sb.append(".xml");
179    
180                    return sb.toString();
181            }
182    
183            protected static void importChoice(
184                            PortletDataContext portletDataContext, PollsChoice choice)
185                    throws Exception {
186    
187                    Map<Long, Long> questionPKs =
188                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
189                                    PollsQuestion.class);
190    
191                    long questionId = MapUtil.getLong(
192                            questionPKs, choice.getQuestionId(), choice.getQuestionId());
193    
194                    PollsChoice importedChoice = null;
195    
196                    if (portletDataContext.isDataStrategyMirror()) {
197                            PollsChoice existingChoice = PollsChoiceFinderUtil.fetchByUUID_G(
198                                    choice.getUuid(), portletDataContext.getScopeGroupId());
199    
200                            if (existingChoice == null) {
201                                    ServiceContext serviceContext = new ServiceContext();
202    
203                                    serviceContext.setUuid(choice.getUuid());
204    
205                                    importedChoice = PollsChoiceLocalServiceUtil.addChoice(
206                                            questionId, choice.getName(), choice.getDescription(),
207                                            serviceContext);
208                            }
209                            else {
210                                    importedChoice = PollsChoiceLocalServiceUtil.updateChoice(
211                                            existingChoice.getChoiceId(), questionId, choice.getName(),
212                                            choice.getDescription());
213                            }
214                    }
215                    else {
216                            importedChoice = PollsChoiceLocalServiceUtil.addChoice(
217                                    questionId, choice.getName(), choice.getDescription(),
218                                    new ServiceContext());
219                    }
220    
221                    portletDataContext.importClassedModel(
222                            choice, importedChoice, _NAMESPACE);
223            }
224    
225            protected static void importQuestion(
226                            PortletDataContext portletDataContext, Element questionElement,
227                            PollsQuestion question)
228                    throws Exception {
229    
230                    long userId = portletDataContext.getUserId(question.getUserUuid());
231    
232                    Date expirationDate = question.getExpirationDate();
233    
234                    int expirationMonth = 0;
235                    int expirationDay = 0;
236                    int expirationYear = 0;
237                    int expirationHour = 0;
238                    int expirationMinute = 0;
239                    boolean neverExpire = true;
240    
241                    if (expirationDate != null) {
242                            Calendar expirationCal = CalendarFactoryUtil.getCalendar();
243    
244                            expirationCal.setTime(expirationDate);
245    
246                            expirationMonth = expirationCal.get(Calendar.MONTH);
247                            expirationDay = expirationCal.get(Calendar.DATE);
248                            expirationYear = expirationCal.get(Calendar.YEAR);
249                            expirationHour = expirationCal.get(Calendar.HOUR);
250                            expirationMinute = expirationCal.get(Calendar.MINUTE);
251                            neverExpire = false;
252    
253                            if (expirationCal.get(Calendar.AM_PM) == Calendar.PM) {
254                                    expirationHour += 12;
255                            }
256                    }
257    
258                    ServiceContext serviceContext = portletDataContext.createServiceContext(
259                            questionElement, question, _NAMESPACE);
260    
261                    PollsQuestion importedQuestion = null;
262    
263                    if (portletDataContext.isDataStrategyMirror()) {
264                            PollsQuestion existingQuestion = PollsQuestionUtil.fetchByUUID_G(
265                                    question.getUuid(), portletDataContext.getScopeGroupId());
266    
267                            if (existingQuestion == null) {
268                                    serviceContext.setUuid(question.getUuid());
269    
270                                    importedQuestion = PollsQuestionLocalServiceUtil.addQuestion(
271                                            userId, question.getTitleMap(),
272                                            question.getDescriptionMap(), expirationMonth,
273                                            expirationDay, expirationYear, expirationHour,
274                                            expirationMinute, neverExpire, null, serviceContext);
275                            }
276                            else {
277                                    importedQuestion = PollsQuestionLocalServiceUtil.updateQuestion(
278                                            userId, existingQuestion.getQuestionId(),
279                                            question.getTitleMap(), question.getDescriptionMap(),
280                                            expirationMonth, expirationDay, expirationYear,
281                                            expirationHour, expirationMinute, neverExpire, null,
282                                            serviceContext);
283                            }
284                    }
285                    else {
286                            importedQuestion = PollsQuestionLocalServiceUtil.addQuestion(
287                                    userId, question.getTitleMap(), question.getDescriptionMap(),
288                                    expirationMonth, expirationDay, expirationYear, expirationHour,
289                                    expirationMinute, neverExpire, null, serviceContext);
290                    }
291    
292                    portletDataContext.importClassedModel(
293                            question, importedQuestion, _NAMESPACE);
294            }
295    
296            protected static void importVote(
297                            PortletDataContext portletDataContext, PollsVote vote)
298                    throws Exception {
299    
300                    long userId = portletDataContext.getUserId(vote.getUserUuid());
301    
302                    Map<Long, Long> questionPKs =
303                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
304                                    PollsQuestion.class);
305    
306                    long questionId = MapUtil.getLong(
307                            questionPKs, vote.getQuestionId(), vote.getQuestionId());
308    
309                    Map<Long, Long> choicePKs =
310                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
311                                    PollsChoice.class);
312    
313                    long choiceId = MapUtil.getLong(
314                            choicePKs, vote.getChoiceId(), vote.getChoiceId());
315    
316                    ServiceContext serviceContext = new ServiceContext();
317    
318                    serviceContext.setCreateDate(vote.getVoteDate());
319    
320                    try {
321                            PollsVoteLocalServiceUtil.addVote(
322                                    userId, questionId, choiceId, serviceContext);
323                    }
324                    catch (DuplicateVoteException dve) {
325                    }
326            }
327    
328            @Override
329            protected PortletPreferences doDeleteData(
330                            PortletDataContext portletDataContext, String portletId,
331                            PortletPreferences portletPreferences)
332                    throws Exception {
333    
334                    if (!portletDataContext.addPrimaryKey(
335                                    PollsPortletDataHandlerImpl.class, "deleteData")) {
336    
337                            PollsQuestionLocalServiceUtil.deleteQuestions(
338                                    portletDataContext.getScopeGroupId());
339                    }
340    
341                    return null;
342            }
343    
344            @Override
345            protected String doExportData(
346                            PortletDataContext portletDataContext, String portletId,
347                            PortletPreferences portletPreferences)
348                    throws Exception {
349    
350                    portletDataContext.addPermissions(
351                            "com.liferay.portlet.polls", portletDataContext.getScopeGroupId());
352    
353                    Document document = SAXReaderUtil.createDocument();
354    
355                    Element rootElement = document.addElement("polls-data");
356    
357                    rootElement.addAttribute(
358                            "group-id", String.valueOf(portletDataContext.getScopeGroupId()));
359    
360                    Element questionsElement = rootElement.addElement("questions");
361                    Element choicesElement = rootElement.addElement("choices");
362                    Element votesElement = rootElement.addElement("votes");
363    
364                    List<PollsQuestion> questions = PollsQuestionUtil.findByGroupId(
365                            portletDataContext.getScopeGroupId());
366    
367                    for (PollsQuestion question : questions) {
368                            exportQuestion(
369                                    portletDataContext, questionsElement, choicesElement,
370                                    votesElement, question);
371                    }
372    
373                    return document.formattedString();
374            }
375    
376            @Override
377            protected PortletPreferences doImportData(
378                            PortletDataContext portletDataContext, String portletId,
379                            PortletPreferences portletPreferences, String data)
380                    throws Exception {
381    
382                    portletDataContext.importPermissions(
383                            "com.liferay.portlet.polls", portletDataContext.getSourceGroupId(),
384                            portletDataContext.getScopeGroupId());
385    
386                    Document document = SAXReaderUtil.read(data);
387    
388                    Element rootElement = document.getRootElement();
389    
390                    Element questionsElement = rootElement.element("questions");
391    
392                    for (Element questionElement : questionsElement.elements("question")) {
393                            String path = questionElement.attributeValue("path");
394    
395                            if (!portletDataContext.isPathNotProcessed(path)) {
396                                    continue;
397                            }
398    
399                            PollsQuestion question =
400                                    (PollsQuestion)portletDataContext.getZipEntryAsObject(path);
401    
402                            importQuestion(portletDataContext, questionElement, question);
403                    }
404    
405                    Element choicesElement = rootElement.element("choices");
406    
407                    for (Element choiceElement : choicesElement.elements("choice")) {
408                            String path = choiceElement.attributeValue("path");
409    
410                            if (!portletDataContext.isPathNotProcessed(path)) {
411                                    continue;
412                            }
413    
414                            PollsChoice choice =
415                                    (PollsChoice)portletDataContext.getZipEntryAsObject(path);
416    
417                            importChoice(portletDataContext, choice);
418                    }
419    
420                    if (portletDataContext.getBooleanParameter(_NAMESPACE, "votes")) {
421                            Element votesElement = rootElement.element("votes");
422    
423                            for (Element voteElement : votesElement.elements("vote")) {
424                                    String path = voteElement.attributeValue("path");
425    
426                                    if (!portletDataContext.isPathNotProcessed(path)) {
427                                            continue;
428                                    }
429    
430                                    PollsVote vote =
431                                            (PollsVote)portletDataContext.getZipEntryAsObject(path);
432    
433                                    importVote(portletDataContext, vote);
434                            }
435                    }
436    
437                    return null;
438            }
439    
440            private static final boolean _ALWAYS_EXPORTABLE = true;
441    
442            private static final String _NAMESPACE = "polls";
443    
444            private static PortletDataHandlerBoolean _questions =
445                    new PortletDataHandlerBoolean(_NAMESPACE, "questions", true, true);
446    
447            private static PortletDataHandlerBoolean _votes =
448                    new PortletDataHandlerBoolean(_NAMESPACE, "votes");
449    
450    }