001
014
015 package com.liferay.portlet.journal.util;
016
017 import com.liferay.portal.LocaleException;
018 import com.liferay.portal.kernel.configuration.Filter;
019 import com.liferay.portal.kernel.dao.orm.QueryUtil;
020 import com.liferay.portal.kernel.diff.CompareVersionsException;
021 import com.liferay.portal.kernel.diff.DiffHtmlUtil;
022 import com.liferay.portal.kernel.diff.DiffVersion;
023 import com.liferay.portal.kernel.diff.DiffVersionsInfo;
024 import com.liferay.portal.kernel.exception.PortalException;
025 import com.liferay.portal.kernel.exception.SystemException;
026 import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
027 import com.liferay.portal.kernel.language.LanguageUtil;
028 import com.liferay.portal.kernel.log.Log;
029 import com.liferay.portal.kernel.log.LogFactoryUtil;
030 import com.liferay.portal.kernel.portlet.LiferayPortletRequest;
031 import com.liferay.portal.kernel.portlet.LiferayPortletResponse;
032 import com.liferay.portal.kernel.portlet.LiferayWindowState;
033 import com.liferay.portal.kernel.portlet.PortletRequestModel;
034 import com.liferay.portal.kernel.portlet.ThemeDisplayModel;
035 import com.liferay.portal.kernel.search.Field;
036 import com.liferay.portal.kernel.search.Hits;
037 import com.liferay.portal.kernel.search.Indexer;
038 import com.liferay.portal.kernel.search.IndexerRegistryUtil;
039 import com.liferay.portal.kernel.templateparser.TransformerListener;
040 import com.liferay.portal.kernel.util.ArrayUtil;
041 import com.liferay.portal.kernel.util.CharPool;
042 import com.liferay.portal.kernel.util.Constants;
043 import com.liferay.portal.kernel.util.FriendlyURLNormalizerUtil;
044 import com.liferay.portal.kernel.util.GetterUtil;
045 import com.liferay.portal.kernel.util.HtmlUtil;
046 import com.liferay.portal.kernel.util.HttpUtil;
047 import com.liferay.portal.kernel.util.InstanceFactory;
048 import com.liferay.portal.kernel.util.LocaleUtil;
049 import com.liferay.portal.kernel.util.LocalizationUtil;
050 import com.liferay.portal.kernel.util.OrderByComparator;
051 import com.liferay.portal.kernel.util.ParamUtil;
052 import com.liferay.portal.kernel.util.PropsKeys;
053 import com.liferay.portal.kernel.util.StringBundler;
054 import com.liferay.portal.kernel.util.StringPool;
055 import com.liferay.portal.kernel.util.StringUtil;
056 import com.liferay.portal.kernel.util.Time;
057 import com.liferay.portal.kernel.util.Validator;
058 import com.liferay.portal.kernel.workflow.WorkflowConstants;
059 import com.liferay.portal.kernel.xml.Attribute;
060 import com.liferay.portal.kernel.xml.Document;
061 import com.liferay.portal.kernel.xml.Element;
062 import com.liferay.portal.kernel.xml.Node;
063 import com.liferay.portal.kernel.xml.SAXReaderUtil;
064 import com.liferay.portal.kernel.xml.XPath;
065 import com.liferay.portal.model.Company;
066 import com.liferay.portal.model.Group;
067 import com.liferay.portal.model.Layout;
068 import com.liferay.portal.model.LayoutConstants;
069 import com.liferay.portal.model.LayoutSet;
070 import com.liferay.portal.model.ModelHintsUtil;
071 import com.liferay.portal.model.User;
072 import com.liferay.portal.service.ImageLocalServiceUtil;
073 import com.liferay.portal.service.LayoutLocalServiceUtil;
074 import com.liferay.portal.service.SubscriptionLocalServiceUtil;
075 import com.liferay.portal.service.UserLocalServiceUtil;
076 import com.liferay.portal.templateparser.Transformer;
077 import com.liferay.portal.theme.ThemeDisplay;
078 import com.liferay.portal.util.PortalUtil;
079 import com.liferay.portal.util.PortletKeys;
080 import com.liferay.portal.util.PropsUtil;
081 import com.liferay.portal.util.PropsValues;
082 import com.liferay.portal.util.WebKeys;
083 import com.liferay.portal.webserver.WebServerServletTokenUtil;
084 import com.liferay.portlet.PortalPreferences;
085 import com.liferay.portlet.PortletPreferencesFactoryUtil;
086 import com.liferay.portlet.PortletURLFactoryUtil;
087 import com.liferay.portlet.asset.service.AssetTagLocalServiceUtil;
088 import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
089 import com.liferay.portlet.dynamicdatamapping.model.DDMTemplate;
090 import com.liferay.portlet.dynamicdatamapping.service.DDMTemplateLocalServiceUtil;
091 import com.liferay.portlet.dynamicdatamapping.util.DDMXMLUtil;
092 import com.liferay.portlet.journal.model.JournalArticle;
093 import com.liferay.portlet.journal.model.JournalArticleDisplay;
094 import com.liferay.portlet.journal.model.JournalFolder;
095 import com.liferay.portlet.journal.model.JournalFolderConstants;
096 import com.liferay.portlet.journal.model.JournalStructureConstants;
097 import com.liferay.portlet.journal.service.JournalArticleLocalServiceUtil;
098 import com.liferay.portlet.journal.service.JournalArticleServiceUtil;
099 import com.liferay.portlet.journal.service.JournalFolderLocalServiceUtil;
100 import com.liferay.portlet.journal.util.comparator.ArticleCreateDateComparator;
101 import com.liferay.portlet.journal.util.comparator.ArticleDisplayDateComparator;
102 import com.liferay.portlet.journal.util.comparator.ArticleIDComparator;
103 import com.liferay.portlet.journal.util.comparator.ArticleModifiedDateComparator;
104 import com.liferay.portlet.journal.util.comparator.ArticleReviewDateComparator;
105 import com.liferay.portlet.journal.util.comparator.ArticleTitleComparator;
106 import com.liferay.portlet.journal.util.comparator.ArticleVersionComparator;
107 import com.liferay.util.FiniteUniqueStack;
108
109 import java.util.ArrayList;
110 import java.util.Collections;
111 import java.util.Date;
112 import java.util.HashMap;
113 import java.util.Iterator;
114 import java.util.LinkedHashMap;
115 import java.util.List;
116 import java.util.Locale;
117 import java.util.Map;
118 import java.util.Stack;
119 import java.util.regex.Pattern;
120
121 import javax.portlet.PortletPreferences;
122 import javax.portlet.PortletRequest;
123 import javax.portlet.PortletSession;
124 import javax.portlet.PortletURL;
125 import javax.portlet.RenderResponse;
126
127 import javax.servlet.http.HttpServletRequest;
128
129
136 public class JournalUtil {
137
138 public static final int MAX_STACK_SIZE = 20;
139
140 public static final String[] SELECTED_FIELD_NAMES =
141 {Field.ARTICLE_ID, Field.COMPANY_ID, Field.GROUP_ID, Field.UID};
142
143 public static void addAllReservedEls(
144 Element rootElement, Map<String, String> tokens, JournalArticle article,
145 String languageId, ThemeDisplay themeDisplay) {
146
147 addReservedEl(
148 rootElement, tokens, JournalStructureConstants.RESERVED_ARTICLE_ID,
149 article.getArticleId());
150
151 addReservedEl(
152 rootElement, tokens,
153 JournalStructureConstants.RESERVED_ARTICLE_VERSION,
154 article.getVersion());
155
156 addReservedEl(
157 rootElement, tokens,
158 JournalStructureConstants.RESERVED_ARTICLE_TITLE,
159 article.getTitle(languageId));
160
161 addReservedEl(
162 rootElement, tokens,
163 JournalStructureConstants.RESERVED_ARTICLE_URL_TITLE,
164 article.getUrlTitle());
165
166 addReservedEl(
167 rootElement, tokens,
168 JournalStructureConstants.RESERVED_ARTICLE_DESCRIPTION,
169 article.getDescription(languageId));
170
171 addReservedEl(
172 rootElement, tokens,
173 JournalStructureConstants.RESERVED_ARTICLE_CREATE_DATE,
174 article.getCreateDate());
175
176 addReservedEl(
177 rootElement, tokens,
178 JournalStructureConstants.RESERVED_ARTICLE_MODIFIED_DATE,
179 article.getModifiedDate());
180
181 if (article.getDisplayDate() != null) {
182 addReservedEl(
183 rootElement, tokens,
184 JournalStructureConstants.RESERVED_ARTICLE_DISPLAY_DATE,
185 article.getDisplayDate());
186 }
187
188 String smallImageURL = StringPool.BLANK;
189
190 if (Validator.isNotNull(article.getSmallImageURL())) {
191 smallImageURL = article.getSmallImageURL();
192 }
193 else if ((themeDisplay != null) && article.isSmallImage()) {
194 StringBundler sb = new StringBundler(5);
195
196 sb.append(themeDisplay.getPathImage());
197 sb.append("/journal/article?img_id=");
198 sb.append(article.getSmallImageId());
199 sb.append("&t=");
200 sb.append(
201 WebServerServletTokenUtil.getToken(article.getSmallImageId()));
202
203 smallImageURL = sb.toString();
204 }
205
206 addReservedEl(
207 rootElement, tokens,
208 JournalStructureConstants.RESERVED_ARTICLE_SMALL_IMAGE_URL,
209 smallImageURL);
210
211 String[] assetTagNames = new String[0];
212
213 try {
214 assetTagNames = AssetTagLocalServiceUtil.getTagNames(
215 JournalArticle.class.getName(), article.getResourcePrimKey());
216 }
217 catch (SystemException se) {
218 }
219
220 addReservedEl(
221 rootElement, tokens,
222 JournalStructureConstants.RESERVED_ARTICLE_ASSET_TAG_NAMES,
223 StringUtil.merge(assetTagNames));
224
225 addReservedEl(
226 rootElement, tokens,
227 JournalStructureConstants.RESERVED_ARTICLE_AUTHOR_ID,
228 String.valueOf(article.getUserId()));
229
230 String userName = StringPool.BLANK;
231 String userEmailAddress = StringPool.BLANK;
232 String userComments = StringPool.BLANK;
233 String userJobTitle = StringPool.BLANK;
234
235 try {
236 User user = UserLocalServiceUtil.fetchUserById(article.getUserId());
237
238 if (user != null) {
239 userName = user.getFullName();
240 userEmailAddress = user.getEmailAddress();
241 userComments = user.getComments();
242 userJobTitle = user.getJobTitle();
243 }
244 }
245 catch (SystemException se) {
246 }
247
248 addReservedEl(
249 rootElement, tokens,
250 JournalStructureConstants.RESERVED_ARTICLE_AUTHOR_NAME, userName);
251
252 addReservedEl(
253 rootElement, tokens,
254 JournalStructureConstants.RESERVED_ARTICLE_AUTHOR_EMAIL_ADDRESS,
255 userEmailAddress);
256
257 addReservedEl(
258 rootElement, tokens,
259 JournalStructureConstants.RESERVED_ARTICLE_AUTHOR_COMMENTS,
260 userComments);
261
262 addReservedEl(
263 rootElement, tokens,
264 JournalStructureConstants.RESERVED_ARTICLE_AUTHOR_JOB_TITLE,
265 userJobTitle);
266 }
267
268 public static void addPortletBreadcrumbEntries(
269 JournalArticle article, HttpServletRequest request,
270 RenderResponse renderResponse)
271 throws Exception {
272
273 JournalFolder folder = article.getFolder();
274
275 if (folder.getFolderId() !=
276 JournalFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
277
278 addPortletBreadcrumbEntries(folder, request, renderResponse);
279 }
280
281 JournalArticle unescapedArticle = article.toUnescapedModel();
282
283 PortletURL portletURL = renderResponse.createRenderURL();
284
285 portletURL.setParameter("struts_action", "/article/view_article");
286 portletURL.setParameter(
287 "groupId", String.valueOf(article.getGroupId()));
288 portletURL.setParameter(
289 "articleId", String.valueOf(article.getArticleId()));
290
291 PortalUtil.addPortletBreadcrumbEntry(
292 request, unescapedArticle.getTitle(), portletURL.toString());
293 }
294
295 public static void addPortletBreadcrumbEntries(
296 JournalFolder folder, HttpServletRequest request,
297 LiferayPortletResponse liferayPortletResponse)
298 throws Exception {
299
300 ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
301 com.liferay.portal.kernel.util.WebKeys.THEME_DISPLAY);
302
303 String strutsAction = ParamUtil.getString(request, "struts_action");
304
305 PortletURL portletURL = liferayPortletResponse.createRenderURL();
306
307 if (strutsAction.equals("/journal/select_folder")) {
308 portletURL.setParameter("struts_action", "/journal/select_folder");
309 portletURL.setWindowState(LiferayWindowState.POP_UP);
310
311 PortalUtil.addPortletBreadcrumbEntry(
312 request, themeDisplay.translate("home"), portletURL.toString());
313 }
314 else {
315 portletURL.setParameter("struts_action", "/journal/view");
316
317 Map<String, Object> data = new HashMap<String, Object>();
318
319 data.put("direction-right", Boolean.TRUE.toString());
320 data.put(
321 "folder-id", JournalFolderConstants.DEFAULT_PARENT_FOLDER_ID);
322
323 PortalUtil.addPortletBreadcrumbEntry(
324 request, themeDisplay.translate("home"), portletURL.toString(),
325 data);
326 }
327
328 if (folder == null) {
329 return;
330 }
331
332 List<JournalFolder> ancestorFolders = folder.getAncestors();
333
334 Collections.reverse(ancestorFolders);
335
336 for (JournalFolder ancestorFolder : ancestorFolders) {
337 portletURL.setParameter(
338 "folderId", String.valueOf(ancestorFolder.getFolderId()));
339
340 Map<String, Object> data = new HashMap<String, Object>();
341
342 data.put("direction-right", Boolean.TRUE.toString());
343 data.put("folder-id", ancestorFolder.getFolderId());
344
345 PortalUtil.addPortletBreadcrumbEntry(
346 request, ancestorFolder.getName(), portletURL.toString(), data);
347 }
348
349 portletURL.setParameter(
350 "folderId", String.valueOf(folder.getFolderId()));
351
352 if (folder.getFolderId() !=
353 JournalFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
354
355 JournalFolder unescapedFolder = folder.toUnescapedModel();
356
357 Map<String, Object> data = new HashMap<String, Object>();
358
359 data.put("direction-right", Boolean.TRUE.toString());
360 data.put("folder-id", folder.getFolderId());
361
362 PortalUtil.addPortletBreadcrumbEntry(
363 request, unescapedFolder.getName(), portletURL.toString(),
364 data);
365 }
366 }
367
368 public static void addPortletBreadcrumbEntries(
369 JournalFolder folder, HttpServletRequest request,
370 RenderResponse renderResponse)
371 throws Exception {
372
373 LiferayPortletResponse liferayPortletResponse =
374 (LiferayPortletResponse)renderResponse;
375
376 addPortletBreadcrumbEntries(folder, request, liferayPortletResponse);
377 }
378
379 public static void addPortletBreadcrumbEntries(
380 long folderId, HttpServletRequest request,
381 RenderResponse renderResponse)
382 throws Exception {
383
384 if (folderId == JournalFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
385 return;
386 }
387
388 JournalFolder folder = JournalFolderLocalServiceUtil.getFolder(
389 folderId);
390
391 addPortletBreadcrumbEntries(folder, request, renderResponse);
392 }
393
394 public static void addRecentArticle(
395 PortletRequest portletRequest, JournalArticle article) {
396
397 if (article != null) {
398 Stack<JournalArticle> stack = getRecentArticles(portletRequest);
399
400 stack.push(article);
401 }
402 }
403
404 public static void addRecentDDMStructure(
405 PortletRequest portletRequest, DDMStructure ddmStructure) {
406
407 if (ddmStructure != null) {
408 Stack<DDMStructure> stack = getRecentDDMStructures(portletRequest);
409
410 stack.push(ddmStructure);
411 }
412 }
413
414 public static void addRecentDDMTemplate(
415 PortletRequest portletRequest, DDMTemplate ddmTemplate) {
416
417 if (ddmTemplate != null) {
418 Stack<DDMTemplate> stack = getRecentDDMTemplates(portletRequest);
419
420 stack.push(ddmTemplate);
421 }
422 }
423
424 public static void addReservedEl(
425 Element rootElement, Map<String, String> tokens, String name,
426 Date value) {
427
428 addReservedEl(rootElement, tokens, name, Time.getRFC822(value));
429 }
430
431 public static void addReservedEl(
432 Element rootElement, Map<String, String> tokens, String name,
433 double value) {
434
435 addReservedEl(rootElement, tokens, name, String.valueOf(value));
436 }
437
438 public static void addReservedEl(
439 Element rootElement, Map<String, String> tokens, String name,
440 String value) {
441
442
443
444 if (rootElement != null) {
445 Element dynamicElementElement = rootElement.addElement(
446 "dynamic-element");
447
448 dynamicElementElement.addAttribute("name", name);
449
450 dynamicElementElement.addAttribute("type", "text");
451
452 Element dynamicContentElement = dynamicElementElement.addElement(
453 "dynamic-content");
454
455
456 dynamicContentElement.setText(value);
457 }
458
459
460
461 tokens.put(
462 StringUtil.replace(name, CharPool.DASH, CharPool.UNDERLINE), value);
463 }
464
465 public static String diffHtml(
466 long groupId, String articleId, double sourceVersion,
467 double targetVersion, String languageId,
468 PortletRequestModel portletRequestModel, ThemeDisplay themeDisplay)
469 throws Exception {
470
471 JournalArticle sourceArticle =
472 JournalArticleLocalServiceUtil.getArticle(
473 groupId, articleId, sourceVersion);
474
475 if (!JournalArticleLocalServiceUtil.isRenderable(
476 sourceArticle, portletRequestModel, themeDisplay)) {
477
478 throw new CompareVersionsException(sourceVersion);
479 }
480
481 JournalArticleDisplay sourceArticleDisplay =
482 JournalArticleLocalServiceUtil.getArticleDisplay(
483 sourceArticle, null, Constants.VIEW, languageId, 1,
484 portletRequestModel, themeDisplay);
485
486 JournalArticle targetArticle =
487 JournalArticleLocalServiceUtil.getArticle(
488 groupId, articleId, targetVersion);
489
490 if (!JournalArticleLocalServiceUtil.isRenderable(
491 targetArticle, portletRequestModel, themeDisplay)) {
492
493 throw new CompareVersionsException(targetVersion);
494 }
495
496 JournalArticleDisplay targetArticleDisplay =
497 JournalArticleLocalServiceUtil.getArticleDisplay(
498 targetArticle, null, Constants.VIEW, languageId, 1,
499 portletRequestModel, themeDisplay);
500
501 return DiffHtmlUtil.diff(
502 new UnsyncStringReader(sourceArticleDisplay.getContent()),
503 new UnsyncStringReader(targetArticleDisplay.getContent()));
504 }
505
506 public static String formatVM(String vm) {
507 return vm;
508 }
509
510 public static String getAbsolutePath(
511 PortletRequest portletRequest, long folderId)
512 throws PortalException {
513
514 ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
515 WebKeys.THEME_DISPLAY);
516
517 if (folderId == JournalFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
518 return themeDisplay.translate("home");
519 }
520
521 JournalFolder folder = JournalFolderLocalServiceUtil.getFolder(
522 folderId);
523
524 List<JournalFolder> folders = folder.getAncestors();
525
526 Collections.reverse(folders);
527
528 StringBundler sb = new StringBundler((folders.size() * 3) + 5);
529
530 sb.append(themeDisplay.translate("home"));
531 sb.append(StringPool.SPACE);
532
533 for (JournalFolder curFolder : folders) {
534 sb.append(StringPool.RAQUO_CHAR);
535 sb.append(StringPool.SPACE);
536 sb.append(curFolder.getName());
537 }
538
539 sb.append(StringPool.RAQUO_CHAR);
540 sb.append(StringPool.SPACE);
541 sb.append(folder.getName());
542
543 return sb.toString();
544 }
545
546 public static Layout getArticleLayout(String layoutUuid, long groupId) {
547 if (Validator.isNull(layoutUuid)) {
548 return null;
549 }
550
551
552
553 Layout layout = LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
554 layoutUuid, groupId, false);
555
556 if (layout == null) {
557 layout = LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
558 layoutUuid, groupId, true);
559 }
560
561 return layout;
562 }
563
564 public static OrderByComparator<JournalArticle> getArticleOrderByComparator(
565 String orderByCol, String orderByType) {
566
567 boolean orderByAsc = false;
568
569 if (orderByType.equals("asc")) {
570 orderByAsc = true;
571 }
572
573 OrderByComparator<JournalArticle> orderByComparator = null;
574
575 if (orderByCol.equals("create-date")) {
576 orderByComparator = new ArticleCreateDateComparator(orderByAsc);
577 }
578 else if (orderByCol.equals("display-date")) {
579 orderByComparator = new ArticleDisplayDateComparator(orderByAsc);
580 }
581 else if (orderByCol.equals("id")) {
582 orderByComparator = new ArticleIDComparator(orderByAsc);
583 }
584 else if (orderByCol.equals("modified-date")) {
585 orderByComparator = new ArticleModifiedDateComparator(orderByAsc);
586 }
587 else if (orderByCol.equals("review-date")) {
588 orderByComparator = new ArticleReviewDateComparator(orderByAsc);
589 }
590 else if (orderByCol.equals("title")) {
591 orderByComparator = new ArticleTitleComparator(orderByAsc);
592 }
593 else if (orderByCol.equals("version")) {
594 orderByComparator = new ArticleVersionComparator(orderByAsc);
595 }
596
597 return orderByComparator;
598 }
599
600 public static List<JournalArticle> getArticles(Hits hits)
601 throws PortalException {
602
603 List<com.liferay.portal.kernel.search.Document> documents =
604 hits.toList();
605
606 List<JournalArticle> articles = new ArrayList<JournalArticle>(
607 documents.size());
608
609 for (com.liferay.portal.kernel.search.Document document : documents) {
610 String articleId = document.get(Field.ARTICLE_ID);
611 long groupId = GetterUtil.getLong(document.get(Field.GROUP_ID));
612
613 JournalArticle article =
614 JournalArticleLocalServiceUtil.fetchLatestArticle(
615 groupId, articleId, WorkflowConstants.STATUS_APPROVED);
616
617 if (article == null) {
618 articles = null;
619
620 Indexer indexer = IndexerRegistryUtil.getIndexer(
621 JournalArticle.class);
622
623 long companyId = GetterUtil.getLong(
624 document.get(Field.COMPANY_ID));
625
626 indexer.delete(companyId, document.getUID());
627 }
628 else if (articles != null) {
629 articles.add(article);
630 }
631 }
632
633 return articles;
634 }
635
636 public static DiffVersionsInfo getDiffVersionsInfo(
637 long groupId, String articleId, double sourceVersion,
638 double targetVersion) {
639
640 double previousVersion = 0;
641 double nextVersion = 0;
642
643 List<JournalArticle> articles =
644 JournalArticleServiceUtil.getArticlesByArticleId(
645 groupId, articleId, QueryUtil.ALL_POS, QueryUtil.ALL_POS,
646 new ArticleVersionComparator(true));
647
648 for (JournalArticle article : articles) {
649 if ((article.getVersion() < sourceVersion) &&
650 (article.getVersion() > previousVersion)) {
651
652 previousVersion = article.getVersion();
653 }
654
655 if ((article.getVersion() > targetVersion) &&
656 ((article.getVersion() < nextVersion) || (nextVersion == 0))) {
657
658 nextVersion = article.getVersion();
659 }
660 }
661
662 List<DiffVersion> diffVersions = new ArrayList<DiffVersion>();
663
664 for (JournalArticle article : articles) {
665 DiffVersion diffVersion = new DiffVersion(
666 article.getUserId(), article.getVersion(),
667 article.getModifiedDate());
668
669 diffVersions.add(diffVersion);
670 }
671
672 return new DiffVersionsInfo(diffVersions, nextVersion, previousVersion);
673 }
674
675 public static String getDisplayStyle(
676 LiferayPortletRequest liferayPortletRequest, String[] displayViews) {
677
678 PortalPreferences portalPreferences =
679 PortletPreferencesFactoryUtil.getPortalPreferences(
680 liferayPortletRequest);
681
682 String displayStyle = ParamUtil.getString(
683 liferayPortletRequest, "displayStyle");
684
685 if (Validator.isNull(displayStyle)) {
686 displayStyle = portalPreferences.getValue(
687 PortletKeys.JOURNAL, "display-style",
688 PropsValues.JOURNAL_DEFAULT_DISPLAY_VIEW);
689 }
690 else {
691 if (ArrayUtil.contains(displayViews, displayStyle)) {
692 portalPreferences.setValue(
693 PortletKeys.JOURNAL, "display-style", displayStyle);
694 }
695 }
696
697 if (!ArrayUtil.contains(displayViews, displayStyle)) {
698 displayStyle = displayViews[0];
699 }
700
701 return displayStyle;
702 }
703
704 public static Map<Locale, String> getEmailArticleAddedBodyMap(
705 PortletPreferences preferences) {
706
707 return LocalizationUtil.getLocalizationMap(
708 preferences, "emailArticleAddedBody",
709 PropsKeys.JOURNAL_EMAIL_ARTICLE_ADDED_BODY);
710 }
711
712 public static boolean getEmailArticleAddedEnabled(
713 PortletPreferences preferences) {
714
715 String emailArticleAddedEnabled = preferences.getValue(
716 "emailArticleAddedEnabled", StringPool.BLANK);
717
718 if (Validator.isNotNull(emailArticleAddedEnabled)) {
719 return GetterUtil.getBoolean(emailArticleAddedEnabled);
720 }
721 else {
722 return GetterUtil.getBoolean(
723 PropsUtil.get(PropsKeys.JOURNAL_EMAIL_ARTICLE_ADDED_ENABLED));
724 }
725 }
726
727 public static Map<Locale, String> getEmailArticleAddedSubjectMap(
728 PortletPreferences preferences) {
729
730 return LocalizationUtil.getLocalizationMap(
731 preferences, "emailArticleAddedSubject",
732 PropsKeys.JOURNAL_EMAIL_ARTICLE_ADDED_SUBJECT);
733 }
734
735 public static boolean getEmailArticleAnyEventEnabled(
736 PortletPreferences preferences) {
737
738 if (getEmailArticleAddedEnabled(preferences) ||
739 getEmailArticleApprovalDeniedEnabled(preferences) ||
740 getEmailArticleApprovalGrantedEnabled(preferences) ||
741 getEmailArticleApprovalRequestedEnabled(preferences) ||
742 getEmailArticleReviewEnabled(preferences) ||
743 getEmailArticleUpdatedEnabled(preferences)) {
744
745 return true;
746 }
747
748 return false;
749 }
750
751 public static Map<Locale, String> getEmailArticleApprovalDeniedBodyMap(
752 PortletPreferences preferences) {
753
754 return LocalizationUtil.getLocalizationMap(
755 preferences, "emailArticleApprovalDeniedBody",
756 PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_DENIED_BODY);
757 }
758
759 public static boolean getEmailArticleApprovalDeniedEnabled(
760 PortletPreferences preferences) {
761
762 String emailArticleApprovalDeniedEnabled = preferences.getValue(
763 "emailArticleApprovalDeniedEnabled", StringPool.BLANK);
764
765 if (Validator.isNotNull(emailArticleApprovalDeniedEnabled)) {
766 return GetterUtil.getBoolean(emailArticleApprovalDeniedEnabled);
767 }
768 else {
769 return GetterUtil.getBoolean(
770 PropsUtil.get(
771 PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_DENIED_ENABLED));
772 }
773 }
774
775 public static Map<Locale, String> getEmailArticleApprovalDeniedSubjectMap(
776 PortletPreferences preferences) {
777
778 return LocalizationUtil.getLocalizationMap(
779 preferences, "emailArticleApprovalDeniedSubject",
780 PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_DENIED_SUBJECT);
781 }
782
783 public static Map<Locale, String> getEmailArticleApprovalGrantedBodyMap(
784 PortletPreferences preferences) {
785
786 return LocalizationUtil.getLocalizationMap(
787 preferences, "emailArticleApprovalGrantedBody",
788 PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_GRANTED_BODY);
789 }
790
791 public static boolean getEmailArticleApprovalGrantedEnabled(
792 PortletPreferences preferences) {
793
794 String emailArticleApprovalGrantedEnabled = preferences.getValue(
795 "emailArticleApprovalGrantedEnabled", StringPool.BLANK);
796
797 if (Validator.isNotNull(emailArticleApprovalGrantedEnabled)) {
798 return GetterUtil.getBoolean(emailArticleApprovalGrantedEnabled);
799 }
800 else {
801 return GetterUtil.getBoolean(
802 PropsUtil.get(
803 PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_GRANTED_ENABLED));
804 }
805 }
806
807 public static Map<Locale, String> getEmailArticleApprovalGrantedSubjectMap(
808 PortletPreferences preferences) {
809
810 return LocalizationUtil.getLocalizationMap(
811 preferences, "emailArticleApprovalGrantedSubject",
812 PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_GRANTED_SUBJECT);
813 }
814
815 public static Map<Locale, String> getEmailArticleApprovalRequestedBodyMap(
816 PortletPreferences preferences) {
817
818 return LocalizationUtil.getLocalizationMap(
819 preferences, "emailArticleApprovalRequestedBody",
820 PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_REQUESTED_BODY);
821 }
822
823 public static boolean getEmailArticleApprovalRequestedEnabled(
824 PortletPreferences preferences) {
825
826 String emailArticleApprovalRequestedEnabled = preferences.getValue(
827 "emailArticleApprovalRequestedEnabled", StringPool.BLANK);
828
829 if (Validator.isNotNull(emailArticleApprovalRequestedEnabled)) {
830 return GetterUtil.getBoolean(emailArticleApprovalRequestedEnabled);
831 }
832 else {
833 return GetterUtil.getBoolean(
834 PropsUtil.get(
835 PropsKeys.
836 JOURNAL_EMAIL_ARTICLE_APPROVAL_REQUESTED_ENABLED));
837 }
838 }
839
840 public static Map<Locale, String>
841 getEmailArticleApprovalRequestedSubjectMap(
842 PortletPreferences preferences) {
843
844 return LocalizationUtil.getLocalizationMap(
845 preferences, "emailArticleApprovalRequestedSubject",
846 PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_REQUESTED_SUBJECT);
847 }
848
849 public static Map<Locale, String> getEmailArticleReviewBodyMap(
850 PortletPreferences preferences) {
851
852 return LocalizationUtil.getLocalizationMap(
853 preferences, "emailArticleReviewBody",
854 PropsKeys.JOURNAL_EMAIL_ARTICLE_REVIEW_BODY);
855 }
856
857 public static boolean getEmailArticleReviewEnabled(
858 PortletPreferences preferences) {
859
860 String emailArticleReviewEnabled = preferences.getValue(
861 "emailArticleReviewEnabled", StringPool.BLANK);
862
863 if (Validator.isNotNull(emailArticleReviewEnabled)) {
864 return GetterUtil.getBoolean(emailArticleReviewEnabled);
865 }
866 else {
867 return GetterUtil.getBoolean(
868 PropsUtil.get(PropsKeys.JOURNAL_EMAIL_ARTICLE_REVIEW_ENABLED));
869 }
870 }
871
872 public static Map<Locale, String> getEmailArticleReviewSubjectMap(
873 PortletPreferences preferences) {
874
875 return LocalizationUtil.getLocalizationMap(
876 preferences, "emailArticleReviewSubject",
877 PropsKeys.JOURNAL_EMAIL_ARTICLE_REVIEW_SUBJECT);
878 }
879
880 public static Map<Locale, String> getEmailArticleUpdatedBodyMap(
881 PortletPreferences preferences) {
882
883 return LocalizationUtil.getLocalizationMap(
884 preferences, "emailArticleUpdatedBody",
885 PropsKeys.JOURNAL_EMAIL_ARTICLE_UPDATED_BODY);
886 }
887
888 public static boolean getEmailArticleUpdatedEnabled(
889 PortletPreferences preferences) {
890
891 String emailArticleUpdatedEnabled = preferences.getValue(
892 "emailArticleUpdatedEnabled", StringPool.BLANK);
893
894 if (Validator.isNotNull(emailArticleUpdatedEnabled)) {
895 return GetterUtil.getBoolean(emailArticleUpdatedEnabled);
896 }
897 else {
898 return GetterUtil.getBoolean(
899 PropsUtil.get(PropsKeys.JOURNAL_EMAIL_ARTICLE_UPDATED_ENABLED));
900 }
901 }
902
903 public static Map<Locale, String> getEmailArticleUpdatedSubjectMap(
904 PortletPreferences preferences) {
905
906 return LocalizationUtil.getLocalizationMap(
907 preferences, "emailArticleUpdatedSubject",
908 PropsKeys.JOURNAL_EMAIL_ARTICLE_UPDATED_SUBJECT);
909 }
910
911 public static Map<String, String> getEmailDefinitionTerms(
912 PortletRequest portletRequest, String emailFromAddress,
913 String emailFromName) {
914
915 ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
916 WebKeys.THEME_DISPLAY);
917
918 Map<String, String> definitionTerms =
919 new LinkedHashMap<String, String>();
920
921 definitionTerms.put(
922 "[$ARTICLE_CONTENT]",
923 LanguageUtil.get(themeDisplay.getLocale(), "the-web-content"));
924 definitionTerms.put(
925 "[$ARTICLE_DIFFS$]",
926 LanguageUtil.get(
927 themeDisplay.getLocale(),
928 "the-web-content-compared-with-the-previous-version-web-" +
929 "content"));
930 definitionTerms.put(
931 "[$ARTICLE_ID$]",
932 LanguageUtil.get(themeDisplay.getLocale(), "the-web-content-id"));
933 definitionTerms.put(
934 "[$ARTICLE_TITLE$]",
935 LanguageUtil.get(
936 themeDisplay.getLocale(), "the-web-content-title"));
937 definitionTerms.put(
938 "[$ARTICLE_URL$]",
939 LanguageUtil.get(themeDisplay.getLocale(), "the-web-content-url"));
940 definitionTerms.put(
941 "[$ARTICLE_VERSION$]",
942 LanguageUtil.get(
943 themeDisplay.getLocale(), "the-web-content-version"));
944 definitionTerms.put(
945 "[$FROM_ADDRESS$]", HtmlUtil.escape(emailFromAddress));
946 definitionTerms.put("[$FROM_NAME$]", HtmlUtil.escape(emailFromName));
947
948 Company company = themeDisplay.getCompany();
949
950 definitionTerms.put("[$PORTAL_URL$]", company.getVirtualHostname());
951
952 definitionTerms.put(
953 "[$PORTLET_NAME$]", PortalUtil.getPortletTitle(portletRequest));
954 definitionTerms.put(
955 "[$TO_ADDRESS$]",
956 LanguageUtil.get(
957 themeDisplay.getLocale(),
958 "the-address-of-the-email-recipient"));
959 definitionTerms.put(
960 "[$TO_NAME$]",
961 LanguageUtil.get(
962 themeDisplay.getLocale(), "the-name-of-the-email-recipient"));
963
964 return definitionTerms;
965 }
966
967 public static String getEmailFromAddress(
968 PortletPreferences preferences, long companyId) {
969
970 return PortalUtil.getEmailFromAddress(
971 preferences, companyId, PropsValues.JOURNAL_EMAIL_FROM_ADDRESS);
972 }
973
974 public static String getEmailFromName(
975 PortletPreferences preferences, long companyId) {
976
977 return PortalUtil.getEmailFromName(
978 preferences, companyId, PropsValues.JOURNAL_EMAIL_FROM_NAME);
979 }
980
981 public static String getJournalControlPanelLink(
982 PortletRequest portletRequest, long folderId)
983 throws PortalException {
984
985 ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
986 WebKeys.THEME_DISPLAY);
987
988 PortletURL portletURL = PortletURLFactoryUtil.create(
989 portletRequest, PortletKeys.JOURNAL,
990 PortalUtil.getControlPanelPlid(themeDisplay.getCompanyId()),
991 PortletRequest.RENDER_PHASE);
992
993 portletURL.setParameter("struts_action", "/journal/view");
994 portletURL.setParameter("folderId", String.valueOf(folderId));
995
996 return portletURL.toString();
997 }
998
999 public static long getPreviewPlid(
1000 JournalArticle article, ThemeDisplay themeDisplay)
1001 throws Exception {
1002
1003 if (article != null) {
1004 Layout layout = article.getLayout();
1005
1006 if (layout != null) {
1007 return layout.getPlid();
1008 }
1009 }
1010
1011 Layout layout = LayoutLocalServiceUtil.fetchFirstLayout(
1012 themeDisplay.getScopeGroupId(), false,
1013 LayoutConstants.DEFAULT_PARENT_LAYOUT_ID);
1014
1015 if (layout == null) {
1016 layout = LayoutLocalServiceUtil.fetchFirstLayout(
1017 themeDisplay.getScopeGroupId(), true,
1018 LayoutConstants.DEFAULT_PARENT_LAYOUT_ID);
1019 }
1020
1021 if (layout != null) {
1022 return layout.getPlid();
1023 }
1024
1025 return themeDisplay.getPlid();
1026 }
1027
1028 public static Stack<JournalArticle> getRecentArticles(
1029 PortletRequest portletRequest) {
1030
1031 PortletSession portletSession = portletRequest.getPortletSession();
1032
1033 Stack<JournalArticle> recentArticles =
1034 (Stack<JournalArticle>)portletSession.getAttribute(
1035 WebKeys.JOURNAL_RECENT_ARTICLES);
1036
1037 if (recentArticles == null) {
1038 recentArticles = new FiniteUniqueStack<JournalArticle>(
1039 MAX_STACK_SIZE);
1040
1041 portletSession.setAttribute(
1042 WebKeys.JOURNAL_RECENT_ARTICLES, recentArticles);
1043 }
1044
1045 return recentArticles;
1046 }
1047
1048 public static Stack<DDMStructure> getRecentDDMStructures(
1049 PortletRequest portletRequest) {
1050
1051 PortletSession portletSession = portletRequest.getPortletSession();
1052
1053 Stack<DDMStructure> recentDDMStructures =
1054 (Stack<DDMStructure>)portletSession.getAttribute(
1055 WebKeys.JOURNAL_RECENT_DYNAMIC_DATA_MAPPING_STRUCTURES);
1056
1057 if (recentDDMStructures == null) {
1058 recentDDMStructures = new FiniteUniqueStack<DDMStructure>(
1059 MAX_STACK_SIZE);
1060
1061 portletSession.setAttribute(
1062 WebKeys.JOURNAL_RECENT_DYNAMIC_DATA_MAPPING_STRUCTURES,
1063 recentDDMStructures);
1064 }
1065
1066 return recentDDMStructures;
1067 }
1068
1069 public static Stack<DDMTemplate> getRecentDDMTemplates(
1070 PortletRequest portletRequest) {
1071
1072 PortletSession portletSession = portletRequest.getPortletSession();
1073
1074 Stack<DDMTemplate> recentDDMTemplates =
1075 (Stack<DDMTemplate>)portletSession.getAttribute(
1076 WebKeys.JOURNAL_RECENT_DYNAMIC_DATA_MAPPING_TEMPLATES);
1077
1078 if (recentDDMTemplates == null) {
1079 recentDDMTemplates = new FiniteUniqueStack<DDMTemplate>(
1080 MAX_STACK_SIZE);
1081
1082 portletSession.setAttribute(
1083 WebKeys.JOURNAL_RECENT_DYNAMIC_DATA_MAPPING_TEMPLATES,
1084 recentDDMTemplates);
1085 }
1086
1087 return recentDDMTemplates;
1088 }
1089
1090 public static int getRestrictionType(long folderId) {
1091 int restrictionType = JournalFolderConstants.RESTRICTION_TYPE_INHERIT;
1092
1093 JournalFolder folder = JournalFolderLocalServiceUtil.fetchFolder(
1094 folderId);
1095
1096 if (folder != null) {
1097 restrictionType = folder.getRestrictionType();
1098 }
1099
1100 return restrictionType;
1101 }
1102
1103 public static String getTemplateScript(
1104 DDMTemplate ddmTemplate, Map<String, String> tokens, String languageId,
1105 boolean transform) {
1106
1107 String script = ddmTemplate.getScript();
1108
1109 if (!transform) {
1110 return script;
1111 }
1112
1113 String[] transformerListenerClassNames = PropsUtil.getArray(
1114 PropsKeys.JOURNAL_TRANSFORMER_LISTENER);
1115
1116 for (String transformerListenerClassName :
1117 transformerListenerClassNames) {
1118
1119 TransformerListener transformerListener = null;
1120
1121 try {
1122 transformerListener =
1123 (TransformerListener)InstanceFactory.newInstance(
1124 transformerListenerClassName);
1125
1126 continue;
1127 }
1128 catch (Exception e) {
1129 _log.error(e, e);
1130 }
1131
1132 script = transformerListener.onScript(
1133 script, (Document)null, languageId, tokens);
1134 }
1135
1136 return script;
1137 }
1138
1139 public static String getTemplateScript(
1140 long groupId, String ddmTemplateKey, Map<String, String> tokens,
1141 String languageId)
1142 throws PortalException {
1143
1144 return getTemplateScript(
1145 groupId, ddmTemplateKey, tokens, languageId, true);
1146 }
1147
1148 public static String getTemplateScript(
1149 long groupId, String ddmTemplateKey, Map<String, String> tokens,
1150 String languageId, boolean transform)
1151 throws PortalException {
1152
1153 DDMTemplate ddmTemplate = DDMTemplateLocalServiceUtil.getTemplate(
1154 groupId, PortalUtil.getClassNameId(DDMStructure.class),
1155 ddmTemplateKey, true);
1156
1157 return getTemplateScript(ddmTemplate, tokens, languageId, transform);
1158 }
1159
1160 public static Map<String, String> getTokens(
1161 long articleGroupId, PortletRequestModel portletRequestModel,
1162 ThemeDisplay themeDisplay)
1163 throws PortalException {
1164
1165 Map<String, String> tokens = new HashMap<String, String>();
1166
1167 if (themeDisplay != null) {
1168 _populateTokens(tokens, articleGroupId, themeDisplay);
1169 }
1170 else if (portletRequestModel != null) {
1171 ThemeDisplayModel themeDisplayModel =
1172 portletRequestModel.getThemeDisplayModel();
1173
1174 if (themeDisplayModel != null) {
1175 try {
1176 _populateTokens(tokens, articleGroupId, themeDisplayModel);
1177 }
1178 catch (Exception e) {
1179 if (_log.isWarnEnabled()) {
1180 _log.warn(e, e);
1181 }
1182 }
1183 }
1184 }
1185
1186 return tokens;
1187 }
1188
1189 public static Map<String, String> getTokens(
1190 long articleGroupId, ThemeDisplay themeDisplay)
1191 throws PortalException {
1192
1193 return getTokens(
1194 articleGroupId, (PortletRequestModel)null, themeDisplay);
1195 }
1196
1197 public static String getUrlTitle(long id, String title) {
1198 if (title == null) {
1199 return String.valueOf(id);
1200 }
1201
1202 title = StringUtil.toLowerCase(title.trim());
1203
1204 if (Validator.isNull(title) || Validator.isNumber(title) ||
1205 title.equals("rss")) {
1206
1207 title = String.valueOf(id);
1208 }
1209 else {
1210 title = FriendlyURLNormalizerUtil.normalize(
1211 title, _friendlyURLPattern);
1212 }
1213
1214 return ModelHintsUtil.trimString(
1215 JournalArticle.class.getName(), "urlTitle", title);
1216 }
1217
1218 public static boolean isSubscribedToFolder(
1219 long companyId, long groupId, long userId, long folderId)
1220 throws PortalException {
1221
1222 return isSubscribedToFolder(companyId, groupId, userId, folderId, true);
1223 }
1224
1225 public static boolean isSubscribedToFolder(
1226 long companyId, long groupId, long userId, long folderId,
1227 boolean recursive)
1228 throws PortalException {
1229
1230 List<Long> ancestorFolderIds = new ArrayList<Long>();
1231
1232 if (folderId != JournalFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
1233 JournalFolder folder = JournalFolderLocalServiceUtil.getFolder(
1234 folderId);
1235
1236 ancestorFolderIds.add(folderId);
1237
1238 if (recursive) {
1239 ancestorFolderIds.addAll(folder.getAncestorFolderIds());
1240
1241 ancestorFolderIds.add(groupId);
1242 }
1243 }
1244 else {
1245 ancestorFolderIds.add(groupId);
1246 }
1247
1248 return SubscriptionLocalServiceUtil.isSubscribed(
1249 companyId, userId, JournalFolder.class.getName(),
1250 ArrayUtil.toLongArray(ancestorFolderIds));
1251 }
1252
1253 public static boolean isSubscribedToStructure(
1254 long companyId, long groupId, long userId, long ddmStructureId) {
1255
1256 return SubscriptionLocalServiceUtil.isSubscribed(
1257 companyId, userId, DDMStructure.class.getName(), ddmStructureId);
1258 }
1259
1260 public static String mergeArticleContent(
1261 String curContent, String newContent, boolean removeNullElements) {
1262
1263 try {
1264 Document curDocument = SAXReaderUtil.read(curContent);
1265 Document newDocument = SAXReaderUtil.read(newContent);
1266
1267 Element curRootElement = curDocument.getRootElement();
1268 Element newRootElement = newDocument.getRootElement();
1269
1270 curRootElement.addAttribute(
1271 "default-locale",
1272 newRootElement.attributeValue("default-locale"));
1273 curRootElement.addAttribute(
1274 "available-locales",
1275 newRootElement.attributeValue("available-locales"));
1276
1277 _mergeArticleContentUpdate(
1278 curDocument, newRootElement,
1279 LocaleUtil.toLanguageId(LocaleUtil.getSiteDefault()));
1280
1281 if (removeNullElements) {
1282 _mergeArticleContentDelete(curRootElement, newDocument);
1283 }
1284
1285 curContent = DDMXMLUtil.formatXML(curDocument);
1286 }
1287 catch (Exception e) {
1288 _log.error(e, e);
1289 }
1290
1291 return curContent;
1292 }
1293
1294 public static String prepareLocalizedContentForImport(
1295 String content, Locale defaultImportLocale)
1296 throws LocaleException {
1297
1298 try {
1299 Document oldDocument = SAXReaderUtil.read(content);
1300
1301 Document newDocument = SAXReaderUtil.read(content);
1302
1303 Element newRootElement = newDocument.getRootElement();
1304
1305 Attribute availableLocalesAttribute = newRootElement.attribute(
1306 "available-locales");
1307
1308 String defaultImportLanguageId = LocaleUtil.toLanguageId(
1309 defaultImportLocale);
1310
1311 if (!StringUtil.contains(
1312 availableLocalesAttribute.getValue(),
1313 defaultImportLanguageId)) {
1314
1315 availableLocalesAttribute.setValue(
1316 availableLocalesAttribute.getValue() + StringPool.COMMA +
1317 defaultImportLanguageId);
1318
1319 _mergeArticleContentUpdate(
1320 oldDocument, newRootElement,
1321 LocaleUtil.toLanguageId(defaultImportLocale));
1322
1323 content = DDMXMLUtil.formatXML(newDocument);
1324 }
1325
1326 Attribute defaultLocaleAttribute = newRootElement.attribute(
1327 "default-locale");
1328
1329 Locale defaultContentLocale = LocaleUtil.fromLanguageId(
1330 defaultLocaleAttribute.getValue());
1331
1332 if (!LocaleUtil.equals(defaultContentLocale, defaultImportLocale)) {
1333 defaultLocaleAttribute.setValue(defaultImportLanguageId);
1334
1335 content = DDMXMLUtil.formatXML(newDocument);
1336 }
1337 }
1338 catch (Exception e) {
1339 throw new LocaleException(
1340 LocaleException.TYPE_CONTENT,
1341 "The locale " + defaultImportLocale + " is not available");
1342 }
1343
1344 return content;
1345 }
1346
1347 public static String removeArticleLocale(
1348 Document document, String content, String languageId) {
1349
1350 try {
1351 Element rootElement = document.getRootElement();
1352
1353 String availableLocales = rootElement.attributeValue(
1354 "available-locales");
1355
1356 if (availableLocales == null) {
1357 return content;
1358 }
1359
1360 availableLocales = StringUtil.removeFromList(
1361 availableLocales, languageId);
1362
1363 if (availableLocales.endsWith(",")) {
1364 availableLocales = availableLocales.substring(
1365 0, availableLocales.length() - 1);
1366 }
1367
1368 rootElement.addAttribute("available-locales", availableLocales);
1369
1370 removeArticleLocale(rootElement, languageId);
1371
1372 content = DDMXMLUtil.formatXML(document);
1373 }
1374 catch (Exception e) {
1375 _log.error(e, e);
1376 }
1377
1378 return content;
1379 }
1380
1381 public static void removeArticleLocale(Element element, String languageId)
1382 throws PortalException {
1383
1384 for (Element dynamicElementElement :
1385 element.elements("dynamic-element")) {
1386
1387 for (Element dynamicContentElement :
1388 dynamicElementElement.elements("dynamic-content")) {
1389
1390 String curLanguageId = GetterUtil.getString(
1391 dynamicContentElement.attributeValue("language-id"));
1392
1393 if (curLanguageId.equals(languageId)) {
1394 long id = GetterUtil.getLong(
1395 dynamicContentElement.attributeValue("id"));
1396
1397 if (id > 0) {
1398 ImageLocalServiceUtil.deleteImage(id);
1399 }
1400
1401 dynamicContentElement.detach();
1402 }
1403 }
1404
1405 removeArticleLocale(dynamicElementElement, languageId);
1406 }
1407 }
1408
1409 public static String removeOldContent(String content, String xsd) {
1410 try {
1411 Document contentDoc = SAXReaderUtil.read(content);
1412 Document xsdDoc = SAXReaderUtil.read(xsd);
1413
1414 Element contentRoot = contentDoc.getRootElement();
1415
1416 Stack<String> path = new Stack<String>();
1417
1418 path.push(contentRoot.getName());
1419
1420 _removeOldContent(path, contentRoot, xsdDoc);
1421
1422 content = DDMXMLUtil.formatXML(contentDoc);
1423 }
1424 catch (Exception e) {
1425 _log.error(e, e);
1426 }
1427
1428 return content;
1429 }
1430
1431 public static void removeRecentArticle(
1432 PortletRequest portletRequest, String articleId) {
1433
1434 removeRecentArticle(portletRequest, articleId, 0);
1435 }
1436
1437 public static void removeRecentArticle(
1438 PortletRequest portletRequest, String articleId, double version) {
1439
1440 Stack<JournalArticle> stack = getRecentArticles(portletRequest);
1441
1442 Iterator<JournalArticle> itr = stack.iterator();
1443
1444 while (itr.hasNext()) {
1445 JournalArticle journalArticle = itr.next();
1446
1447 if (journalArticle.getArticleId().equals(articleId) &&
1448 ((journalArticle.getVersion() == version) ||
1449 (version == 0))) {
1450
1451 itr.remove();
1452 }
1453 }
1454 }
1455
1456 public static void removeRecentDDMStructure(
1457 PortletRequest portletRequest, String ddmStructureKey) {
1458
1459 Stack<DDMStructure> stack = getRecentDDMStructures(portletRequest);
1460
1461 Iterator<DDMStructure> itr = stack.iterator();
1462
1463 while (itr.hasNext()) {
1464 DDMStructure ddmStructure = itr.next();
1465
1466 if (ddmStructureKey.equals(ddmStructure.getStructureKey())) {
1467 itr.remove();
1468
1469 break;
1470 }
1471 }
1472 }
1473
1474 public static void removeRecentDDMTemplate(
1475 PortletRequest portletRequest, String ddmTemplateKey) {
1476
1477 Stack<DDMTemplate> stack = getRecentDDMTemplates(portletRequest);
1478
1479 Iterator<DDMTemplate> itr = stack.iterator();
1480
1481 while (itr.hasNext()) {
1482 DDMTemplate ddmTemplate = itr.next();
1483
1484 if (ddmTemplateKey.equals(ddmTemplate.getTemplateKey())) {
1485 itr.remove();
1486
1487 break;
1488 }
1489 }
1490 }
1491
1492 public static String transform(
1493 ThemeDisplay themeDisplay, Map<String, String> tokens,
1494 String viewMode, String languageId, Document document,
1495 PortletRequestModel portletRequestModel, String script,
1496 String langType)
1497 throws Exception {
1498
1499 return transform(
1500 themeDisplay, tokens, viewMode, languageId, document,
1501 portletRequestModel, script, langType, false);
1502 }
1503
1504 public static String transform(
1505 ThemeDisplay themeDisplay, Map<String, String> tokens,
1506 String viewMode, String languageId, Document document,
1507 PortletRequestModel portletRequestModel, String script,
1508 String langType, boolean propagateException)
1509 throws Exception {
1510
1511 return _transformer.transform(
1512 themeDisplay, tokens, viewMode, languageId, document,
1513 portletRequestModel, script, langType, propagateException);
1514 }
1515
1516 private static void _addElementOptions(
1517 Element curContentElement, Element newContentElement) {
1518
1519 List<Element> newElementOptions = newContentElement.elements("option");
1520
1521 for (Element newElementOption : newElementOptions) {
1522 Element curElementOption = SAXReaderUtil.createElement("option");
1523
1524 curElementOption.addCDATA(newElementOption.getText());
1525
1526 curContentElement.add(curElementOption);
1527 }
1528 }
1529
1530 private static Element _getElementByInstanceId(
1531 Document document, String instanceId) {
1532
1533 if (Validator.isNull(instanceId)) {
1534 return null;
1535 }
1536
1537 XPath xPathSelector = SAXReaderUtil.createXPath(
1538 "
1539 HtmlUtil.escapeXPathAttribute(instanceId) + "]");
1540
1541 List<Node> nodes = xPathSelector.selectNodes(document);
1542
1543 if (nodes.size() == 1) {
1544 return (Element)nodes.get(0);
1545 }
1546 else {
1547 return null;
1548 }
1549 }
1550
1551 private static void _mergeArticleContentDelete(
1552 Element curParentElement, Document newDocument)
1553 throws Exception {
1554
1555 List<Element> curElements = curParentElement.elements(
1556 "dynamic-element");
1557
1558 for (int i = 0; i < curElements.size(); i++) {
1559 Element curElement = curElements.get(i);
1560
1561 _mergeArticleContentDelete(curElement, newDocument);
1562
1563 String instanceId = curElement.attributeValue("instance-id");
1564
1565 Element newElement = _getElementByInstanceId(
1566 newDocument, instanceId);
1567
1568 if (newElement == null) {
1569 curElement.detach();
1570 }
1571 }
1572 }
1573
1574 private static void _mergeArticleContentUpdate(
1575 Document curDocument, Element newParentElement, Element newElement,
1576 int pos, String defaultLocale)
1577 throws Exception {
1578
1579 _mergeArticleContentUpdate(curDocument, newElement, defaultLocale);
1580
1581 String instanceId = newElement.attributeValue("instance-id");
1582
1583 Element curElement = _getElementByInstanceId(curDocument, instanceId);
1584
1585 if (curElement != null) {
1586 _mergeArticleContentUpdate(curElement, newElement, defaultLocale);
1587 }
1588 else {
1589 String parentInstanceId = newParentElement.attributeValue(
1590 "instance-id");
1591
1592 if (Validator.isNull(parentInstanceId)) {
1593 Element curRoot = curDocument.getRootElement();
1594
1595 List<Element> curRootElements = curRoot.elements();
1596
1597 curRootElements.add(pos, newElement.createCopy());
1598 }
1599 else {
1600 Element curParentElement = _getElementByInstanceId(
1601 curDocument, parentInstanceId);
1602
1603 if (curParentElement != null) {
1604 List<Element> curParentElements =
1605 curParentElement.elements();
1606
1607 curParentElements.add(pos, newElement.createCopy());
1608 }
1609 }
1610 }
1611 }
1612
1613 private static void _mergeArticleContentUpdate(
1614 Document curDocument, Element newParentElement,
1615 String defaultLocale)
1616 throws Exception {
1617
1618 List<Element> newElements = newParentElement.elements(
1619 "dynamic-element");
1620
1621 for (int i = 0; i < newElements.size(); i++) {
1622 Element newElement = newElements.get(i);
1623
1624 _mergeArticleContentUpdate(
1625 curDocument, newParentElement, newElement, i, defaultLocale);
1626 }
1627 }
1628
1629 private static void _mergeArticleContentUpdate(
1630 Element curElement, Element newElement, String defaultLocale) {
1631
1632 Attribute curTypeAttribute = curElement.attribute("type");
1633 Attribute newTypeAttribute = newElement.attribute("type");
1634
1635 curTypeAttribute.setValue(newTypeAttribute.getValue());
1636
1637 Attribute curIndexTypeAttribute = curElement.attribute("index-type");
1638 Attribute newIndexTypeAttribute = newElement.attribute("index-type");
1639
1640 if (newIndexTypeAttribute != null) {
1641 if (curIndexTypeAttribute == null) {
1642 curElement.addAttribute(
1643 "index-type", newIndexTypeAttribute.getValue());
1644 }
1645 else {
1646 curIndexTypeAttribute.setValue(
1647 newIndexTypeAttribute.getValue());
1648 }
1649 }
1650
1651 List<Element> elements = newElement.elements("dynamic-content");
1652
1653 Element newContentElement = elements.get(0);
1654
1655 String newLanguageId = newContentElement.attributeValue("language-id");
1656 String newValue = newContentElement.getText();
1657
1658 String indexType = newElement.attributeValue("index-type");
1659
1660 if (Validator.isNotNull(indexType)) {
1661 curElement.addAttribute("index-type", indexType);
1662 }
1663
1664 List<Element> curContentElements = curElement.elements(
1665 "dynamic-content");
1666
1667 if (Validator.isNull(newLanguageId)) {
1668 for (Element curContentElement : curContentElements) {
1669 curContentElement.detach();
1670 }
1671
1672 Element curContentElement = SAXReaderUtil.createElement(
1673 "dynamic-content");
1674
1675 if (newContentElement.element("option") != null) {
1676 _addElementOptions(curContentElement, newContentElement);
1677 }
1678 else {
1679 curContentElement.addCDATA(newValue);
1680 }
1681
1682 curElement.add(curContentElement);
1683 }
1684 else {
1685 boolean alreadyExists = false;
1686
1687 for (Element curContentElement : curContentElements) {
1688 String curLanguageId = curContentElement.attributeValue(
1689 "language-id");
1690
1691 if (newLanguageId.equals(curLanguageId)) {
1692 alreadyExists = true;
1693
1694 curContentElement.clearContent();
1695
1696 if (newContentElement.element("option") != null) {
1697 _addElementOptions(
1698 curContentElement, newContentElement);
1699 }
1700 else {
1701 curContentElement.addCDATA(newValue);
1702 }
1703
1704 break;
1705 }
1706 }
1707
1708 if (!alreadyExists) {
1709 Element curContentElement = curContentElements.get(0);
1710
1711 String curLanguageId = curContentElement.attributeValue(
1712 "language-id");
1713
1714 if (Validator.isNull(curLanguageId)) {
1715 if (newLanguageId.equals(defaultLocale)) {
1716 curContentElement.clearContent();
1717
1718 if (newContentElement.element("option") != null) {
1719 _addElementOptions(
1720 curContentElement, newContentElement);
1721 }
1722 else {
1723 curContentElement.addCDATA(newValue);
1724 }
1725 }
1726 else {
1727 curElement.add(newContentElement.createCopy());
1728 }
1729
1730 curContentElement.addAttribute(
1731 "language-id", defaultLocale);
1732 }
1733 else {
1734 curElement.add(newContentElement.createCopy());
1735 }
1736 }
1737 }
1738 }
1739
1740 private static void _populateCustomTokens(Map<String, String> tokens) {
1741 if (_customTokens == null) {
1742 synchronized (JournalUtil.class) {
1743 _customTokens = new HashMap<String, String>();
1744
1745 for (String customToken :
1746 PropsValues.JOURNAL_ARTICLE_CUSTOM_TOKENS) {
1747
1748 String value = PropsUtil.get(
1749 PropsKeys.JOURNAL_ARTICLE_CUSTOM_TOKEN_VALUE,
1750 new Filter(customToken));
1751
1752 _customTokens.put(customToken, value);
1753 }
1754 }
1755 }
1756
1757 if (!_customTokens.isEmpty()) {
1758 tokens.putAll(_customTokens);
1759 }
1760 }
1761
1762 private static void _populateTokens(
1763 Map<String, String> tokens, long articleGroupId,
1764 ThemeDisplay themeDisplay)
1765 throws PortalException {
1766
1767 Layout layout = themeDisplay.getLayout();
1768
1769 Group group = layout.getGroup();
1770
1771 LayoutSet layoutSet = layout.getLayoutSet();
1772
1773 String friendlyUrlCurrent = null;
1774
1775 if (layout.isPublicLayout()) {
1776 friendlyUrlCurrent = themeDisplay.getPathFriendlyURLPublic();
1777 }
1778 else if (group.isUserGroup()) {
1779 friendlyUrlCurrent = themeDisplay.getPathFriendlyURLPrivateUser();
1780 }
1781 else {
1782 friendlyUrlCurrent = themeDisplay.getPathFriendlyURLPrivateGroup();
1783 }
1784
1785 String layoutSetFriendlyUrl = themeDisplay.getI18nPath();
1786
1787 String virtualHostname = layoutSet.getVirtualHostname();
1788
1789 if (Validator.isNull(virtualHostname) ||
1790 !virtualHostname.equals(themeDisplay.getServerName())) {
1791
1792 layoutSetFriendlyUrl = friendlyUrlCurrent + group.getFriendlyURL();
1793 }
1794
1795 tokens.put("article_group_id", String.valueOf(articleGroupId));
1796 tokens.put("cdn_host", themeDisplay.getCDNHost());
1797 tokens.put("company_id", String.valueOf(themeDisplay.getCompanyId()));
1798 tokens.put("friendly_url_current", friendlyUrlCurrent);
1799 tokens.put(
1800 "friendly_url_private_group",
1801 themeDisplay.getPathFriendlyURLPrivateGroup());
1802 tokens.put(
1803 "friendly_url_private_user",
1804 themeDisplay.getPathFriendlyURLPrivateUser());
1805 tokens.put(
1806 "friendly_url_public", themeDisplay.getPathFriendlyURLPublic());
1807 tokens.put("group_friendly_url", group.getFriendlyURL());
1808 tokens.put("image_path", themeDisplay.getPathImage());
1809 tokens.put("layout_set_friendly_url", layoutSetFriendlyUrl);
1810 tokens.put("main_path", themeDisplay.getPathMain());
1811 tokens.put("portal_ctx", themeDisplay.getPathContext());
1812 tokens.put(
1813 "portal_url", HttpUtil.removeProtocol(themeDisplay.getURLPortal()));
1814 tokens.put(
1815 "protocol", HttpUtil.getProtocol(themeDisplay.getURLPortal()));
1816 tokens.put("root_path", themeDisplay.getPathContext());
1817 tokens.put(
1818 "site_group_id", String.valueOf(themeDisplay.getSiteGroupId()));
1819 tokens.put(
1820 "scope_group_id", String.valueOf(themeDisplay.getScopeGroupId()));
1821 tokens.put("theme_image_path", themeDisplay.getPathThemeImages());
1822
1823 _populateCustomTokens(tokens);
1824
1825
1826
1827 tokens.put("friendly_url", themeDisplay.getPathFriendlyURLPublic());
1828 tokens.put(
1829 "friendly_url_private",
1830 themeDisplay.getPathFriendlyURLPrivateGroup());
1831 tokens.put("group_id", String.valueOf(articleGroupId));
1832 tokens.put("page_url", themeDisplay.getPathFriendlyURLPublic());
1833 }
1834
1835 private static void _populateTokens(
1836 Map<String, String> tokens, long articleGroupId,
1837 ThemeDisplayModel themeDisplayModel)
1838 throws Exception {
1839
1840 Layout layout = LayoutLocalServiceUtil.getLayout(
1841 themeDisplayModel.getPlid());
1842
1843 Group group = layout.getGroup();
1844
1845 LayoutSet layoutSet = layout.getLayoutSet();
1846
1847 String friendlyUrlCurrent = null;
1848
1849 if (layout.isPublicLayout()) {
1850 friendlyUrlCurrent = themeDisplayModel.getPathFriendlyURLPublic();
1851 }
1852 else if (group.isUserGroup()) {
1853 friendlyUrlCurrent =
1854 themeDisplayModel.getPathFriendlyURLPrivateUser();
1855 }
1856 else {
1857 friendlyUrlCurrent =
1858 themeDisplayModel.getPathFriendlyURLPrivateGroup();
1859 }
1860
1861 String layoutSetFriendlyUrl = themeDisplayModel.getI18nPath();
1862
1863 String virtualHostname = layoutSet.getVirtualHostname();
1864
1865 if (Validator.isNull(virtualHostname) ||
1866 !virtualHostname.equals(themeDisplayModel.getServerName())) {
1867
1868 layoutSetFriendlyUrl = friendlyUrlCurrent + group.getFriendlyURL();
1869 }
1870
1871 tokens.put("article_group_id", String.valueOf(articleGroupId));
1872 tokens.put("cdn_host", themeDisplayModel.getCdnHost());
1873 tokens.put(
1874 "company_id", String.valueOf(themeDisplayModel.getCompanyId()));
1875 tokens.put("friendly_url_current", friendlyUrlCurrent);
1876 tokens.put(
1877 "friendly_url_private_group",
1878 themeDisplayModel.getPathFriendlyURLPrivateGroup());
1879 tokens.put(
1880 "friendly_url_private_user",
1881 themeDisplayModel.getPathFriendlyURLPrivateUser());
1882 tokens.put(
1883 "friendly_url_public",
1884 themeDisplayModel.getPathFriendlyURLPublic());
1885 tokens.put("group_friendly_url", group.getFriendlyURL());
1886 tokens.put("image_path", themeDisplayModel.getPathImage());
1887 tokens.put("layout_set_friendly_url", layoutSetFriendlyUrl);
1888 tokens.put("main_path", themeDisplayModel.getPathMain());
1889 tokens.put("portal_ctx", themeDisplayModel.getPathContext());
1890 tokens.put(
1891 "portal_url",
1892 HttpUtil.removeProtocol(themeDisplayModel.getURLPortal()));
1893 tokens.put(
1894 "protocol", HttpUtil.getProtocol(themeDisplayModel.getURLPortal()));
1895 tokens.put("root_path", themeDisplayModel.getPathContext());
1896 tokens.put(
1897 "scope_group_id",
1898 String.valueOf(themeDisplayModel.getScopeGroupId()));
1899 tokens.put("theme_image_path", themeDisplayModel.getPathThemeImages());
1900
1901 _populateCustomTokens(tokens);
1902
1903
1904
1905 tokens.put(
1906 "friendly_url", themeDisplayModel.getPathFriendlyURLPublic());
1907 tokens.put(
1908 "friendly_url_private",
1909 themeDisplayModel.getPathFriendlyURLPrivateGroup());
1910 tokens.put("group_id", String.valueOf(articleGroupId));
1911 tokens.put("page_url", themeDisplayModel.getPathFriendlyURLPublic());
1912 }
1913
1914 private static void _removeOldContent(
1915 Stack<String> path, Element contentElement, Document xsdDocument) {
1916
1917 String elementPath = "";
1918
1919 for (int i = 0; i < path.size(); i++) {
1920 elementPath += "/" + path.elementAt(i);
1921 }
1922
1923 for (int i = 0; i < contentElement.nodeCount(); i++) {
1924 Node contentNode = contentElement.node(i);
1925
1926 if (contentNode instanceof Element) {
1927 _removeOldContent(
1928 path, (Element)contentNode, xsdDocument, elementPath);
1929 }
1930 }
1931 }
1932
1933 private static void _removeOldContent(
1934 Stack<String> path, Element contentElement, Document xsdDocument,
1935 String elementPath) {
1936
1937 String name = contentElement.attributeValue("name");
1938
1939 if (Validator.isNull(name)) {
1940 return;
1941 }
1942
1943 String localPath =
1944 "dynamic-element[@name=" + HtmlUtil.escapeXPathAttribute(name) +
1945 "]";
1946
1947 String fullPath = elementPath + "/" + localPath;
1948
1949 XPath xPathSelector = SAXReaderUtil.createXPath(fullPath);
1950
1951 List<Node> curNodes = xPathSelector.selectNodes(xsdDocument);
1952
1953 if (curNodes.isEmpty()) {
1954 contentElement.detach();
1955 }
1956
1957 path.push(localPath);
1958
1959 _removeOldContent(path, contentElement, xsdDocument);
1960
1961 path.pop();
1962 }
1963
1964 private static Log _log = LogFactoryUtil.getLog(JournalUtil.class);
1965
1966 private static Map<String, String> _customTokens;
1967 private static Pattern _friendlyURLPattern = Pattern.compile("[^a-z0-9_-]");
1968 private static Transformer _transformer = new Transformer(
1969 PropsKeys.JOURNAL_TRANSFORMER_LISTENER,
1970 PropsKeys.JOURNAL_ERROR_TEMPLATE, true);
1971
1972 }