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