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