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