001    /**
002     * Copyright (c) 2000-2013 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            @Override
070            public boolean isDataLocalized() {
071                    return _DATA_LOCALIZED;
072            }
073    
074            protected static void exportChoice(
075                            PortletDataContext portletDataContext, Element questionsElement,
076                            PollsChoice choice)
077                    throws Exception {
078    
079                    String path = getChoicePath(portletDataContext, choice);
080    
081                    if (!portletDataContext.isPathNotProcessed(path)) {
082                            return;
083                    }
084    
085                    Element choiceElement = questionsElement.addElement("choice");
086    
087                    portletDataContext.addClassedModel(
088                            choiceElement, path, choice, _NAMESPACE);
089            }
090    
091            protected static void exportQuestion(
092                            PortletDataContext portletDataContext, Element questionsElement,
093                            Element choicesElement, Element votesElement,
094                            PollsQuestion question)
095                    throws Exception {
096    
097                    if (!portletDataContext.isWithinDateRange(question.getModifiedDate())) {
098                            return;
099                    }
100    
101                    String path = getQuestionPath(portletDataContext, question);
102    
103                    if (!portletDataContext.isPathNotProcessed(path)) {
104                            return;
105                    }
106    
107                    Element questionElement = questionsElement.addElement("question");
108    
109                    List<PollsChoice> choices = PollsChoiceUtil.findByQuestionId(
110                            question.getQuestionId());
111    
112                    for (PollsChoice choice : choices) {
113                            exportChoice(portletDataContext, choicesElement, choice);
114                    }
115    
116                    if (portletDataContext.getBooleanParameter(_NAMESPACE, "votes")) {
117                            List<PollsVote> votes = PollsVoteUtil.findByQuestionId(
118                                    question.getQuestionId());
119    
120                            for (PollsVote vote : votes) {
121                                    exportVote(portletDataContext, votesElement, vote);
122                            }
123                    }
124    
125                    portletDataContext.addClassedModel(
126                            questionElement, path, question, _NAMESPACE);
127            }
128    
129            protected static void exportVote(
130                            PortletDataContext portletDataContext, Element questionsElement,
131                            PollsVote vote)
132                    throws Exception {
133    
134                    String path = getVotePath(portletDataContext, vote);
135    
136                    if (!portletDataContext.isPathNotProcessed(path)) {
137                            return;
138                    }
139    
140                    Element voteElement = questionsElement.addElement("vote");
141    
142                    portletDataContext.addClassedModel(voteElement, path, vote, _NAMESPACE);
143            }
144    
145            protected static String getChoicePath(
146                    PortletDataContext portletDataContext, PollsChoice choice) {
147    
148                    StringBundler sb = new StringBundler(6);
149    
150                    sb.append(portletDataContext.getPortletPath(PortletKeys.POLLS));
151                    sb.append("/questions/");
152                    sb.append(choice.getQuestionId());
153                    sb.append("/choices/");
154                    sb.append(choice.getChoiceId());
155                    sb.append(".xml");
156    
157                    return sb.toString();
158            }
159    
160            protected static String getQuestionPath(
161                    PortletDataContext portletDataContext, PollsQuestion question) {
162    
163                    StringBundler sb = new StringBundler(4);
164    
165                    sb.append(portletDataContext.getPortletPath(PortletKeys.POLLS));
166                    sb.append("/questions/");
167                    sb.append(question.getQuestionId());
168                    sb.append(".xml");
169    
170                    return sb.toString();
171            }
172    
173            protected static String getVotePath(
174                    PortletDataContext portletDataContext, PollsVote vote) {
175    
176                    StringBundler sb = new StringBundler(6);
177    
178                    sb.append(portletDataContext.getPortletPath(PortletKeys.POLLS));
179                    sb.append("/questions/");
180                    sb.append(vote.getQuestionId());
181                    sb.append("/votes/");
182                    sb.append(vote.getVoteId());
183                    sb.append(".xml");
184    
185                    return sb.toString();
186            }
187    
188            protected static void importChoice(
189                            PortletDataContext portletDataContext, PollsChoice choice)
190                    throws Exception {
191    
192                    Map<Long, Long> questionIds =
193                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
194                                    PollsQuestion.class);
195    
196                    long questionId = MapUtil.getLong(
197                            questionIds, choice.getQuestionId(), choice.getQuestionId());
198    
199                    PollsChoice importedChoice = null;
200    
201                    if (portletDataContext.isDataStrategyMirror()) {
202                            PollsChoice existingChoice = PollsChoiceFinderUtil.fetchByUUID_G(
203                                    choice.getUuid(), portletDataContext.getScopeGroupId());
204    
205                            if (existingChoice == null) {
206                                    ServiceContext serviceContext = new ServiceContext();
207    
208                                    serviceContext.setUuid(choice.getUuid());
209    
210                                    importedChoice = PollsChoiceLocalServiceUtil.addChoice(
211                                            questionId, choice.getName(), choice.getDescription(),
212                                            serviceContext);
213                            }
214                            else {
215                                    importedChoice = PollsChoiceLocalServiceUtil.updateChoice(
216                                            existingChoice.getChoiceId(), questionId, choice.getName(),
217                                            choice.getDescription());
218                            }
219                    }
220                    else {
221                            importedChoice = PollsChoiceLocalServiceUtil.addChoice(
222                                    questionId, choice.getName(), choice.getDescription(),
223                                    new ServiceContext());
224                    }
225    
226                    portletDataContext.importClassedModel(
227                            choice, importedChoice, _NAMESPACE);
228            }
229    
230            protected static void importQuestion(
231                            PortletDataContext portletDataContext, Element questionElement,
232                            PollsQuestion question)
233                    throws Exception {
234    
235                    long userId = portletDataContext.getUserId(question.getUserUuid());
236    
237                    Date expirationDate = question.getExpirationDate();
238    
239                    int expirationMonth = 0;
240                    int expirationDay = 0;
241                    int expirationYear = 0;
242                    int expirationHour = 0;
243                    int expirationMinute = 0;
244                    boolean neverExpire = true;
245    
246                    if (expirationDate != null) {
247                            Calendar expirationCal = CalendarFactoryUtil.getCalendar();
248    
249                            expirationCal.setTime(expirationDate);
250    
251                            expirationMonth = expirationCal.get(Calendar.MONTH);
252                            expirationDay = expirationCal.get(Calendar.DATE);
253                            expirationYear = expirationCal.get(Calendar.YEAR);
254                            expirationHour = expirationCal.get(Calendar.HOUR);
255                            expirationMinute = expirationCal.get(Calendar.MINUTE);
256                            neverExpire = false;
257    
258                            if (expirationCal.get(Calendar.AM_PM) == Calendar.PM) {
259                                    expirationHour += 12;
260                            }
261                    }
262    
263                    ServiceContext serviceContext = portletDataContext.createServiceContext(
264                            questionElement, question, _NAMESPACE);
265    
266                    PollsQuestion importedQuestion = null;
267    
268                    if (portletDataContext.isDataStrategyMirror()) {
269                            PollsQuestion existingQuestion = PollsQuestionUtil.fetchByUUID_G(
270                                    question.getUuid(), portletDataContext.getScopeGroupId());
271    
272                            if (existingQuestion == null) {
273                                    serviceContext.setUuid(question.getUuid());
274    
275                                    importedQuestion = PollsQuestionLocalServiceUtil.addQuestion(
276                                            userId, question.getTitleMap(),
277                                            question.getDescriptionMap(), expirationMonth,
278                                            expirationDay, expirationYear, expirationHour,
279                                            expirationMinute, neverExpire, null, serviceContext);
280                            }
281                            else {
282                                    importedQuestion = PollsQuestionLocalServiceUtil.updateQuestion(
283                                            userId, existingQuestion.getQuestionId(),
284                                            question.getTitleMap(), question.getDescriptionMap(),
285                                            expirationMonth, expirationDay, expirationYear,
286                                            expirationHour, expirationMinute, neverExpire, null,
287                                            serviceContext);
288                            }
289                    }
290                    else {
291                            importedQuestion = PollsQuestionLocalServiceUtil.addQuestion(
292                                    userId, question.getTitleMap(), question.getDescriptionMap(),
293                                    expirationMonth, expirationDay, expirationYear, expirationHour,
294                                    expirationMinute, neverExpire, null, serviceContext);
295                    }
296    
297                    portletDataContext.importClassedModel(
298                            question, importedQuestion, _NAMESPACE);
299            }
300    
301            protected static void importVote(
302                            PortletDataContext portletDataContext, PollsVote vote)
303                    throws Exception {
304    
305                    Map<Long, Long> questionIds =
306                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
307                                    PollsQuestion.class);
308    
309                    long questionId = MapUtil.getLong(
310                            questionIds, vote.getQuestionId(), vote.getQuestionId());
311    
312                    Map<Long, Long> choiceIds =
313                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
314                                    PollsChoice.class);
315    
316                    long choiceId = MapUtil.getLong(
317                            choiceIds, vote.getChoiceId(), vote.getChoiceId());
318    
319                    ServiceContext serviceContext = new ServiceContext();
320    
321                    serviceContext.setCreateDate(vote.getVoteDate());
322    
323                    try {
324                            PollsVoteLocalServiceUtil.addVote(
325                                    vote.getUserId(), questionId, choiceId, serviceContext);
326                    }
327                    catch (DuplicateVoteException dve) {
328                    }
329            }
330    
331            @Override
332            protected PortletPreferences doDeleteData(
333                            PortletDataContext portletDataContext, String portletId,
334                            PortletPreferences portletPreferences)
335                    throws Exception {
336    
337                    if (!portletDataContext.addPrimaryKey(
338                                    PollsPortletDataHandlerImpl.class, "deleteData")) {
339    
340                            PollsQuestionLocalServiceUtil.deleteQuestions(
341                                    portletDataContext.getScopeGroupId());
342                    }
343    
344                    return null;
345            }
346    
347            @Override
348            protected String doExportData(
349                            PortletDataContext portletDataContext, String portletId,
350                            PortletPreferences portletPreferences)
351                    throws Exception {
352    
353                    portletDataContext.addPermissions(
354                            "com.liferay.portlet.polls", portletDataContext.getScopeGroupId());
355    
356                    Document document = SAXReaderUtil.createDocument();
357    
358                    Element rootElement = document.addElement("polls-data");
359    
360                    rootElement.addAttribute(
361                            "group-id", String.valueOf(portletDataContext.getScopeGroupId()));
362    
363                    Element questionsElement = rootElement.addElement("questions");
364                    Element choicesElement = rootElement.addElement("choices");
365                    Element votesElement = rootElement.addElement("votes");
366    
367                    List<PollsQuestion> questions = PollsQuestionUtil.findByGroupId(
368                            portletDataContext.getScopeGroupId());
369    
370                    for (PollsQuestion question : questions) {
371                            exportQuestion(
372                                    portletDataContext, questionsElement, choicesElement,
373                                    votesElement, question);
374                    }
375    
376                    return document.formattedString();
377            }
378    
379            @Override
380            protected PortletPreferences doImportData(
381                            PortletDataContext portletDataContext, String portletId,
382                            PortletPreferences portletPreferences, String data)
383                    throws Exception {
384    
385                    portletDataContext.importPermissions(
386                            "com.liferay.portlet.polls", portletDataContext.getSourceGroupId(),
387                            portletDataContext.getScopeGroupId());
388    
389                    Document document = SAXReaderUtil.read(data);
390    
391                    Element rootElement = document.getRootElement();
392    
393                    Element questionsElement = rootElement.element("questions");
394    
395                    for (Element questionElement : questionsElement.elements("question")) {
396                            String path = questionElement.attributeValue("path");
397    
398                            if (!portletDataContext.isPathNotProcessed(path)) {
399                                    continue;
400                            }
401    
402                            PollsQuestion question =
403                                    (PollsQuestion)portletDataContext.getZipEntryAsObject(path);
404    
405                            importQuestion(portletDataContext, questionElement, question);
406                    }
407    
408                    Element choicesElement = rootElement.element("choices");
409    
410                    for (Element choiceElement : choicesElement.elements("choice")) {
411                            String path = choiceElement.attributeValue("path");
412    
413                            if (!portletDataContext.isPathNotProcessed(path)) {
414                                    continue;
415                            }
416    
417                            PollsChoice choice =
418                                    (PollsChoice)portletDataContext.getZipEntryAsObject(path);
419    
420                            importChoice(portletDataContext, choice);
421                    }
422    
423                    if (portletDataContext.getBooleanParameter(_NAMESPACE, "votes")) {
424                            Element votesElement = rootElement.element("votes");
425    
426                            for (Element voteElement : votesElement.elements("vote")) {
427                                    String path = voteElement.attributeValue("path");
428    
429                                    if (!portletDataContext.isPathNotProcessed(path)) {
430                                            continue;
431                                    }
432    
433                                    PollsVote vote =
434                                            (PollsVote)portletDataContext.getZipEntryAsObject(path);
435    
436                                    importVote(portletDataContext, vote);
437                            }
438                    }
439    
440                    return null;
441            }
442    
443            private static final boolean _ALWAYS_EXPORTABLE = true;
444    
445            private static final boolean _DATA_LOCALIZED = true;
446    
447            private static final String _NAMESPACE = "polls";
448    
449            private static PortletDataHandlerBoolean _questions =
450                    new PortletDataHandlerBoolean(_NAMESPACE, "questions", true, true);
451            private static PortletDataHandlerBoolean _votes =
452                    new PortletDataHandlerBoolean(_NAMESPACE, "votes");
453    
454    }