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