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