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