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