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