1   /**
2    * Copyright (c) 2000-2010 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   *
12   * 
13   */
14  
15  package com.liferay.portlet.journal.lar;
16  
17  import com.liferay.portal.NoSuchImageException;
18  import com.liferay.portal.PortalException;
19  import com.liferay.portal.SystemException;
20  import com.liferay.portal.kernel.dao.orm.QueryUtil;
21  import com.liferay.portal.kernel.log.Log;
22  import com.liferay.portal.kernel.log.LogFactoryUtil;
23  import com.liferay.portal.kernel.util.CalendarFactoryUtil;
24  import com.liferay.portal.kernel.util.FileUtil;
25  import com.liferay.portal.kernel.util.GetterUtil;
26  import com.liferay.portal.kernel.util.MapUtil;
27  import com.liferay.portal.kernel.util.StringBundler;
28  import com.liferay.portal.kernel.util.StringPool;
29  import com.liferay.portal.kernel.util.StringUtil;
30  import com.liferay.portal.kernel.util.Validator;
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.model.Image;
41  import com.liferay.portal.model.User;
42  import com.liferay.portal.service.ServiceContext;
43  import com.liferay.portal.service.UserLocalServiceUtil;
44  import com.liferay.portal.service.persistence.ImageUtil;
45  import com.liferay.portal.util.PortletKeys;
46  import com.liferay.portal.util.PropsValues;
47  import com.liferay.portlet.documentlibrary.lar.DLPortletDataHandlerImpl;
48  import com.liferay.portlet.documentlibrary.model.DLFileEntry;
49  import com.liferay.portlet.documentlibrary.model.DLFileRank;
50  import com.liferay.portlet.documentlibrary.model.DLFolder;
51  import com.liferay.portlet.documentlibrary.service.DLFileEntryLocalServiceUtil;
52  import com.liferay.portlet.imagegallery.lar.IGPortletDataHandlerImpl;
53  import com.liferay.portlet.imagegallery.model.IGFolder;
54  import com.liferay.portlet.imagegallery.model.IGImage;
55  import com.liferay.portlet.imagegallery.service.IGImageLocalServiceUtil;
56  import com.liferay.portlet.journal.model.JournalArticle;
57  import com.liferay.portlet.journal.model.JournalArticleImage;
58  import com.liferay.portlet.journal.model.JournalFeed;
59  import com.liferay.portlet.journal.model.JournalStructure;
60  import com.liferay.portlet.journal.model.JournalTemplate;
61  import com.liferay.portlet.journal.model.impl.JournalArticleImpl;
62  import com.liferay.portlet.journal.service.JournalArticleLocalServiceUtil;
63  import com.liferay.portlet.journal.service.JournalFeedLocalServiceUtil;
64  import com.liferay.portlet.journal.service.JournalStructureLocalServiceUtil;
65  import com.liferay.portlet.journal.service.JournalTemplateLocalServiceUtil;
66  import com.liferay.portlet.journal.service.persistence.JournalArticleImageUtil;
67  import com.liferay.portlet.journal.service.persistence.JournalArticleUtil;
68  import com.liferay.portlet.journal.service.persistence.JournalFeedUtil;
69  import com.liferay.portlet.journal.service.persistence.JournalStructureUtil;
70  import com.liferay.portlet.journal.service.persistence.JournalTemplateUtil;
71  import com.liferay.portlet.journal.util.comparator.ArticleIDComparator;
72  
73  import java.io.File;
74  
75  import java.util.Calendar;
76  import java.util.Date;
77  import java.util.HashMap;
78  import java.util.List;
79  import java.util.Map;
80  
81  import javax.portlet.PortletPreferences;
82  
83  /**
84   * <a href="JournalPortletDataHandlerImpl.java.html"><b><i>View Source</i></b>
85   * </a>
86   *
87   * <p>
88   * Provides the Journal portlet export and import functionality, which is to
89   * clone all articles, structures, and templates associated with the layout's
90   * group. Upon import, new instances of the corresponding articles, structures,
91   * and templates are created or updated according to the DATA_MIRROW strategy
92   * The author of the newly created objects are determined by the
93   * JournalCreationStrategy class defined in <i>portal.properties</i>. That
94   * strategy also allows the text of the journal article to be modified prior to
95   * import.
96   * </p>
97   *
98   * <p>
99   * This <code>PortletDataHandler</code> differs from
100  * <code>JournalContentPortletDataHandlerImpl</code> in that it exports all
101  * articles owned by the group whether or not they are actually displayed in a
102  * portlet in the layout set.
103  * </p>
104  *
105  * @author Raymond Augé
106  * @author Joel Kozikowski
107  * @author Brian Wing Shun Chan
108  * @author Bruno Farache
109  * @author Karthik Sudarshan
110  * @see    com.liferay.portal.lar.PortletDataHandler
111  * @see    com.liferay.portlet.journal.lar.JournalContentPortletDataHandlerImpl
112  * @see    com.liferay.portlet.journal.lar.JournalCreationStrategy
113  */
114 public class JournalPortletDataHandlerImpl extends BasePortletDataHandler {
115 
116     public static void exportArticle(
117             PortletDataContext context, Element articlesEl, Element dlFoldersEl,
118             Element dlFileEntriesEl, Element dlFileRanks, Element igFoldersEl,
119             Element igImagesEl, JournalArticle article)
120         throws PortalException, SystemException {
121 
122         if (!context.isWithinDateRange(article.getModifiedDate())) {
123             return;
124         }
125 
126         String path = getArticlePath(context, article);
127 
128         if (!context.isPathNotProcessed(path)) {
129             return;
130         }
131 
132         // Clone this article to make sure changes to its content are never
133         // persisted
134 
135         article = (JournalArticle)article.clone();
136 
137         Element articleEl = articlesEl.addElement("article");
138 
139         articleEl.addAttribute("path", path);
140 
141         Image smallImage = ImageUtil.fetchByPrimaryKey(
142             article.getSmallImageId());
143 
144         if (article.isSmallImage() && (smallImage != null)) {
145             String smallImagePath = getArticleSmallImagePath(context, article);
146 
147             articleEl.addAttribute("small-image-path", smallImagePath);
148 
149             article.setSmallImageType(smallImage.getType());
150 
151             context.addZipEntry(smallImagePath, smallImage.getTextObj());
152         }
153 
154         if (context.getBooleanParameter(_NAMESPACE, "images")) {
155             String imagePath = getArticleImagePath(context, article);
156 
157             articleEl.addAttribute("image-path", imagePath);
158 
159             List<JournalArticleImage> articleImages =
160                 JournalArticleImageUtil.findByG_A_V(
161                     article.getGroupId(), article.getArticleId(),
162                     article.getVersion());
163 
164             for (JournalArticleImage articleImage : articleImages) {
165                 try {
166                     Image image = ImageUtil.findByPrimaryKey(
167                         articleImage.getArticleImageId());
168 
169                     String articleImagePath = getArticleImagePath(
170                         context, article, articleImage, image);
171 
172                     if (!context.isPathNotProcessed(articleImagePath)) {
173                         continue;
174                     }
175 
176                     context.addZipEntry(articleImagePath, image.getTextObj());
177                 }
178                 catch (NoSuchImageException nsie) {
179                 }
180             }
181         }
182 
183         context.addPermissions(
184             JournalArticle.class, article.getResourcePrimKey());
185 
186         if (context.getBooleanParameter(_NAMESPACE, "categories")) {
187             context.addTagsCategories(
188                 JournalArticle.class, article.getResourcePrimKey());
189         }
190 
191         if (context.getBooleanParameter(_NAMESPACE, "comments")) {
192             context.addComments(
193                 JournalArticle.class, article.getResourcePrimKey());
194         }
195 
196         if (context.getBooleanParameter(_NAMESPACE, "ratings")) {
197             context.addRatingsEntries(
198                 JournalArticle.class, article.getResourcePrimKey());
199         }
200 
201         if (context.getBooleanParameter(_NAMESPACE, "tags")) {
202             context.addTagsEntries(
203                 JournalArticle.class, article.getResourcePrimKey());
204         }
205 
206         if (context.getBooleanParameter(_NAMESPACE, "embedded-assets")) {
207             String content = article.getContent();
208 
209             content = exportDLFileEntries(
210                 context, dlFoldersEl, dlFileEntriesEl, dlFileRanks,
211                 article.getGroupId(), content);
212             content = exportIGImages(context, igFoldersEl, igImagesEl,
213                 article.getGroupId(), content);
214 
215             article.setContent(content);
216         }
217 
218         article.setUserUuid(article.getUserUuid());
219         article.setApprovedByUserUuid(article.getApprovedByUserUuid());
220 
221         context.addZipEntry(path, article);
222     }
223 
224     public static void exportFeed(
225             PortletDataContext context, Element feedsEl, JournalFeed feed)
226         throws PortalException, SystemException {
227 
228         if (!context.isWithinDateRange(feed.getModifiedDate())) {
229             return;
230         }
231 
232         String path = getFeedPath(context, feed);
233 
234         if (!context.isPathNotProcessed(path)) {
235             return;
236         }
237 
238         Element feedEl = feedsEl.addElement("feed");
239 
240         feedEl.addAttribute("path", path);
241 
242         feed.setUserUuid(feed.getUserUuid());
243 
244         context.addPermissions(JournalFeed.class, feed.getId());
245 
246         context.addZipEntry(path, feed);
247     }
248 
249     public static String exportDLFileEntries(
250         PortletDataContext context, Element foldersEl, Element fileEntriesEl,
251         Element fileRanks, long entityGroupId, String content) {
252 
253         StringBuilder sb = new StringBuilder(content);
254 
255         int beginPos = content.length();
256 
257         while (true) {
258             beginPos = content.lastIndexOf("/get_file?", beginPos);
259 
260             if (beginPos == -1) {
261                 return sb.toString();
262             }
263 
264             int endPos1 = content.indexOf(StringPool.APOSTROPHE, beginPos);
265             int endPos2 = content.indexOf(StringPool.CLOSE_BRACKET, beginPos);
266             int endPos3 = content.indexOf(
267                 StringPool.CLOSE_PARENTHESIS, beginPos);
268             int endPos4 = content.indexOf(StringPool.LESS_THAN, beginPos);
269             int endPos5 = content.indexOf(StringPool.QUOTE, beginPos);
270             int endPos6 = content.indexOf(StringPool.SPACE, beginPos);
271 
272             int endPos = endPos1;
273 
274             if ((endPos == -1) || ((endPos2 != -1) && (endPos2 < endPos))) {
275                 endPos = endPos2;
276             }
277 
278             if ((endPos == -1) || ((endPos3 != -1) && (endPos3 < endPos))) {
279                 endPos = endPos3;
280             }
281 
282             if ((endPos == -1) || ((endPos4 != -1) && (endPos4 < endPos))) {
283                 endPos = endPos4;
284             }
285 
286             if ((endPos == -1) || ((endPos5 != -1) && (endPos5 < endPos))) {
287                 endPos = endPos5;
288             }
289 
290             if ((endPos == -1) || ((endPos6 != -1) && (endPos6 < endPos))) {
291                 endPos = endPos6;
292             }
293 
294             if ((beginPos == -1) || (endPos == -1)) {
295                 break;
296             }
297 
298             try {
299                 String oldParameters = content.substring(beginPos, endPos);
300 
301                 oldParameters = oldParameters.substring(
302                     oldParameters.indexOf(StringPool.QUESTION) + 1);
303 
304                 boolean hasEncodedAmpersands = false;
305 
306                 while (oldParameters.contains(StringPool.AMPERSAND_ENCODED)) {
307                     hasEncodedAmpersands = true;
308 
309                     oldParameters = oldParameters.replace(
310                         StringPool.AMPERSAND_ENCODED, StringPool.AMPERSAND);
311                 }
312 
313                 Map<String, String> map = MapUtil.toLinkedHashMap(
314                     oldParameters.split(StringPool.AMPERSAND),
315                     StringPool.EQUAL);
316 
317                 DLFileEntry fileEntry = null;
318 
319                 if (map.containsKey("uuid")) {
320                     String uuid = map.get("uuid");
321 
322                     String groupIdString = map.get("groupId");
323 
324                     long groupId = GetterUtil.getLong(groupIdString);
325 
326                     if (groupIdString.equals("@group_id@")) {
327                         groupId = entityGroupId;
328                     }
329 
330                     fileEntry = DLFileEntryLocalServiceUtil.
331                         getFileEntryByUuidAndGroupId(uuid, groupId);
332                 }
333                 else if (map.containsKey("folderId")) {
334                     long folderId = GetterUtil.getLong(map.get("folderId"));
335                     String name = map.get("name");
336 
337                     fileEntry = DLFileEntryLocalServiceUtil.getFileEntry(
338                         folderId, name);
339                 }
340 
341                 if (fileEntry == null) {
342                     beginPos--;
343 
344                     continue;
345                 }
346 
347                 DLPortletDataHandlerImpl.exportFileEntry(
348                     context, foldersEl, fileEntriesEl, fileRanks, fileEntry);
349 
350                 String newParameters =
351                     "/get_file?uuid=" + fileEntry.getUuid() +
352                         "&groupId=@data_handler_group_id@";
353 
354                 if (hasEncodedAmpersands) {
355                     newParameters = newParameters.replace(
356                         StringPool.AMPERSAND, StringPool.AMPERSAND_ENCODED);
357                 }
358 
359                 sb.replace(beginPos, endPos, newParameters);
360             }
361             catch (Exception e) {
362                 if (_log.isWarnEnabled()) {
363                     _log.warn(e);
364                 }
365             }
366 
367             beginPos--;
368         }
369 
370         return sb.toString();
371     }
372 
373     public static String exportIGImages(
374         PortletDataContext context, Element foldersEl, Element imagesEl,
375         long entityGroupId, String content) {
376 
377         StringBuilder sb = new StringBuilder(content);
378 
379         int beginPos = content.length();
380 
381         while (true) {
382             beginPos = content.lastIndexOf("/image_gallery?", beginPos);
383 
384             if (beginPos == -1) {
385                 return sb.toString();
386             }
387 
388             int endPos1 = content.indexOf(StringPool.APOSTROPHE, beginPos);
389             int endPos2 = content.indexOf(StringPool.CLOSE_BRACKET, beginPos);
390             int endPos3 = content.indexOf(
391                 StringPool.CLOSE_PARENTHESIS, beginPos);
392             int endPos4 = content.indexOf(StringPool.LESS_THAN, beginPos);
393             int endPos5 = content.indexOf(StringPool.QUOTE, beginPos);
394             int endPos6 = content.indexOf(StringPool.SPACE, beginPos);
395 
396             int endPos = endPos1;
397 
398             if ((endPos == -1) || ((endPos2 != -1) && (endPos2 < endPos))) {
399                 endPos = endPos2;
400             }
401 
402             if ((endPos == -1) || ((endPos3 != -1) && (endPos3 < endPos))) {
403                 endPos = endPos3;
404             }
405 
406             if ((endPos == -1) || ((endPos4 != -1) && (endPos4 < endPos))) {
407                 endPos = endPos4;
408             }
409 
410             if ((endPos == -1) || ((endPos5 != -1) && (endPos5 < endPos))) {
411                 endPos = endPos5;
412             }
413 
414             if ((endPos == -1) || ((endPos6 != -1) && (endPos6 < endPos))) {
415                 endPos = endPos6;
416             }
417 
418             if ((beginPos == -1) || (endPos == -1)) {
419                 break;
420             }
421 
422             try {
423                 String oldParameters = content.substring(beginPos, endPos);
424 
425                 oldParameters = oldParameters.substring(
426                     oldParameters.indexOf(StringPool.QUESTION) + 1);
427 
428                 boolean hasEncodedAmpersands = false;
429 
430                 while (oldParameters.contains(StringPool.AMPERSAND_ENCODED)) {
431                     hasEncodedAmpersands = true;
432 
433                     oldParameters = oldParameters.replace(
434                         StringPool.AMPERSAND_ENCODED, StringPool.AMPERSAND);
435                 }
436 
437                 Map<String, String> map = MapUtil.toLinkedHashMap(
438                     oldParameters.split(StringPool.AMPERSAND),
439                     StringPool.EQUAL);
440 
441                 IGImage image = null;
442 
443                 if (map.containsKey("uuid")) {
444                     String uuid = map.get("uuid");
445 
446                     String groupIdString = map.get("groupId");
447 
448                     long groupId = GetterUtil.getLong(groupIdString);
449 
450                     if (groupIdString.equals("@group_id@")) {
451                         groupId = entityGroupId;
452                     }
453 
454                     image = IGImageLocalServiceUtil.getImageByUuidAndGroupId(
455                         uuid, groupId);
456                 }
457                 else if (map.containsKey("image_id") ||
458                          map.containsKey("img_id") ||
459                          map.containsKey("i_id")) {
460 
461                     long imageId = GetterUtil.getLong(map.get("image_id"));
462 
463                     if (imageId <= 0) {
464                         imageId = GetterUtil.getLong(map.get("img_id"));
465 
466                         if (imageId <= 0) {
467                             imageId = GetterUtil.getLong(map.get("i_id"));
468                         }
469                     }
470 
471                     try {
472                         image = IGImageLocalServiceUtil.getImageByLargeImageId(
473                             imageId);
474                     }
475                     catch (Exception e) {
476                         image = IGImageLocalServiceUtil.getImageBySmallImageId(
477                             imageId);
478                     }
479                 }
480 
481                 if (image == null) {
482                     beginPos--;
483 
484                     continue;
485                 }
486 
487                 IGPortletDataHandlerImpl.exportImage(
488                     context, foldersEl, imagesEl, image);
489 
490                 String timestamp = map.get("t");
491 
492                 if (timestamp == null) {
493                     timestamp = String.valueOf(System.currentTimeMillis());
494                 }
495 
496                 String newParameters =
497                     "/image_gallery?uuid=" + image.getUuid() +
498                         "&groupId=@data_handler_group_id@&t=" + timestamp;
499 
500                 if (hasEncodedAmpersands) {
501                     newParameters = newParameters.replace(
502                         StringPool.AMPERSAND, StringPool.AMPERSAND_ENCODED);
503                 }
504 
505                 sb.replace(beginPos, endPos, newParameters);
506             }
507             catch (Exception e) {
508                 if (_log.isWarnEnabled()) {
509                     _log.warn(e);
510                 }
511             }
512 
513             beginPos--;
514         }
515 
516         return sb.toString();
517     }
518 
519     public static void exportStructure(
520             PortletDataContext context, Element structuresEl,
521             JournalStructure structure)
522         throws PortalException, SystemException {
523 
524         if (!context.isWithinDateRange(structure.getModifiedDate())) {
525             return;
526         }
527 
528         String path = getStructurePath(context, structure);
529 
530         if (!context.isPathNotProcessed(path)) {
531             return;
532         }
533 
534         Element structureEl = structuresEl.addElement("structure");
535 
536         structureEl.addAttribute("path", path);
537 
538         structure.setUserUuid(structure.getUserUuid());
539 
540         context.addPermissions(JournalStructure.class, structure.getId());
541 
542         context.addZipEntry(path, structure);
543     }
544 
545     public static void exportTemplate(
546             PortletDataContext context, Element templatesEl,
547             Element dlFoldersEl, Element dlFileEntriesEl, Element dlFileRanks,
548             Element igFoldersEl, Element igImagesEl, JournalTemplate template)
549         throws PortalException, SystemException {
550 
551         if (!context.isWithinDateRange(template.getModifiedDate())) {
552             return;
553         }
554 
555         String path = getTemplatePath(context, template);
556 
557         if (!context.isPathNotProcessed(path)) {
558             return;
559         }
560 
561         // Clone this template to make sure changes to its content are never
562         // persisted
563 
564         template = (JournalTemplate)template.clone();
565 
566         Element templateEl = templatesEl.addElement("template");
567 
568         templateEl.addAttribute("path", path);
569 
570         if (template.isSmallImage()) {
571             String smallImagePath = getTemplateSmallImagePath(
572                 context, template);
573 
574             templateEl.addAttribute("small-image-path", smallImagePath);
575 
576             Image smallImage = ImageUtil.fetchByPrimaryKey(
577                 template.getSmallImageId());
578 
579             template.setSmallImageType(smallImage.getType());
580 
581             context.addZipEntry(smallImagePath, smallImage.getTextObj());
582         }
583 
584         if (context.getBooleanParameter(_NAMESPACE, "embedded-assets")) {
585             String content = template.getXsl();
586 
587             content = exportDLFileEntries(
588                 context, dlFoldersEl, dlFileEntriesEl, dlFileRanks,
589                 template.getGroupId(), content);
590             content = exportIGImages(
591                 context, igFoldersEl, igImagesEl, template.getGroupId(),
592                 content);
593 
594             content = StringUtil.replace(
595                 content, StringPool.AMPERSAND_ENCODED, StringPool.AMPERSAND);
596 
597             template.setXsl(content);
598         }
599 
600         template.setUserUuid(template.getUserUuid());
601 
602         context.addPermissions(JournalTemplate.class, template.getId());
603 
604         context.addZipEntry(path, template);
605     }
606 
607     public static void importArticle(
608             PortletDataContext context, Map<String, String> structureIds,
609             Map<String, String> templateIds, Map<String, String> articleIds,
610             Element articleEl)
611         throws Exception {
612 
613         String path = articleEl.attributeValue("path");
614 
615         if (!context.isPathNotProcessed(path)) {
616             return;
617         }
618 
619         JournalArticle article = (JournalArticle)context.getZipEntryAsObject(
620             path);
621 
622         long userId = context.getUserId(article.getUserUuid());
623 
624         User user = UserLocalServiceUtil.getUser(userId);
625 
626         long groupId = context.getGroupId();
627 
628         String articleId = article.getArticleId();
629         boolean autoArticleId = false;
630 
631         if ((Validator.isNumber(articleId)) ||
632             (JournalArticleUtil.fetchByG_A_V(
633                 groupId, articleId,
634                     JournalArticleImpl.DEFAULT_VERSION) != null)) {
635 
636             autoArticleId = true;
637         }
638 
639         String newArticleId = articleIds.get(articleId);
640 
641         if (Validator.isNotNull(newArticleId)) {
642 
643             // A sibling of a different version was already assigned a new
644             // article id
645 
646             articleId = newArticleId;
647             autoArticleId = false;
648         }
649 
650         boolean incrementVersion = false;
651 
652         String content = article.getContent();
653 
654         article.setContent(
655             StringUtil.replace(
656                 content, "@data_handler_group_id@", String.valueOf(groupId)));
657 
658         String parentStructureId = MapUtil.getString(
659             structureIds, article.getStructureId(), article.getStructureId());
660         String parentTemplateId = MapUtil.getString(
661             templateIds, article.getTemplateId(), article.getTemplateId());
662 
663         Date displayDate = article.getDisplayDate();
664 
665         int displayDateMonth = 0;
666         int displayDateDay = 0;
667         int displayDateYear = 0;
668         int displayDateHour = 0;
669         int displayDateMinute = 0;
670 
671         if (displayDate != null) {
672             Calendar displayCal = CalendarFactoryUtil.getCalendar(
673                 user.getTimeZone());
674 
675             displayCal.setTime(displayDate);
676 
677             displayDateMonth = displayCal.get(Calendar.MONTH);
678             displayDateDay = displayCal.get(Calendar.DATE);
679             displayDateYear = displayCal.get(Calendar.YEAR);
680             displayDateHour = displayCal.get(Calendar.HOUR);
681             displayDateMinute = displayCal.get(Calendar.MINUTE);
682 
683             if (displayCal.get(Calendar.AM_PM) == Calendar.PM) {
684                 displayDateHour += 12;
685             }
686         }
687 
688         Date expirationDate = article.getExpirationDate();
689 
690         int expirationDateMonth = 0;
691         int expirationDateDay = 0;
692         int expirationDateYear = 0;
693         int expirationDateHour = 0;
694         int expirationDateMinute = 0;
695         boolean neverExpire = true;
696 
697         if (expirationDate != null) {
698             Calendar expirationCal = CalendarFactoryUtil.getCalendar(
699                 user.getTimeZone());
700 
701             expirationCal.setTime(expirationDate);
702 
703             expirationDateMonth = expirationCal.get(Calendar.MONTH);
704             expirationDateDay = expirationCal.get(Calendar.DATE);
705             expirationDateYear = expirationCal.get(Calendar.YEAR);
706             expirationDateHour = expirationCal.get(Calendar.HOUR);
707             expirationDateMinute = expirationCal.get(Calendar.MINUTE);
708             neverExpire = false;
709 
710             if (expirationCal.get(Calendar.AM_PM) == Calendar.PM) {
711                 expirationDateHour += 12;
712             }
713         }
714 
715         Date reviewDate = article.getReviewDate();
716 
717         int reviewDateMonth = 0;
718         int reviewDateDay = 0;
719         int reviewDateYear = 0;
720         int reviewDateHour = 0;
721         int reviewDateMinute = 0;
722         boolean neverReview = true;
723 
724         if (reviewDate != null) {
725             Calendar reviewCal = CalendarFactoryUtil.getCalendar(
726                 user.getTimeZone());
727 
728             reviewCal.setTime(reviewDate);
729 
730             reviewDateMonth = reviewCal.get(Calendar.MONTH);
731             reviewDateDay = reviewCal.get(Calendar.DATE);
732             reviewDateYear = reviewCal.get(Calendar.YEAR);
733             reviewDateHour = reviewCal.get(Calendar.HOUR);
734             reviewDateMinute = reviewCal.get(Calendar.MINUTE);
735             neverReview = false;
736 
737             if (reviewCal.get(Calendar.AM_PM) == Calendar.PM) {
738                 reviewDateHour += 12;
739             }
740         }
741 
742         File smallFile = null;
743 
744         String smallImagePath = articleEl.attributeValue("small-image-path");
745 
746         if (article.isSmallImage() && Validator.isNotNull(smallImagePath)) {
747             byte[] bytes = context.getZipEntryAsByteArray(smallImagePath);
748 
749             smallFile = File.createTempFile(
750                 String.valueOf(article.getSmallImageId()),
751                 StringPool.PERIOD + article.getSmallImageType());
752 
753             FileUtil.write(smallFile, bytes);
754         }
755 
756         Map<String, byte[]> images = new HashMap<String, byte[]>();
757 
758         if (context.getBooleanParameter(_NAMESPACE, "images")) {
759             String imagePath = articleEl.attributeValue("image-path");
760 
761             List<String> imageFiles = context.getZipFolderEntries(imagePath);
762 
763             for (String imageFile : imageFiles) {
764                 String fileName = imageFile;
765 
766                 if (fileName.contains(StringPool.SLASH)) {
767                     fileName = fileName.substring(
768                         fileName.lastIndexOf(StringPool.SLASH) + 1);
769                 }
770 
771                 if (fileName.endsWith(".xml")) {
772                     continue;
773                 }
774 
775                 int pos = fileName.lastIndexOf(StringPool.PERIOD);
776 
777                 if (pos != -1) {
778                     fileName = fileName.substring(0, pos);
779                 }
780 
781                 images.put(fileName, context.getZipEntryAsByteArray(imageFile));
782             }
783         }
784 
785         String articleURL = null;
786 
787         String[] tagsCategories = null;
788         String[] tagsEntries = null;
789 
790         if (context.getBooleanParameter(_NAMESPACE, "categories")) {
791             tagsCategories = context.getTagsCategories(
792                 JournalArticle.class, article.getResourcePrimKey());
793         }
794 
795         if (context.getBooleanParameter(_NAMESPACE, "tags")) {
796             tagsEntries = context.getTagsEntries(
797                 JournalArticle.class, article.getResourcePrimKey());
798         }
799 
800         JournalCreationStrategy creationStrategy =
801             JournalCreationStrategyFactory.getInstance();
802 
803         long authorId = creationStrategy.getAuthorUserId(context, article);
804 
805         if (authorId != JournalCreationStrategy.USE_DEFAULT_USER_ID_STRATEGY) {
806             userId = authorId;
807         }
808 
809         String newContent = creationStrategy.getTransformedContent(
810             context, article);
811 
812         if (newContent != JournalCreationStrategy.ARTICLE_CONTENT_UNCHANGED) {
813             article.setContent(newContent);
814         }
815 
816         boolean addCommunityPermissions =
817             creationStrategy.addCommunityPermissions(context, article);
818         boolean addGuestPermissions = creationStrategy.addGuestPermissions(
819             context, article);
820 
821         ServiceContext serviceContext = new ServiceContext();
822 
823         serviceContext.setAddCommunityPermissions(addCommunityPermissions);
824         serviceContext.setAddGuestPermissions(addGuestPermissions);
825         serviceContext.setCreateDate(article.getCreateDate());
826         serviceContext.setModifiedDate(article.getModifiedDate());
827         serviceContext.setScopeGroupId(groupId);
828         serviceContext.setTagsCategories(tagsCategories);
829         serviceContext.setTagsEntries(tagsEntries);
830 
831         JournalArticle existingArticle = null;
832 
833         if (Validator.isNotNull(article.getStructureId())) {
834             JournalStructure structure = JournalStructureUtil.fetchByG_S(
835                 context.getGroupId(), article.getStructureId());
836 
837             if (structure == null) {
838                 String structurePath = getImportStructurePath(
839                     context, article.getStructureId());
840 
841                 importStructure(context, structureIds, structurePath);
842             }
843         }
844 
845         if (Validator.isNotNull(article.getTemplateId())) {
846             JournalTemplate template = JournalTemplateUtil.fetchByG_T(
847                 context.getGroupId(), article.getTemplateId());
848 
849             if (template == null) {
850                 String templatePath = getImportTemplatePath(
851                     context, article.getTemplateId());
852 
853                 String templateSmallImagePath = getImportTemplateSmallImagePath(
854                     context, article.getTemplateId());
855 
856                 importTemplate(
857                     context, structureIds, templateIds, templateSmallImagePath,
858                     templatePath);
859             }
860         }
861 
862         if (context.getDataStrategy().equals(
863                 PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
864 
865             existingArticle = JournalArticleUtil.fetchByUUID_G(
866                 article.getUuid(), groupId);
867 
868             if (existingArticle == null) {
869                 existingArticle = JournalArticleLocalServiceUtil.addArticle(
870                     article.getUuid(), userId, groupId, articleId,
871                     autoArticleId, article.getVersion(), article.getTitle(),
872                     article.getDescription(), article.getContent(),
873                     article.getType(), parentStructureId, parentTemplateId,
874                     displayDateMonth, displayDateDay, displayDateYear,
875                     displayDateHour, displayDateMinute, expirationDateMonth,
876                     expirationDateDay, expirationDateYear, expirationDateHour,
877                     expirationDateMinute, neverExpire, reviewDateMonth,
878                     reviewDateDay, reviewDateYear, reviewDateHour,
879                     reviewDateMinute, neverReview, article.isIndexable(),
880                     article.isSmallImage(), article.getSmallImageURL(),
881                     smallFile, images, articleURL, serviceContext);
882             }
883             else {
884                 existingArticle = JournalArticleLocalServiceUtil.updateArticle(
885                     userId, existingArticle.getGroupId(),
886                     existingArticle.getArticleId(),
887                     existingArticle.getVersion(), incrementVersion,
888                     article.getTitle(), article.getDescription(),
889                     article.getContent(), article.getType(), parentStructureId,
890                     parentTemplateId, displayDateMonth, displayDateDay,
891                     displayDateYear, displayDateHour, displayDateMinute,
892                     expirationDateMonth, expirationDateDay, expirationDateYear,
893                     expirationDateHour, expirationDateMinute, neverExpire,
894                     reviewDateMonth, reviewDateDay, reviewDateYear,
895                     reviewDateHour, reviewDateMinute, neverReview,
896                     article.isIndexable(), article.isSmallImage(),
897                     article.getSmallImageURL(), smallFile, images, articleURL,
898                     serviceContext);
899             }
900         }
901         else {
902             existingArticle = JournalArticleLocalServiceUtil.addArticle(
903                 userId, groupId, articleId, autoArticleId, article.getVersion(),
904                 article.getTitle(), article.getDescription(),
905                 article.getContent(), article.getType(), parentStructureId,
906                 parentTemplateId, displayDateMonth, displayDateDay,
907                 displayDateYear, displayDateHour, displayDateMinute,
908                 expirationDateMonth, expirationDateDay, expirationDateYear,
909                 expirationDateHour, expirationDateMinute, neverExpire,
910                 reviewDateMonth, reviewDateDay, reviewDateYear, reviewDateHour,
911                 reviewDateMinute, neverReview, article.isIndexable(),
912                 article.isSmallImage(), article.getSmallImageURL(), smallFile,
913                 images, articleURL, serviceContext);
914         }
915 
916         long strategyApprovalUserId = creationStrategy.getApprovalUserId(
917             context, article);
918 
919         if ((strategyApprovalUserId !=
920                 JournalCreationStrategy.USE_DEFAULT_USER_ID_STRATEGY) ||
921             (article.isApproved() && !existingArticle.isApproved())) {
922 
923             long approvedByUserId = strategyApprovalUserId;
924 
925             if (approvedByUserId == 0) {
926                 approvedByUserId = context.getUserId(
927                     article.getApprovedByUserUuid());
928             }
929 
930             JournalArticleLocalServiceUtil.approveArticle(
931                 approvedByUserId, groupId, existingArticle.getArticleId(),
932                 existingArticle.getVersion(), articleURL, serviceContext);
933         }
934 
935         context.importPermissions(
936             JournalArticle.class, article.getResourcePrimKey(),
937             existingArticle.getResourcePrimKey());
938 
939         if (context.getBooleanParameter(_NAMESPACE, "comments")) {
940             context.importComments(
941                 JournalArticle.class, article.getResourcePrimKey(),
942                 existingArticle.getResourcePrimKey(), groupId);
943         }
944 
945         if (context.getBooleanParameter(_NAMESPACE, "ratings")) {
946             context.importRatingsEntries(
947                 JournalArticle.class, article.getResourcePrimKey(),
948                 existingArticle.getResourcePrimKey());
949         }
950 
951         articleIds.put(articleId, existingArticle.getArticleId());
952 
953         if (!articleId.equals(existingArticle.getArticleId())) {
954             if (_log.isWarnEnabled()) {
955                 _log.warn(
956                     "An article with the ID " + articleId + " already " +
957                         "exists. The new generated ID is " +
958                             existingArticle.getArticleId());
959             }
960         }
961     }
962 
963     public static void importFeed(
964             PortletDataContext context, Map<String, String> structureIds,
965             Map<String, String> templateIds, Map<String, String> feedIds,
966             Element feedEl)
967         throws Exception {
968 
969         String path = feedEl.attributeValue("path");
970 
971         if (!context.isPathNotProcessed(path)) {
972             return;
973         }
974 
975         JournalFeed feed = (JournalFeed)context.getZipEntryAsObject(path);
976 
977         long userId = context.getUserId(feed.getUserUuid());
978         long groupId = context.getGroupId();
979 
980         String feedId = feed.getFeedId();
981         boolean autoFeedId = false;
982 
983         if ((Validator.isNumber(feedId)) ||
984             (JournalFeedUtil.fetchByG_F(groupId, feedId) != null)) {
985 
986             autoFeedId = true;
987         }
988 
989         String parentStructureId = MapUtil.getString(
990             structureIds, feed.getStructureId(), feed.getStructureId());
991         String parentTemplateId = MapUtil.getString(
992             templateIds, feed.getTemplateId(), feed.getTemplateId());
993         String parentRenderTemplateId = MapUtil.getString(
994             templateIds, feed.getRendererTemplateId(),
995             feed.getRendererTemplateId());
996 
997         JournalCreationStrategy creationStrategy =
998             JournalCreationStrategyFactory.getInstance();
999 
1000        long authorId = creationStrategy.getAuthorUserId(context, feed);
1001
1002        if (authorId != JournalCreationStrategy.USE_DEFAULT_USER_ID_STRATEGY) {
1003            userId = authorId;
1004        }
1005
1006        boolean addCommunityPermissions =
1007            creationStrategy.addCommunityPermissions(context, feed);
1008        boolean addGuestPermissions = creationStrategy.addGuestPermissions(
1009            context, feed);
1010
1011        ServiceContext serviceContext = new ServiceContext();
1012
1013        serviceContext.setAddCommunityPermissions(addCommunityPermissions);
1014        serviceContext.setAddGuestPermissions(addGuestPermissions);
1015        serviceContext.setCreateDate(feed.getCreateDate());
1016        serviceContext.setModifiedDate(feed.getModifiedDate());
1017
1018        JournalFeed existingFeed = null;
1019
1020        if (context.getDataStrategy().equals(
1021                PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
1022
1023            existingFeed = JournalFeedUtil.fetchByUUID_G(
1024                feed.getUuid(), groupId);
1025
1026            if (existingFeed == null) {
1027                existingFeed = JournalFeedLocalServiceUtil.addFeed(
1028                    feed.getUuid(), userId, groupId, feedId, autoFeedId,
1029                    feed.getName(), feed.getDescription(), feed.getType(),
1030                    parentStructureId, parentTemplateId, parentRenderTemplateId,
1031                    feed.getDelta(), feed.getOrderByCol(),
1032                    feed.getOrderByType(), feed.getTargetLayoutFriendlyUrl(),
1033                    feed.getTargetPortletId(), feed.getContentField(),
1034                    feed.getFeedType(), feed.getFeedVersion(),
1035                    serviceContext);
1036            }
1037            else {
1038                existingFeed = JournalFeedLocalServiceUtil.updateFeed(
1039                    existingFeed.getGroupId(), existingFeed.getFeedId(),
1040                    feed.getName(), feed.getDescription(), feed.getType(),
1041                    parentStructureId, parentTemplateId, parentRenderTemplateId,
1042                    feed.getDelta(), feed.getOrderByCol(),
1043                    feed.getOrderByType(), feed.getTargetLayoutFriendlyUrl(),
1044                    feed.getTargetPortletId(), feed.getContentField(),
1045                    feed.getFeedType(), feed.getFeedVersion(), serviceContext);
1046            }
1047        }
1048        else {
1049            existingFeed = JournalFeedLocalServiceUtil.addFeed(
1050                userId, groupId, feedId, autoFeedId, feed.getName(),
1051                feed.getDescription(), feed.getType(), parentStructureId,
1052                parentTemplateId, parentRenderTemplateId, feed.getDelta(),
1053                feed.getOrderByCol(), feed.getOrderByType(),
1054                feed.getTargetLayoutFriendlyUrl(), feed.getTargetPortletId(),
1055                feed.getContentField(), feed.getFeedType(),
1056                feed.getFeedVersion(), serviceContext);
1057        }
1058
1059        feedIds.put(feedId, existingFeed.getFeedId());
1060
1061        context.importPermissions(
1062            JournalFeed.class, feed.getId(), existingFeed.getId());
1063
1064        if (!feedId.equals(existingFeed.getStructureId())) {
1065            if (_log.isWarnEnabled()) {
1066                _log.warn(
1067                    "A feed with the ID " + feedId + " already " +
1068                        "exists. The new generated ID is " +
1069                            existingFeed.getFeedId());
1070            }
1071        }
1072    }
1073
1074    public static void importStructure(
1075            PortletDataContext context, Map<String, String> structureIds,
1076            Element structureEl)
1077        throws Exception {
1078
1079        String path = structureEl.attributeValue("path");
1080
1081        importStructure(context, structureIds, path);
1082    }
1083
1084    protected static void importStructure(
1085            PortletDataContext context, Map<String, String> structureIds,
1086            String path)
1087        throws Exception {
1088
1089        if (!context.isPathNotProcessed(path)) {
1090            return;
1091        }
1092
1093        JournalStructure structure =
1094            (JournalStructure)context.getZipEntryAsObject(path);
1095
1096        long userId = context.getUserId(structure.getUserUuid());
1097        long groupId = context.getGroupId();
1098
1099        String structureId = structure.getStructureId();
1100        boolean autoStructureId = false;
1101
1102        if ((Validator.isNumber(structureId)) ||
1103            (JournalStructureUtil.fetchByG_S(groupId, structureId) != null)) {
1104
1105            autoStructureId = true;
1106        }
1107
1108        JournalCreationStrategy creationStrategy =
1109            JournalCreationStrategyFactory.getInstance();
1110
1111        long authorId = creationStrategy.getAuthorUserId(context, structure);
1112
1113        if (authorId != JournalCreationStrategy.USE_DEFAULT_USER_ID_STRATEGY) {
1114            userId = authorId;
1115        }
1116
1117        boolean addCommunityPermissions =
1118            creationStrategy.addCommunityPermissions(context, structure);
1119        boolean addGuestPermissions = creationStrategy.addGuestPermissions(
1120            context, structure);
1121
1122        ServiceContext serviceContext = new ServiceContext();
1123
1124        serviceContext.setAddCommunityPermissions(addCommunityPermissions);
1125        serviceContext.setAddGuestPermissions(addGuestPermissions);
1126        serviceContext.setCreateDate(structure.getCreateDate());
1127        serviceContext.setModifiedDate(structure.getModifiedDate());
1128
1129        JournalStructure existingStructure = null;
1130
1131        if (context.getDataStrategy().equals(
1132                PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
1133
1134            existingStructure = JournalStructureUtil.fetchByUUID_G(
1135                structure.getUuid(), groupId);
1136
1137            if (existingStructure == null) {
1138                existingStructure =
1139                    JournalStructureLocalServiceUtil.addStructure(
1140                        structure.getUuid(), userId, groupId, structureId,
1141                        autoStructureId, structure.getParentStructureId(),
1142                        structure.getName(), structure.getDescription(),
1143                        structure.getXsd(), serviceContext);
1144            }
1145            else {
1146                existingStructure =
1147                    JournalStructureLocalServiceUtil.updateStructure(
1148                        existingStructure.getGroupId(),
1149                        existingStructure.getStructureId(),
1150                        structure.getParentStructureId(), structure.getName(),
1151                        structure.getDescription(), structure.getXsd(),
1152                        serviceContext);
1153            }
1154        }
1155        else {
1156            existingStructure = JournalStructureLocalServiceUtil.addStructure(
1157                userId, groupId, structureId, autoStructureId,
1158                structure.getParentStructureId(), structure.getName(),
1159                structure.getDescription(), structure.getXsd(), serviceContext);
1160        }
1161
1162        structureIds.put(structureId, existingStructure.getStructureId());
1163
1164        context.importPermissions(
1165            JournalStructure.class, structure.getId(),
1166            existingStructure.getId());
1167
1168        if (!structureId.equals(existingStructure.getStructureId())) {
1169            if (_log.isWarnEnabled()) {
1170                _log.warn(
1171                    "A structure with the ID " + structureId + " already " +
1172                        "exists. The new generated ID is " +
1173                            existingStructure.getStructureId());
1174            }
1175        }
1176    }
1177
1178    public static void importTemplate(
1179            PortletDataContext context, Map<String, String> structureIds,
1180            Map<String, String> templateIds, Element templateEl)
1181        throws Exception {
1182
1183        String path = templateEl.attributeValue("path");
1184
1185        importTemplate(
1186            context, structureIds, templateIds,
1187            templateEl.attributeValue("small-image-path"), path);
1188    }
1189
1190    protected static void importTemplate(
1191            PortletDataContext context, Map<String, String> structureIds,
1192            Map<String, String> templateIds, String smallImagePath, String path)
1193        throws Exception {
1194
1195        if (!context.isPathNotProcessed(path)) {
1196            return;
1197        }
1198
1199        JournalTemplate template = (JournalTemplate)context.getZipEntryAsObject(
1200            path);
1201
1202        long userId = context.getUserId(template.getUserUuid());
1203        long groupId = context.getGroupId();
1204
1205        String templateId = template.getTemplateId();
1206        boolean autoTemplateId = false;
1207
1208        if ((Validator.isNumber(templateId)) ||
1209            (JournalTemplateUtil.fetchByG_T(groupId, templateId) != null)) {
1210
1211            autoTemplateId = true;
1212        }
1213
1214        String parentStructureId = MapUtil.getString(
1215            structureIds, template.getStructureId(), template.getStructureId());
1216
1217        boolean formatXsl = false;
1218
1219        JournalCreationStrategy creationStrategy =
1220            JournalCreationStrategyFactory.getInstance();
1221
1222        long authorId = creationStrategy.getAuthorUserId(context, template);
1223
1224        if (authorId != JournalCreationStrategy.USE_DEFAULT_USER_ID_STRATEGY) {
1225            userId = authorId;
1226        }
1227
1228        boolean addCommunityPermissions =
1229            creationStrategy.addCommunityPermissions(context, template);
1230        boolean addGuestPermissions = creationStrategy.addGuestPermissions(
1231            context, template);
1232
1233        ServiceContext serviceContext = new ServiceContext();
1234
1235        serviceContext.setAddCommunityPermissions(addCommunityPermissions);
1236        serviceContext.setAddGuestPermissions(addGuestPermissions);
1237        serviceContext.setCreateDate(template.getCreateDate());
1238        serviceContext.setModifiedDate(template.getModifiedDate());
1239
1240        File smallFile = null;
1241
1242        if (template.isSmallImage() && Validator.isNotNull(smallImagePath)) {
1243            if (smallImagePath.endsWith(StringPool.PERIOD)) {
1244                smallImagePath += template.getSmallImageType();
1245            }
1246
1247            byte[] bytes = context.getZipEntryAsByteArray(smallImagePath);
1248
1249            if (bytes != null) {
1250                smallFile = File.createTempFile(
1251                    String.valueOf(template.getSmallImageId()),
1252                    StringPool.PERIOD + template.getSmallImageType());
1253
1254                FileUtil.write(smallFile, bytes);
1255            }
1256        }
1257
1258        JournalTemplate existingTemplate = null;
1259
1260        if (context.getDataStrategy().equals(
1261                PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
1262
1263            existingTemplate = JournalTemplateUtil.fetchByUUID_G(
1264                template.getUuid(), groupId);
1265
1266            if (existingTemplate == null) {
1267                existingTemplate = JournalTemplateLocalServiceUtil.addTemplate(
1268                    template.getUuid(), userId, groupId, templateId,
1269                    autoTemplateId, parentStructureId, template.getName(),
1270                    template.getDescription(), template.getXsl(), formatXsl,
1271                    template.getLangType(), template.getCacheable(),
1272                    template.isSmallImage(), template.getSmallImageURL(),
1273                    smallFile, serviceContext);
1274            }
1275            else {
1276                existingTemplate =
1277                    JournalTemplateLocalServiceUtil.updateTemplate(
1278                        existingTemplate.getGroupId(),
1279                        existingTemplate.getTemplateId(),
1280                        existingTemplate.getStructureId(), template.getName(),
1281                        template.getDescription(), template.getXsl(), formatXsl,
1282                        template.getLangType(), template.getCacheable(),
1283                        template.isSmallImage(), template.getSmallImageURL(),
1284                        smallFile, serviceContext);
1285            }
1286        }
1287        else {
1288            existingTemplate = JournalTemplateLocalServiceUtil.addTemplate(
1289                userId, groupId, templateId, autoTemplateId, parentStructureId,
1290                template.getName(), template.getDescription(),
1291                template.getXsl(), formatXsl, template.getLangType(),
1292                template.getCacheable(), template.isSmallImage(),
1293                template.getSmallImageURL(), smallFile, serviceContext);
1294        }
1295
1296        templateIds.put(templateId, existingTemplate.getTemplateId());
1297
1298        context.importPermissions(
1299            JournalTemplate.class, template.getId(),
1300            existingTemplate.getId());
1301
1302        if (!templateId.equals(existingTemplate.getTemplateId())) {
1303            if (_log.isWarnEnabled()) {
1304                _log.warn(
1305                    "A template with the ID " + templateId + " already " +
1306                        "exists. The new generated ID is " +
1307                            existingTemplate.getTemplateId());
1308            }
1309        }
1310    }
1311
1312    public PortletPreferences deleteData(
1313            PortletDataContext context, String portletId,
1314            PortletPreferences preferences)
1315        throws PortletDataException {
1316
1317        try {
1318            if (!context.addPrimaryKey(
1319                    JournalPortletDataHandlerImpl.class, "deleteData")) {
1320
1321                JournalArticleLocalServiceUtil.deleteArticles(
1322                    context.getGroupId());
1323
1324                JournalTemplateLocalServiceUtil.deleteTemplates(
1325                    context.getGroupId());
1326
1327                JournalStructureLocalServiceUtil.deleteStructures(
1328                    context.getGroupId());
1329            }
1330
1331            return preferences;
1332        }
1333        catch (Exception e) {
1334            throw new PortletDataException(e);
1335        }
1336    }
1337
1338    public String exportData(
1339            PortletDataContext context, String portletId,
1340            PortletPreferences preferences)
1341        throws PortletDataException {
1342
1343        try {
1344            context.addPermissions(
1345                "com.liferay.portlet.journal", context.getGroupId());
1346
1347            Document doc = SAXReaderUtil.createDocument();
1348
1349            Element root = doc.addElement("journal-data");
1350
1351            root.addAttribute("group-id", String.valueOf(context.getGroupId()));
1352
1353            Element structuresEl = root.addElement("structures");
1354
1355            List<JournalStructure> structures =
1356                JournalStructureUtil.findByGroupId(context.getGroupId());
1357
1358            for (JournalStructure structure : structures) {
1359                exportStructure(context, structuresEl, structure);
1360            }
1361
1362            Element templatesEl = root.addElement("templates");
1363            Element dlFoldersEl = root.addElement("dl-folders");
1364            Element dlFilesEl = root.addElement("dl-file-entries");
1365            Element dlFileRanksEl = root.addElement("dl-file-ranks");
1366            Element igFoldersEl = root.addElement("ig-folders");
1367            Element igImagesEl = root.addElement("ig-images");
1368
1369            List<JournalTemplate> templates = JournalTemplateUtil.findByGroupId(
1370                context.getGroupId());
1371
1372            for (JournalTemplate template : templates) {
1373                exportTemplate(
1374                    context, templatesEl, dlFoldersEl, dlFilesEl, dlFileRanksEl,
1375                    igFoldersEl, igImagesEl, template);
1376            }
1377
1378            Element feedsEl = root.addElement("feeds");
1379
1380            List<JournalFeed> feeds = JournalFeedUtil.findByGroupId(
1381                context.getGroupId());
1382
1383            for (JournalFeed feed : feeds) {
1384                if (context.isWithinDateRange(feed.getModifiedDate())) {
1385                    exportFeed(context, feedsEl, feed);
1386                }
1387            }
1388
1389            Element articlesEl = root.addElement("articles");
1390
1391            if (context.getBooleanParameter(_NAMESPACE, "articles")) {
1392                List<JournalArticle> articles =
1393                    JournalArticleUtil.findByGroupId(
1394                        context.getGroupId(), QueryUtil.ALL_POS,
1395                        QueryUtil.ALL_POS, new ArticleIDComparator(true));
1396
1397                for (JournalArticle article : articles) {
1398                    exportArticle(
1399                        context, articlesEl, dlFoldersEl, dlFilesEl,
1400                        dlFileRanksEl, igFoldersEl, igImagesEl, article);
1401                }
1402            }
1403
1404            return doc.formattedString();
1405        }
1406        catch (Exception e) {
1407            throw new PortletDataException(e);
1408        }
1409    }
1410
1411    public PortletDataHandlerControl[] getExportControls() {
1412        return new PortletDataHandlerControl[] {
1413            _articles, _structuresTemplatesAndFeeds, _embeddedAssets, _images,
1414            _categories, _comments, _ratings, _tags
1415        };
1416    }
1417
1418    public PortletDataHandlerControl[] getImportControls() {
1419        return new PortletDataHandlerControl[] {
1420            _articles, _structuresTemplatesAndFeeds, _images, _categories,
1421            _comments, _ratings, _tags
1422        };
1423    }
1424
1425    public PortletPreferences importData(
1426            PortletDataContext context, String portletId,
1427            PortletPreferences preferences, String data)
1428        throws PortletDataException {
1429
1430        try {
1431            context.importPermissions(
1432                "com.liferay.portlet.journal", context.getSourceGroupId(),
1433                context.getGroupId());
1434
1435            Document doc = SAXReaderUtil.read(data);
1436
1437            Element root = doc.getRootElement();
1438
1439            List<Element> structureEls = root.element("structures").elements(
1440                "structure");
1441
1442            Map<String, String> structureIds =
1443                (Map<String, String>)context.getNewPrimaryKeysMap(
1444                    JournalStructure.class);
1445
1446            for (Element structureEl : structureEls) {
1447                importStructure(context, structureIds, structureEl);
1448            }
1449
1450            List<Element> templateEls = root.element("templates").elements(
1451                "template");
1452
1453            Map<String, String> templateIds =
1454                (Map<String, String>)context.getNewPrimaryKeysMap(
1455                    JournalTemplate.class);
1456
1457            for (Element templateEl : templateEls) {
1458                importTemplate(context, structureIds, templateIds, templateEl);
1459            }
1460
1461            List<Element> feedEls = root.element("feeds").elements("feed");
1462
1463            Map<String, String> feedIds =
1464                (Map<String, String>)context.getNewPrimaryKeysMap(
1465                    JournalFeed.class);
1466
1467            for (Element feedEl : feedEls) {
1468                importFeed(context, structureIds, templateIds, feedIds, feedEl);
1469            }
1470
1471            if (context.getBooleanParameter(_NAMESPACE, "articles")) {
1472                List<Element> articleEls = root.element("articles").elements(
1473                    "article");
1474
1475                Map<String, String> articleIds =
1476                    (Map<String, String>)context.getNewPrimaryKeysMap(
1477                        JournalArticle.class);
1478
1479                for (Element articleEl : articleEls) {
1480                    importArticle(
1481                        context, structureIds, templateIds, articleIds,
1482                        articleEl);
1483                }
1484            }
1485
1486            List<Element> dlFolderEls = root.element("dl-folders").elements(
1487                "folder");
1488
1489            Map<Long, Long> dlFolderPKs =
1490                (Map<Long, Long>)context.getNewPrimaryKeysMap(DLFolder.class);
1491
1492            for (Element folderEl : dlFolderEls) {
1493                String path = folderEl.attributeValue("path");
1494
1495                if (!context.isPathNotProcessed(path)) {
1496                    continue;
1497                }
1498
1499                DLFolder folder = (DLFolder)context.getZipEntryAsObject(path);
1500
1501                DLPortletDataHandlerImpl.importFolder(
1502                    context, dlFolderPKs, folder);
1503            }
1504
1505            List<Element> fileEntryEls = root.element(
1506                "dl-file-entries").elements("file-entry");
1507
1508            Map<String, String> fileEntryNames =
1509                (Map<String, String>)context.getNewPrimaryKeysMap(
1510                    DLFileEntry.class);
1511
1512            for (Element fileEntryEl : fileEntryEls) {
1513                String path = fileEntryEl.attributeValue("path");
1514
1515                if (!context.isPathNotProcessed(path)) {
1516                    continue;
1517                }
1518
1519                DLFileEntry fileEntry = null;
1520
1521                try {
1522                    fileEntry = (DLFileEntry)context.getZipEntryAsObject(path);
1523                }
1524                catch (Exception e) {
1525                    if (_log.isWarnEnabled()) {
1526                        _log.warn("No file entry found for path " + path);
1527                    }
1528
1529                    continue;
1530                }
1531
1532                String binPath = fileEntryEl.attributeValue("bin-path");
1533
1534                DLPortletDataHandlerImpl.importFileEntry(
1535                    context, dlFolderPKs, fileEntryNames, fileEntry, binPath);
1536            }
1537
1538            List<Element> fileRankEls = root.element("dl-file-ranks").elements(
1539                "file-rank");
1540
1541            for (Element fileRankEl : fileRankEls) {
1542                String path = fileRankEl.attributeValue("path");
1543
1544                if (!context.isPathNotProcessed(path)) {
1545                    continue;
1546                }
1547
1548                DLFileRank fileRank = (DLFileRank)context.getZipEntryAsObject(
1549                    path);
1550
1551                DLPortletDataHandlerImpl.importFileRank(
1552                    context, dlFolderPKs, fileEntryNames, fileRank);
1553            }
1554
1555            List<Element> igFolderEls = root.element("ig-folders").elements(
1556                "folder");
1557
1558            Map<Long, Long> igFolderPKs =
1559                (Map<Long, Long>)context.getNewPrimaryKeysMap(IGFolder.class);
1560
1561            for (Element folderEl : igFolderEls) {
1562                String path = folderEl.attributeValue("path");
1563
1564                if (!context.isPathNotProcessed(path)) {
1565                    continue;
1566                }
1567
1568                IGFolder folder = (IGFolder)context.getZipEntryAsObject(path);
1569
1570                IGPortletDataHandlerImpl.importFolder(
1571                    context, igFolderPKs, folder);
1572            }
1573
1574            List<Element> imageEls = root.element("ig-images").elements(
1575                "image");
1576
1577            for (Element imageEl : imageEls) {
1578                String path = imageEl.attributeValue("path");
1579
1580                if (!context.isPathNotProcessed(path)) {
1581                    continue;
1582                }
1583
1584                IGImage image = (IGImage)context.getZipEntryAsObject(path);
1585
1586                String binPath = imageEl.attributeValue("bin-path");
1587
1588                IGPortletDataHandlerImpl.importImage(
1589                    context, igFolderPKs, image, binPath);
1590            }
1591
1592            return preferences;
1593        }
1594        catch (Exception e) {
1595            throw new PortletDataException(e);
1596        }
1597    }
1598
1599    public boolean isAlwaysExportable() {
1600        return _ALWAYS_EXPORTABLE;
1601    }
1602
1603    public boolean isPublishToLiveByDefault() {
1604        return PropsValues.JOURNAL_PUBLISH_TO_LIVE_BY_DEFAULT;
1605    }
1606
1607    protected static String getArticlePath(
1608        PortletDataContext context, JournalArticle article) {
1609
1610        StringBundler sb = new StringBundler(8);
1611
1612        sb.append(context.getPortletPath(PortletKeys.JOURNAL));
1613        sb.append("/articles/");
1614        sb.append(article.getArticleId());
1615        sb.append(StringPool.SLASH);
1616        sb.append(article.getVersion());
1617        sb.append(StringPool.SLASH);
1618        sb.append(article.getArticleId());
1619        sb.append(".xml");
1620
1621        return sb.toString();
1622    }
1623
1624    protected static String getArticleImagePath(
1625        PortletDataContext context, JournalArticle article) {
1626
1627        StringBundler sb = new StringBundler(6);
1628
1629        sb.append(context.getPortletPath(PortletKeys.JOURNAL));
1630        sb.append("/articles/");
1631        sb.append(article.getArticleId());
1632        sb.append(StringPool.SLASH);
1633        sb.append(article.getVersion());
1634        sb.append(StringPool.SLASH);
1635
1636        return sb.toString();
1637    }
1638
1639    protected static String getArticleImagePath(
1640        PortletDataContext context, JournalArticle article,
1641        JournalArticleImage articleImage, Image image) {
1642
1643        StringBundler sb = new StringBundler(13);
1644
1645        sb.append(context.getPortletPath(PortletKeys.JOURNAL));
1646        sb.append("/articles/");
1647        sb.append(article.getArticleId());
1648        sb.append(StringPool.SLASH);
1649        sb.append(article.getVersion());
1650        sb.append(StringPool.SLASH);
1651        sb.append(articleImage.getElInstanceId());
1652        sb.append(StringPool.UNDERLINE);
1653        sb.append(articleImage.getElName());
1654
1655        if (Validator.isNotNull(articleImage.getLanguageId())) {
1656            sb.append(StringPool.UNDERLINE);
1657            sb.append(articleImage.getLanguageId());
1658        }
1659
1660        sb.append(StringPool.PERIOD);
1661        sb.append(image.getType());
1662
1663        return sb.toString();
1664    }
1665
1666    protected static String getArticleSmallImagePath(
1667            PortletDataContext context, JournalArticle article)
1668        throws PortalException, SystemException {
1669
1670        StringBundler sb = new StringBundler(6);
1671
1672        sb.append(context.getPortletPath(PortletKeys.JOURNAL));
1673        sb.append("/articles/");
1674        sb.append(article.getArticleId());
1675        sb.append("/thumbnail");
1676        sb.append(StringPool.PERIOD);
1677        sb.append(article.getSmallImageType());
1678
1679        return sb.toString();
1680    }
1681
1682    protected static String getFeedPath(
1683        PortletDataContext context, JournalFeed feed) {
1684
1685        StringBundler sb = new StringBundler(4);
1686
1687        sb.append(context.getPortletPath(PortletKeys.JOURNAL));
1688        sb.append("/feeds/");
1689        sb.append(feed.getFeedId());
1690        sb.append(".xml");
1691
1692        return sb.toString();
1693    }
1694
1695    protected static String getImportStructurePath(
1696        PortletDataContext context, String structureId) {
1697
1698        StringBundler sb = new StringBundler(4);
1699
1700        sb.append(context.getSourcePortletPath(PortletKeys.JOURNAL));
1701        sb.append("/structures/");
1702        sb.append(structureId);
1703        sb.append(".xml");
1704
1705        return sb.toString();
1706    }
1707
1708    protected static String getImportTemplatePath(
1709        PortletDataContext context, String templateId) {
1710
1711        StringBundler sb = new StringBundler(4);
1712
1713        sb.append(context.getSourcePortletPath(PortletKeys.JOURNAL));
1714        sb.append("/templates/");
1715        sb.append(templateId);
1716        sb.append(".xml");
1717
1718        return sb.toString();
1719    }
1720
1721    protected static String getImportTemplateSmallImagePath(
1722        PortletDataContext context, String templateId) {
1723
1724        StringBundler sb = new StringBundler(4);
1725
1726        sb.append(context.getSourcePortletPath(PortletKeys.JOURNAL));
1727        sb.append("/templates/thumbnail-");
1728        sb.append(templateId);
1729        sb.append(StringPool.PERIOD);
1730
1731        return sb.toString();
1732    }
1733
1734    protected static String getTemplatePath(
1735        PortletDataContext context, JournalTemplate template) {
1736
1737        StringBundler sb = new StringBundler(4);
1738
1739        sb.append(context.getPortletPath(PortletKeys.JOURNAL));
1740        sb.append("/templates/");
1741        sb.append(template.getTemplateId());
1742        sb.append(".xml");
1743
1744        return sb.toString();
1745    }
1746
1747    protected static String getTemplateSmallImagePath(
1748            PortletDataContext context, JournalTemplate template)
1749        throws PortalException, SystemException {
1750
1751        StringBundler sb = new StringBundler(5);
1752
1753        sb.append(context.getPortletPath(PortletKeys.JOURNAL));
1754        sb.append("/templates/thumbnail-");
1755        sb.append(template.getTemplateId());
1756        sb.append(StringPool.PERIOD);
1757        sb.append(template.getSmallImageType());
1758
1759        return sb.toString();
1760    }
1761
1762    protected static String getStructurePath(
1763        PortletDataContext context, JournalStructure structure) {
1764
1765        StringBundler sb = new StringBundler(4);
1766
1767        sb.append(context.getPortletPath(PortletKeys.JOURNAL));
1768        sb.append("/structures/");
1769        sb.append(structure.getStructureId());
1770        sb.append(".xml");
1771
1772        return sb.toString();
1773    }
1774
1775    private static final boolean _ALWAYS_EXPORTABLE = true;
1776
1777    private static final String _NAMESPACE = "journal";
1778
1779    private static final PortletDataHandlerBoolean _embeddedAssets =
1780        new PortletDataHandlerBoolean(_NAMESPACE, "embedded-assets");
1781
1782    private static final PortletDataHandlerBoolean _images =
1783        new PortletDataHandlerBoolean(_NAMESPACE, "images");
1784
1785    private static final PortletDataHandlerBoolean _categories =
1786        new PortletDataHandlerBoolean(_NAMESPACE, "categories");
1787
1788    private static final PortletDataHandlerBoolean _comments =
1789        new PortletDataHandlerBoolean(_NAMESPACE, "comments");
1790
1791    private static final PortletDataHandlerBoolean _ratings =
1792        new PortletDataHandlerBoolean(_NAMESPACE, "ratings");
1793
1794    private static final PortletDataHandlerBoolean _tags =
1795        new PortletDataHandlerBoolean(_NAMESPACE, "tags");
1796
1797    private static final PortletDataHandlerBoolean _articles =
1798        new PortletDataHandlerBoolean(_NAMESPACE, "articles", true, false,
1799        new PortletDataHandlerControl[] {_images, _comments, _ratings, _tags});
1800
1801    private static final PortletDataHandlerBoolean
1802        _structuresTemplatesAndFeeds = new PortletDataHandlerBoolean(
1803            _NAMESPACE, "structures-templates-and-feeds", true, true);
1804
1805    private static Log _log = LogFactoryUtil.getLog(
1806        JournalPortletDataHandlerImpl.class);
1807
1808}