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