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