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