1
22
23 package com.liferay.portlet.journal.util;
24
25 import com.liferay.portal.PortalException;
26 import com.liferay.portal.SystemException;
27 import com.liferay.portal.kernel.log.Log;
28 import com.liferay.portal.kernel.log.LogFactoryUtil;
29 import com.liferay.portal.kernel.util.Constants;
30 import com.liferay.portal.kernel.util.GetterUtil;
31 import com.liferay.portal.kernel.util.HttpUtil;
32 import com.liferay.portal.kernel.util.LocaleUtil;
33 import com.liferay.portal.kernel.util.OrderByComparator;
34 import com.liferay.portal.kernel.util.PropertiesUtil;
35 import com.liferay.portal.kernel.util.StringPool;
36 import com.liferay.portal.kernel.util.StringUtil;
37 import com.liferay.portal.kernel.util.Time;
38 import com.liferay.portal.kernel.util.Validator;
39 import com.liferay.portal.kernel.xml.Document;
40 import com.liferay.portal.kernel.xml.Element;
41 import com.liferay.portal.kernel.xml.Node;
42 import com.liferay.portal.kernel.xml.SAXReaderUtil;
43 import com.liferay.portal.kernel.xml.XPath;
44 import com.liferay.portal.model.Group;
45 import com.liferay.portal.model.Layout;
46 import com.liferay.portal.model.LayoutSet;
47 import com.liferay.portal.model.User;
48 import com.liferay.portal.service.ImageLocalServiceUtil;
49 import com.liferay.portal.service.LayoutLocalServiceUtil;
50 import com.liferay.portal.service.UserLocalServiceUtil;
51 import com.liferay.portal.theme.ThemeDisplay;
52 import com.liferay.portal.util.ContentUtil;
53 import com.liferay.portal.util.PropsKeys;
54 import com.liferay.portal.util.PropsUtil;
55 import com.liferay.portal.util.WebKeys;
56 import com.liferay.portlet.journal.model.JournalArticle;
57 import com.liferay.portlet.journal.model.JournalStructure;
58 import com.liferay.portlet.journal.model.JournalTemplate;
59 import com.liferay.portlet.journal.model.impl.JournalStructureImpl;
60 import com.liferay.portlet.journal.model.impl.JournalTemplateImpl;
61 import com.liferay.portlet.journal.service.JournalArticleImageLocalServiceUtil;
62 import com.liferay.portlet.journal.service.JournalTemplateLocalServiceUtil;
63 import com.liferay.portlet.journal.util.comparator.ArticleCreateDateComparator;
64 import com.liferay.portlet.journal.util.comparator.ArticleDisplayDateComparator;
65 import com.liferay.portlet.journal.util.comparator.ArticleIDComparator;
66 import com.liferay.portlet.journal.util.comparator.ArticleModifiedDateComparator;
67 import com.liferay.portlet.journal.util.comparator.ArticleReviewDateComparator;
68 import com.liferay.portlet.journal.util.comparator.ArticleTitleComparator;
69 import com.liferay.util.FiniteUniqueStack;
70 import com.liferay.util.LocalizationUtil;
71 import com.liferay.util.xml.XMLFormatter;
72
73 import java.io.IOException;
74
75 import java.util.ArrayList;
76 import java.util.Date;
77 import java.util.HashMap;
78 import java.util.Iterator;
79 import java.util.List;
80 import java.util.Map;
81 import java.util.Stack;
82
83 import javax.portlet.PortletPreferences;
84 import javax.portlet.PortletRequest;
85 import javax.portlet.PortletSession;
86
87
94 public class JournalUtil {
95
96 public static final int MAX_STACK_SIZE = 20;
97
98 public static final String XML_INDENT = " ";
99
100 public static void addRecentArticle(
101 PortletRequest portletRequest, JournalArticle article) {
102
103 if (article != null) {
104 Stack<JournalArticle> stack = getRecentArticles(portletRequest);
105
106 stack.push(article);
107 }
108 }
109
110 public static void addRecentStructure(
111 PortletRequest portletRequest, JournalStructure structure) {
112
113 if (structure != null) {
114 Stack<JournalStructure> stack = getRecentStructures(portletRequest);
115
116 stack.push(structure);
117 }
118 }
119
120 public static void addRecentTemplate(
121 PortletRequest portletRequest, JournalTemplate template) {
122
123 if (template != null) {
124 Stack<JournalTemplate> stack = getRecentTemplates(portletRequest);
125
126 stack.push(template);
127 }
128 }
129
130 public static void addReservedEl(
131 Element root, Map<String, String> tokens, String name, double value) {
132
133 addReservedEl(root, tokens, name, String.valueOf(value));
134 }
135
136 public static void addReservedEl(
137 Element root, Map<String, String> tokens, String name, Date value) {
138
139 addReservedEl(root, tokens, name, Time.getRFC822(value));
140 }
141
142 public static void addReservedEl(
143 Element root, Map<String, String> tokens, String name, String value) {
144
145
147 if (root != null) {
148 Element dynamicEl = SAXReaderUtil.createElement("dynamic-element");
149
150 dynamicEl.add(
151 SAXReaderUtil.createAttribute(dynamicEl, "name", name));
152 dynamicEl.add(
153 SAXReaderUtil.createAttribute(dynamicEl, "type", "text"));
154
155 Element dynamicContent = SAXReaderUtil.createElement(
156 "dynamic-content");
157
158 dynamicContent.setText(value);
160
161 dynamicEl.add(dynamicContent);
162
163 root.add(dynamicEl);
164 }
165
166
168 tokens.put(
169 StringUtil.replace(name, StringPool.DASH, StringPool.UNDERLINE),
170 value);
171 }
172
173 public static void addAllReservedEls(
174 Element root, Map<String, String> tokens, JournalArticle article) {
175
176 JournalUtil.addReservedEl(
177 root, tokens, JournalStructureImpl.RESERVED_ARTICLE_ID,
178 article.getArticleId());
179
180 JournalUtil.addReservedEl(
181 root, tokens, JournalStructureImpl.RESERVED_ARTICLE_VERSION,
182 article.getVersion());
183
184 JournalUtil.addReservedEl(
185 root, tokens, JournalStructureImpl.RESERVED_ARTICLE_TITLE,
186 article.getTitle());
187
188 JournalUtil.addReservedEl(
189 root, tokens, JournalStructureImpl.RESERVED_ARTICLE_DESCRIPTION,
190 article.getDescription());
191
192 JournalUtil.addReservedEl(
193 root, tokens, JournalStructureImpl.RESERVED_ARTICLE_TYPE,
194 article.getType());
195
196 JournalUtil.addReservedEl(
197 root, tokens, JournalStructureImpl.RESERVED_ARTICLE_CREATE_DATE,
198 article.getCreateDate());
199
200 JournalUtil.addReservedEl(
201 root, tokens,
202 JournalStructureImpl.RESERVED_ARTICLE_MODIFIED_DATE,
203 article.getModifiedDate());
204
205 if (article.getDisplayDate() != null) {
206 JournalUtil.addReservedEl(
207 root, tokens,
208 JournalStructureImpl.RESERVED_ARTICLE_DISPLAY_DATE,
209 article.getDisplayDate());
210 }
211
212 JournalUtil.addReservedEl(
213 root, tokens, JournalStructureImpl.RESERVED_ARTICLE_SMALL_IMAGE_URL,
214 article.getSmallImageURL());
215
216 JournalUtil.addReservedEl(
217 root, tokens, JournalStructureImpl.RESERVED_ARTICLE_AUTHOR_ID,
218 String.valueOf(article.getUserId()));
219
220 String userName = StringPool.BLANK;
221 String userEmailAddress = StringPool.BLANK;
222 String userComments = StringPool.BLANK;
223 String userJobTitle = StringPool.BLANK;
224
225 User user = null;
226
227 try {
228 user = UserLocalServiceUtil.getUserById(article.getUserId());
229
230 userName = user.getFullName();
231 userEmailAddress = user.getEmailAddress();
232 userComments = user.getComments();
233 userJobTitle = user.getJobTitle();
234 }
235 catch (PortalException pe) {
236 }
237 catch (SystemException se) {
238 }
239
240 JournalUtil.addReservedEl(
241 root, tokens, JournalStructureImpl.RESERVED_ARTICLE_AUTHOR_NAME,
242 userName);
243
244 JournalUtil.addReservedEl(
245 root, tokens,
246 JournalStructureImpl.RESERVED_ARTICLE_AUTHOR_EMAIL_ADDRESS,
247 userEmailAddress);
248
249 JournalUtil.addReservedEl(
250 root, tokens,
251 JournalStructureImpl.RESERVED_ARTICLE_AUTHOR_COMMENTS,
252 userComments);
253
254 JournalUtil.addReservedEl(
255 root, tokens,
256 JournalStructureImpl.RESERVED_ARTICLE_AUTHOR_JOB_TITLE,
257 userJobTitle);
258 }
259
260 public static String formatVM(String vm) {
261 return vm;
262 }
263
264 public static String formatXML(String xml)
265 throws org.dom4j.DocumentException, IOException {
266
267
271 xml = StringUtil.replace(xml, "&#", "[$SPECIAL_CHARACTER$]");
272
273 xml = XMLFormatter.toString(xml, XML_INDENT);
274
275 xml = StringUtil.replace(xml, "[$SPECIAL_CHARACTER$]", "&#");
276
277 return xml;
278 }
279
280 public static String formatXML(Document doc) throws IOException {
281 return doc.formattedString(XML_INDENT);
282 }
283
284 public static OrderByComparator getArticleOrderByComparator(
285 String orderByCol, String orderByType) {
286
287 boolean orderByAsc = false;
288
289 if (orderByType.equals("asc")) {
290 orderByAsc = true;
291 }
292
293 OrderByComparator orderByComparator = null;
294
295 if (orderByCol.equals("create-date")) {
296 orderByComparator = new ArticleCreateDateComparator(orderByAsc);
297 }
298 else if (orderByCol.equals("display-date")) {
299 orderByComparator = new ArticleDisplayDateComparator(orderByAsc);
300 }
301 else if (orderByCol.equals("id")) {
302 orderByComparator = new ArticleIDComparator(orderByAsc);
303 }
304 else if (orderByCol.equals("modified-date")) {
305 orderByComparator = new ArticleModifiedDateComparator(orderByAsc);
306 }
307 else if (orderByCol.equals("review-date")) {
308 orderByComparator = new ArticleReviewDateComparator(orderByAsc);
309 }
310 else if (orderByCol.equals("title")) {
311 orderByComparator = new ArticleTitleComparator(orderByAsc);
312 }
313 else if (orderByCol.equals("version")) {
314 orderByComparator = new ArticleModifiedDateComparator(orderByAsc);
315 }
316
317 return orderByComparator;
318 }
319
320 public static String getEmailFromAddress(PortletPreferences preferences) {
321 String emailFromAddress = PropsUtil.get(
322 PropsKeys.JOURNAL_EMAIL_FROM_ADDRESS);
323
324 return preferences.getValue("email-from-address", emailFromAddress);
325 }
326
327 public static String getEmailFromName(PortletPreferences preferences) {
328 String emailFromName = PropsUtil.get(
329 PropsKeys.JOURNAL_EMAIL_FROM_NAME);
330
331 return preferences.getValue("email-from-name", emailFromName);
332 }
333
334 public static boolean getEmailArticleApprovalDeniedEnabled(
335 PortletPreferences preferences) {
336
337 String emailArticleApprovalDeniedEnabled = preferences.getValue(
338 "email-article-approval-denied-enabled", StringPool.BLANK);
339
340 if (Validator.isNotNull(emailArticleApprovalDeniedEnabled)) {
341 return GetterUtil.getBoolean(emailArticleApprovalDeniedEnabled);
342 }
343 else {
344 return GetterUtil.getBoolean(PropsUtil.get(
345 PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_DENIED_ENABLED));
346 }
347 }
348
349 public static String getEmailArticleApprovalDeniedBody(
350 PortletPreferences preferences) {
351
352 String emailArticleApprovalDeniedBody = preferences.getValue(
353 "email-article-approval-denied-body", StringPool.BLANK);
354
355 if (Validator.isNotNull(emailArticleApprovalDeniedBody)) {
356 return emailArticleApprovalDeniedBody;
357 }
358 else {
359 return ContentUtil.get(PropsUtil.get(
360 PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_DENIED_BODY));
361 }
362 }
363
364 public static String getEmailArticleApprovalDeniedSubject(
365 PortletPreferences preferences) {
366
367 String emailArticleApprovalDeniedSubject = preferences.getValue(
368 "email-article-approval-denied-subject", StringPool.BLANK);
369
370 if (Validator.isNotNull(emailArticleApprovalDeniedSubject)) {
371 return emailArticleApprovalDeniedSubject;
372 }
373 else {
374 return ContentUtil.get(PropsUtil.get(
375 PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_DENIED_SUBJECT));
376 }
377 }
378
379 public static boolean getEmailArticleApprovalGrantedEnabled(
380 PortletPreferences preferences) {
381
382 String emailArticleApprovalGrantedEnabled = preferences.getValue(
383 "email-article-approval-granted-enabled", StringPool.BLANK);
384
385 if (Validator.isNotNull(emailArticleApprovalGrantedEnabled)) {
386 return GetterUtil.getBoolean(emailArticleApprovalGrantedEnabled);
387 }
388 else {
389 return GetterUtil.getBoolean(PropsUtil.get(
390 PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_GRANTED_ENABLED));
391 }
392 }
393
394 public static String getEmailArticleApprovalGrantedBody(
395 PortletPreferences preferences) {
396
397 String emailArticleApprovalGrantedBody = preferences.getValue(
398 "email-article-approval-granted-body", StringPool.BLANK);
399
400 if (Validator.isNotNull(emailArticleApprovalGrantedBody)) {
401 return emailArticleApprovalGrantedBody;
402 }
403 else {
404 return ContentUtil.get(PropsUtil.get(
405 PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_GRANTED_BODY));
406 }
407 }
408
409 public static String getEmailArticleApprovalGrantedSubject(
410 PortletPreferences preferences) {
411
412 String emailArticleApprovalGrantedSubject = preferences.getValue(
413 "email-article-approval-granted-subject", StringPool.BLANK);
414
415 if (Validator.isNotNull(emailArticleApprovalGrantedSubject)) {
416 return emailArticleApprovalGrantedSubject;
417 }
418 else {
419 return ContentUtil.get(PropsUtil.get(
420 PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_GRANTED_SUBJECT));
421 }
422 }
423
424 public static boolean getEmailArticleApprovalRequestedEnabled(
425 PortletPreferences preferences) {
426
427 String emailArticleApprovalRequestedEnabled = preferences.getValue(
428 "email-article-approval-requested-enabled", StringPool.BLANK);
429
430 if (Validator.isNotNull(emailArticleApprovalRequestedEnabled)) {
431 return GetterUtil.getBoolean(emailArticleApprovalRequestedEnabled);
432 }
433 else {
434 return GetterUtil.getBoolean(PropsUtil.get(
435 PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_REQUESTED_ENABLED));
436 }
437 }
438
439 public static String getEmailArticleApprovalRequestedBody(
440 PortletPreferences preferences) {
441
442 String emailArticleApprovalRequestedBody = preferences.getValue(
443 "email-article-approval-requested-body", StringPool.BLANK);
444
445 if (Validator.isNotNull(emailArticleApprovalRequestedBody)) {
446 return emailArticleApprovalRequestedBody;
447 }
448 else {
449 return ContentUtil.get(PropsUtil.get(
450 PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_REQUESTED_BODY));
451 }
452 }
453
454 public static String getEmailArticleApprovalRequestedSubject(
455 PortletPreferences preferences) {
456
457 String emailArticleApprovalRequestedSubject = preferences.getValue(
458 "email-article-approval-requested-subject", StringPool.BLANK);
459
460 if (Validator.isNotNull(emailArticleApprovalRequestedSubject)) {
461 return emailArticleApprovalRequestedSubject;
462 }
463 else {
464 return ContentUtil.get(PropsUtil.get(
465 PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_REQUESTED_SUBJECT));
466 }
467 }
468
469 public static boolean getEmailArticleReviewEnabled(
470 PortletPreferences preferences) {
471
472 String emailArticleReviewEnabled = preferences.getValue(
473 "email-article-review-enabled", StringPool.BLANK);
474
475 if (Validator.isNotNull(emailArticleReviewEnabled)) {
476 return GetterUtil.getBoolean(emailArticleReviewEnabled);
477 }
478 else {
479 return GetterUtil.getBoolean(PropsUtil.get(
480 PropsKeys.JOURNAL_EMAIL_ARTICLE_REVIEW_ENABLED));
481 }
482 }
483
484 public static String getEmailArticleReviewBody(
485 PortletPreferences preferences) {
486
487 String emailArticleReviewBody = preferences.getValue(
488 "email-article-review-body", StringPool.BLANK);
489
490 if (Validator.isNotNull(emailArticleReviewBody)) {
491 return emailArticleReviewBody;
492 }
493 else {
494 return ContentUtil.get(PropsUtil.get(
495 PropsKeys.JOURNAL_EMAIL_ARTICLE_REVIEW_BODY));
496 }
497 }
498
499 public static String getEmailArticleReviewSubject(
500 PortletPreferences preferences) {
501
502 String emailArticleReviewSubject = preferences.getValue(
503 "email-article-review-subject", StringPool.BLANK);
504
505 if (Validator.isNotNull(emailArticleReviewSubject)) {
506 return emailArticleReviewSubject;
507 }
508 else {
509 return ContentUtil.get(PropsUtil.get(
510 PropsKeys.JOURNAL_EMAIL_ARTICLE_REVIEW_SUBJECT));
511 }
512 }
513
514 public static Stack<JournalArticle> getRecentArticles(
515 PortletRequest portletRequest) {
516
517 PortletSession portletSession = portletRequest.getPortletSession();
518
519 Stack<JournalArticle> recentArticles =
520 (Stack<JournalArticle>)portletSession.getAttribute(
521 WebKeys.JOURNAL_RECENT_ARTICLES);
522
523 if (recentArticles == null) {
524 recentArticles = new FiniteUniqueStack<JournalArticle>(
525 MAX_STACK_SIZE);
526
527 portletSession.setAttribute(
528 WebKeys.JOURNAL_RECENT_ARTICLES, recentArticles);
529 }
530
531 return recentArticles;
532 }
533
534 public static Stack<JournalStructure> getRecentStructures(
535 PortletRequest portletRequest) {
536
537 PortletSession portletSession = portletRequest.getPortletSession();
538
539 Stack<JournalStructure> recentStructures =
540 (Stack<JournalStructure>)portletSession.getAttribute(
541 WebKeys.JOURNAL_RECENT_STRUCTURES);
542
543 if (recentStructures == null) {
544 recentStructures = new FiniteUniqueStack<JournalStructure>(
545 MAX_STACK_SIZE);
546
547 portletSession.setAttribute(
548 WebKeys.JOURNAL_RECENT_STRUCTURES, recentStructures);
549 }
550
551 return recentStructures;
552 }
553
554 public static Stack<JournalTemplate> getRecentTemplates(
555 PortletRequest portletRequest) {
556
557 PortletSession portletSession = portletRequest.getPortletSession();
558
559 Stack<JournalTemplate> recentTemplates =
560 (Stack<JournalTemplate>)portletSession.getAttribute(
561 WebKeys.JOURNAL_RECENT_TEMPLATES);
562
563 if (recentTemplates == null) {
564 recentTemplates = new FiniteUniqueStack<JournalTemplate>(
565 MAX_STACK_SIZE);
566
567 portletSession.setAttribute(
568 WebKeys.JOURNAL_RECENT_TEMPLATES, recentTemplates);
569 }
570
571 return recentTemplates;
572 }
573
574 public static String getTemplateScript(
575 long groupId, String templateId, Map<String, String> tokens,
576 String languageId)
577 throws PortalException, SystemException {
578
579 return getTemplateScript(groupId, templateId, tokens, languageId, true);
580 }
581
582 public static String getTemplateScript(
583 long groupId, String templateId, Map<String, String> tokens,
584 String languageId, boolean transform)
585 throws PortalException, SystemException {
586
587 JournalTemplate template = JournalTemplateLocalServiceUtil.getTemplate(
588 groupId, templateId);
589
590 return getTemplateScript(template, tokens, languageId, transform);
591 }
592
593 public static String getTemplateScript(
594 JournalTemplate template, Map<String, String> tokens, String languageId,
595 boolean transform) {
596
597 String script = template.getXsl();
598
599 if (transform) {
600
601
603 String[] listeners =
604 PropsUtil.getArray(PropsKeys.JOURNAL_TRANSFORMER_LISTENER);
605
606 for (int i = 0; i < listeners.length; i++) {
607 TransformerListener listener = null;
608
609 try {
610 listener =
611 (TransformerListener)Class.forName(
612 listeners[i]).newInstance();
613
614 listener.setTemplateDriven(true);
615 listener.setLanguageId(languageId);
616 listener.setTokens(tokens);
617 }
618 catch (Exception e) {
619 _log.error(e, e);
620 }
621
622
624 if (listener != null) {
625 script = listener.onScript(script);
626 }
627 }
628 }
629
630 return script;
631 }
632
633 public static Map<String, String> getTokens(
634 long groupId, ThemeDisplay themeDisplay) {
635
636 return getTokens(groupId, themeDisplay, null);
637 }
638
639 public static Map<String, String> getTokens(
640 long groupId, ThemeDisplay themeDisplay, String xmlRequest) {
641
642 Map<String, String> tokens = new HashMap<String, String>();
643
644 if (themeDisplay != null) {
645 _populateTokens(tokens, groupId, themeDisplay);
646 }
647 else if (Validator.isNotNull(xmlRequest)) {
648 try {
649 _populateTokens(tokens, groupId, xmlRequest);
650 }
651 catch (Exception e) {
652 if (_log.isWarnEnabled()) {
653 _log.warn(e, e);
654 }
655 }
656 }
657
658 return tokens;
659 }
660
661 public static String mergeArticleContent(
662 String curContent, String newContent) {
663
664 try {
665 Document curDocument = SAXReaderUtil.read(curContent);
666 Document newDocument = SAXReaderUtil.read(newContent);
667
668 Element curRoot = curDocument.getRootElement();
669 Element newRoot = newDocument.getRootElement();
670
671 curRoot.addAttribute(
672 "default-locale",
673 newRoot.attributeValue("default-locale"));
674 curRoot.addAttribute(
675 "available-locales",
676 newRoot.attributeValue("available-locales"));
677
678 _mergeArticleContentUpdate(
679 curDocument, newRoot,
680 LocaleUtil.toLanguageId(LocaleUtil.getDefault()));
681 _mergeArticleContentDelete(curRoot, newDocument);
682
683 curContent = JournalUtil.formatXML(curDocument);
684 }
685 catch (Exception e) {
686 _log.error(e, e);
687 }
688
689 return curContent;
690 }
691
692 public static String removeArticleLocale(
693 String content, String languageId) {
694
695 try {
696 Document doc = SAXReaderUtil.read(content);
697
698 Element root = doc.getRootElement();
699
700 String availableLocales = root.attributeValue("available-locales");
701
702 if (availableLocales == null) {
703 return content;
704 }
705
706 availableLocales = StringUtil.remove(availableLocales, languageId);
707
708 if (availableLocales.endsWith(",")) {
709 availableLocales = availableLocales.substring(
710 0, availableLocales.length() - 1);
711 }
712
713 root.addAttribute("available-locales", availableLocales);
714
715 removeArticleLocale(root, languageId);
716
717 content = formatXML(doc);
718 }
719 catch (Exception e) {
720 _log.error(e, e);
721 }
722
723 return content;
724 }
725
726 public static void removeArticleLocale(Element el, String languageId)
727 throws PortalException, SystemException {
728
729 for (Element dynamicEl : el.elements("dynamic-element")) {
730 for (Element dynamicContentEl :
731 dynamicEl.elements("dynamic-content")) {
732
733 String curLanguageId = GetterUtil.getString(
734 dynamicContentEl.attributeValue("language-id"));
735
736 if (curLanguageId.equals(languageId)) {
737 long id = GetterUtil.getLong(
738 dynamicContentEl.attributeValue("id"));
739
740 if (id > 0) {
741 ImageLocalServiceUtil.deleteImage(id);
742 }
743
744 dynamicContentEl.detach();
745 }
746 }
747
748 removeArticleLocale(dynamicEl, languageId);
749 }
750 }
751
752 public static String removeOldContent(String content, String xsd) {
753 try {
754 Document contentDoc = SAXReaderUtil.read(content);
755 Document xsdDoc = SAXReaderUtil.read(xsd);
756
757 Element contentRoot = contentDoc.getRootElement();
758
759 Stack<String> path = new Stack<String>();
760
761 path.push(contentRoot.getName());
762
763 _removeOldContent(path, contentRoot, xsdDoc);
764
765 content = formatXML(contentDoc);
766 }
767 catch (Exception e) {
768 _log.error(e, e);
769 }
770
771 return content;
772 }
773
774 public static void removeRecentArticle(
775 PortletRequest portletRequest, String articleId) {
776
777 Stack<JournalArticle> stack = getRecentArticles(portletRequest);
778
779 Iterator<JournalArticle> itr = stack.iterator();
780
781 while (itr.hasNext()) {
782 JournalArticle journalArticle = itr.next();
783
784 if (journalArticle.getArticleId().equals(articleId)) {
785 itr.remove();
786
787 break;
788 }
789 }
790 }
791
792 public static void removeRecentStructure(
793 PortletRequest portletRequest, String structureId) {
794
795 Stack<JournalStructure> stack = getRecentStructures(portletRequest);
796
797 Iterator<JournalStructure> itr = stack.iterator();
798
799 while (itr.hasNext()) {
800 JournalStructure journalStructure = itr.next();
801
802 if (journalStructure.getStructureId().equals(structureId)) {
803 itr.remove();
804
805 break;
806 }
807 }
808 }
809
810 public static void removeRecentTemplate(
811 PortletRequest portletRequest, String templateId) {
812
813 Stack<JournalTemplate> stack = getRecentTemplates(portletRequest);
814
815 Iterator<JournalTemplate> itr = stack.iterator();
816
817 while (itr.hasNext()) {
818 JournalTemplate journalTemplate = itr.next();
819
820 if (journalTemplate.getTemplateId().equals(templateId)) {
821 itr.remove();
822
823 break;
824 }
825 }
826 }
827
828 public static String transform(
829 Map<String, String> tokens, String viewMode, String languageId,
830 String xml, String script, String langType)
831 throws Exception {
832
833
835 if (_log.isDebugEnabled()) {
836 _log.debug("Language " + languageId);
837 }
838
839 if (Validator.isNull(viewMode)) {
840 viewMode = Constants.VIEW;
841 }
842
843 if (_logTokens.isDebugEnabled()) {
844 String tokensString = PropertiesUtil.list(tokens);
845
846 _logTokens.debug(tokensString);
847 }
848
849 if (_logTransformBefore.isDebugEnabled()) {
850 _logTransformBefore.debug(xml);
851 }
852
853 List<TransformerListener> listenersList =
854 new ArrayList<TransformerListener>();
855
856 String[] listeners = PropsUtil.getArray(
857 PropsKeys.JOURNAL_TRANSFORMER_LISTENER);
858
859 for (int i = 0; i < listeners.length; i++) {
860 TransformerListener listener = null;
861
862 try {
863 if (_log.isDebugEnabled()) {
864 _log.debug("Instantiate listener " + listeners[i]);
865 }
866
867 boolean templateDriven = Validator.isNotNull(langType);
868
869 listener = (TransformerListener)Class.forName(
870 listeners[i]).newInstance();
871
872 listener.setTemplateDriven(templateDriven);
873 listener.setLanguageId(languageId);
874 listener.setTokens(tokens);
875
876 listenersList.add(listener);
877 }
878 catch (Exception e) {
879 _log.error(e, e);
880 }
881
882
884 if (_logXmlBeforeListener.isDebugEnabled()) {
885 _logXmlBeforeListener.debug(xml);
886 }
887
888 if (listener != null) {
889 xml = listener.onXml(xml);
890
891 if (_logXmlAfterListener.isDebugEnabled()) {
892 _logXmlAfterListener.debug(xml);
893 }
894 }
895
896
898 if (_logScriptBeforeListener.isDebugEnabled()) {
899 _logScriptBeforeListener.debug(script);
900 }
901
902 if (listener != null) {
903 script = listener.onScript(script);
904
905 if (_logScriptAfterListener.isDebugEnabled()) {
906 _logScriptAfterListener.debug(script);
907 }
908 }
909 }
910
911
913 String output = null;
914
915 if (Validator.isNull(langType)) {
916 output = LocalizationUtil.getLocalization(xml, languageId);
917 }
918 else if (langType.equals(JournalTemplateImpl.LANG_TYPE_VM)) {
919 output = JournalVmUtil.transform(
920 tokens, viewMode, languageId, xml, script);
921 }
922 else if (langType.equals(JournalTemplateImpl.LANG_TYPE_XSL)) {
923 output = JournalXslUtil.transform(
924 tokens, viewMode, languageId, xml, script);
925 }
926
927
929 for (int i = 0; i < listenersList.size(); i++) {
930 TransformerListener listener = listenersList.get(i);
931
932
934 if (_logOutputBeforeListener.isDebugEnabled()) {
935 _logOutputBeforeListener.debug(output);
936 }
937
938 output = listener.onOutput(output);
939
940 if (_logOutputAfterListener.isDebugEnabled()) {
941 _logOutputAfterListener.debug(output);
942 }
943 }
944
945 if (_logTransfromAfter.isDebugEnabled()) {
946 _logTransfromAfter.debug(output);
947 }
948
949 return output;
950 }
951
952 private static Element _getElementByInstanceId(
953 Document document, String instanceId) {
954
955 XPath xPathSelector = SAXReaderUtil.createXPath(
956 "//dynamic-element[@instance-id='" + instanceId + "']");
957
958 List<Node> nodes = xPathSelector.selectNodes(document);
959
960 if (nodes.size() == 1) {
961 return (Element)nodes.get(0);
962 }
963 else {
964 return null;
965 }
966 }
967
968 private static void _mergeArticleContentDelete(
969 Element curParentElement, Document newDocument)
970 throws Exception {
971
972 List<Element> curElements = curParentElement.elements(
973 "dynamic-element");
974
975 for (int i = 0; i < curElements.size(); i++) {
976 Element curElement = curElements.get(i);
977
978 _mergeArticleContentDelete(curElement, newDocument);
979
980 String instanceId = curElement.attributeValue("instance-id");
981
982 Element newElement = _getElementByInstanceId(
983 newDocument, instanceId);
984
985 if (newElement == null) {
986 curElement.detach();
987
988 String type = curElement.attributeValue("type");
989
990 if (type.equals("image")) {
991 _mergeArticleContentDeleteImages(
992 curElement.elements("dynamic-content"));
993 }
994 }
995 }
996 }
997
998 private static void _mergeArticleContentDeleteImages(List<Element> elements)
999 throws Exception {
1000
1001 for (Element element : elements) {
1002 long articleImageId = GetterUtil.getLong(
1003 element.attributeValue("id"));
1004
1005 JournalArticleImageLocalServiceUtil.deleteArticleImage(
1006 articleImageId);
1007 }
1008 }
1009
1010 private static void _mergeArticleContentUpdate(
1011 Document curDocument, Element newParentElement,
1012 String defaultLocale)
1013 throws Exception {
1014
1015 List<Element> newElements = newParentElement.elements(
1016 "dynamic-element");
1017
1018 for (int i = 0; i < newElements.size(); i++) {
1019 Element newElement = newElements.get(i);
1020
1021 _mergeArticleContentUpdate(
1022 curDocument, newParentElement, newElement, i, defaultLocale);
1023 }
1024 }
1025
1026 private static void _mergeArticleContentUpdate(
1027 Document curDocument, Element newParentElement, Element newElement,
1028 int pos, String defaultLocale)
1029 throws Exception {
1030
1031 _mergeArticleContentUpdate(curDocument, newElement, defaultLocale);
1032
1033 String instanceId = newElement.attributeValue("instance-id");
1034
1035 Element curElement = _getElementByInstanceId(curDocument, instanceId);
1036
1037 if (curElement != null) {
1038 _mergeArticleContentUpdate(curElement, newElement, defaultLocale);
1039 }
1040 else {
1041 String parentInstanceId = newParentElement.attributeValue(
1042 "instance-id");
1043
1044 if (Validator.isNull(parentInstanceId)) {
1045 Element curRoot = curDocument.getRootElement();
1046
1047 List<Element> curRootElements = curRoot.elements();
1048
1049 curRootElements.add(pos, newElement.createCopy());
1050 }
1051 else {
1052 Element curParentElement = _getElementByInstanceId(
1053 curDocument, parentInstanceId);
1054
1055 if (curParentElement != null) {
1056 List<Element> curParentElements =
1057 curParentElement.elements();
1058
1059 curParentElements.add(pos, newElement.createCopy());
1060 }
1061 }
1062 }
1063 }
1064
1065 private static void _mergeArticleContentUpdate(
1066 Element curElement, Element newElement, String defaultLocale) {
1067
1068 Element newContentElement = newElement.elements(
1069 "dynamic-content").get(0);
1070
1071 String newLanguageId = newContentElement.attributeValue("language-id");
1072 String newValue = newContentElement.getText();
1073
1074 List<Element> curContentElements = curElement.elements(
1075 "dynamic-content");
1076
1077 if (Validator.isNull(newLanguageId)) {
1078 for (Element curContentElement : curContentElements) {
1079 curContentElement.detach();
1080 }
1081
1082 Element curContentElement = SAXReaderUtil.createElement(
1083 "dynamic-content");
1084
1085 curContentElement.addCDATA(newValue);
1086
1087 curElement.add(curContentElement);
1088 }
1089 else {
1090 boolean alreadyExists = false;
1091
1092 for (Element curContentElement : curContentElements) {
1093 String curLanguageId = curContentElement.attributeValue(
1094 "language-id");
1095
1096 if (newLanguageId.equals(curLanguageId)) {
1097 alreadyExists = true;
1098
1099 curContentElement.clearContent();
1100 curContentElement.addCDATA(newValue);
1101
1102 break;
1103 }
1104 }
1105
1106 if (!alreadyExists) {
1107 Element curContentElement = curContentElements.get(0);
1108
1109 String curLanguageId = curContentElement.attributeValue(
1110 "language-id");
1111
1112 if (Validator.isNull(curLanguageId)) {
1113 curContentElement.detach();
1114 }
1115
1116 curElement.add(newContentElement.createCopy());
1117 }
1118 }
1119 }
1120
1121 private static void _populateTokens(
1122 Map<String, String> tokens, long groupId, String xmlRequest)
1123 throws Exception {
1124
1125 Document request = SAXReaderUtil.read(xmlRequest);
1126
1127 Element root = request.getRootElement();
1128
1129 Element themeDisplayEl = root.element("theme-display");
1130
1131 Layout layout = LayoutLocalServiceUtil.getLayout(
1132 GetterUtil.getLong(themeDisplayEl.elementText("plid")));
1133
1134 Group group = layout.getGroup();
1135
1136 LayoutSet layoutSet = layout.getLayoutSet();
1137
1138 String friendlyUrlCurrent = null;
1139
1140 if (layout.isPublicLayout()) {
1141 friendlyUrlCurrent = themeDisplayEl.elementText(
1142 "path-friendly-url-public");
1143 }
1144 else if (group.isUserGroup()) {
1145 friendlyUrlCurrent = themeDisplayEl.elementText(
1146 "path-friendly-url-private-user");
1147 }
1148 else {
1149 friendlyUrlCurrent = themeDisplayEl.elementText(
1150 "path-friendly-url-private-group");
1151 }
1152
1153 String layoutSetFriendlyUrl = StringPool.BLANK;
1154
1155 String virtualHost = layoutSet.getVirtualHost();
1156
1157 if (Validator.isNull(virtualHost) ||
1158 !virtualHost.equals(themeDisplayEl.elementText("server-name"))) {
1159
1160 layoutSetFriendlyUrl = friendlyUrlCurrent + group.getFriendlyURL();
1161 }
1162
1163 tokens.put("cdn_host", themeDisplayEl.elementText("cdn-host"));
1164 tokens.put("company_id", themeDisplayEl.elementText("company-id"));
1165 tokens.put("friendly_url_current", friendlyUrlCurrent);
1166 tokens.put(
1167 "friendly_url_private_group",
1168 themeDisplayEl.elementText("path-friendly-url-private-group"));
1169 tokens.put(
1170 "friendly_url_private_user",
1171 themeDisplayEl.elementText("path-friendly-url-private-user"));
1172 tokens.put(
1173 "friendly_url_public",
1174 themeDisplayEl.elementText("path-friendly-url-public"));
1175 tokens.put("group_friendly_url", group.getFriendlyURL());
1176 tokens.put("group_id", String.valueOf(groupId));
1177 tokens.put("image_path", themeDisplayEl.elementText("path-image"));
1178 tokens.put("layout_set_friendly_url", layoutSetFriendlyUrl);
1179 tokens.put("main_path", themeDisplayEl.elementText("path-main"));
1180 tokens.put("portal_ctx", themeDisplayEl.elementText("path-context"));
1181 tokens.put(
1182 "portal_url",
1183 HttpUtil.removeProtocol(themeDisplayEl.elementText("url-portal")));
1184 tokens.put("root_path", themeDisplayEl.elementText("path-context"));
1185 tokens.put(
1186 "theme_image_path",
1187 themeDisplayEl.elementText("path-theme-images"));
1188
1189
1191 tokens.put(
1192 "friendly_url",
1193 themeDisplayEl.elementText("path-friendly-url-public"));
1194 tokens.put(
1195 "friendly_url_private",
1196 themeDisplayEl.elementText("path-friendly-url-private-group"));
1197 tokens.put(
1198 "page_url", themeDisplayEl.elementText("path-friendly-url-public"));
1199 }
1200
1201 private static void _populateTokens(
1202 Map<String, String> tokens, long groupId, ThemeDisplay themeDisplay) {
1203
1204 Layout layout = themeDisplay.getLayout();
1205
1206 Group group = layout.getGroup();
1207
1208 LayoutSet layoutSet = layout.getLayoutSet();
1209
1210 String friendlyUrlCurrent = null;
1211
1212 if (layout.isPublicLayout()) {
1213 friendlyUrlCurrent = themeDisplay.getPathFriendlyURLPublic();
1214 }
1215 else if (group.isUserGroup()) {
1216 friendlyUrlCurrent = themeDisplay.getPathFriendlyURLPrivateUser();
1217 }
1218 else {
1219 friendlyUrlCurrent = themeDisplay.getPathFriendlyURLPrivateGroup();
1220 }
1221
1222 String layoutSetFriendlyUrl = StringPool.BLANK;
1223
1224 String virtualHost = layoutSet.getVirtualHost();
1225
1226 if (Validator.isNull(virtualHost) ||
1227 !virtualHost.equals(themeDisplay.getServerName())) {
1228
1229 layoutSetFriendlyUrl = friendlyUrlCurrent + group.getFriendlyURL();
1230 }
1231
1232 tokens.put("cdn_host", themeDisplay.getCDNHost());
1233 tokens.put("company_id", String.valueOf(themeDisplay.getCompanyId()));
1234 tokens.put("friendly_url_current", friendlyUrlCurrent);
1235 tokens.put(
1236 "friendly_url_private_group",
1237 themeDisplay.getPathFriendlyURLPrivateGroup());
1238 tokens.put(
1239 "friendly_url_private_user",
1240 themeDisplay.getPathFriendlyURLPrivateUser());
1241 tokens.put(
1242 "friendly_url_public", themeDisplay.getPathFriendlyURLPublic());
1243 tokens.put("group_friendly_url", group.getFriendlyURL());
1244 tokens.put("group_id", String.valueOf(groupId));
1245 tokens.put("image_path", themeDisplay.getPathImage());
1246 tokens.put("layout_set_friendly_url", layoutSetFriendlyUrl);
1247 tokens.put("main_path", themeDisplay.getPathMain());
1248 tokens.put("portal_ctx", themeDisplay.getPathContext());
1249 tokens.put(
1250 "portal_url", HttpUtil.removeProtocol(themeDisplay.getURLPortal()));
1251 tokens.put("root_path", themeDisplay.getPathContext());
1252 tokens.put("theme_image_path", themeDisplay.getPathThemeImages());
1253
1254
1256 tokens.put("friendly_url", themeDisplay.getPathFriendlyURLPublic());
1257 tokens.put(
1258 "friendly_url_private",
1259 themeDisplay.getPathFriendlyURLPrivateGroup());
1260 tokens.put("page_url", themeDisplay.getPathFriendlyURLPublic());
1261 }
1262
1263 private static void _removeOldContent(
1264 Stack<String> path, Element contentEl, Document xsdDoc)
1265 throws SystemException {
1266
1267 String elPath = "";
1268
1269 for (int i = 0; i < path.size(); i++) {
1270 elPath += "/" + path.elementAt(i);
1271 }
1272
1273 for (int i = 0; i < contentEl.nodeCount(); i++) {
1274 Node contentNode = contentEl.node(i);
1275
1276 if (contentNode instanceof Element) {
1277 _removeOldContent(path, (Element)contentNode, xsdDoc, elPath);
1278 }
1279 }
1280 }
1281
1282 private static void _removeOldContent(
1283 Stack<String> path, Element contentEl, Document xsdDoc,
1284 String elPath)
1285 throws SystemException {
1286
1287 String name = contentEl.attributeValue("name");
1288
1289 if (Validator.isNull(name)) {
1290 return;
1291 }
1292
1293 String localPath = "dynamic-element[@name='" + name + "']";
1294
1295 String fullPath = elPath + "/" + localPath;
1296
1297 XPath xPathSelector = SAXReaderUtil.createXPath(fullPath);
1298
1299 List<Node> curNodes = xPathSelector.selectNodes(xsdDoc);
1300
1301 if (curNodes.size() == 0) {
1302 contentEl.detach();
1303 }
1304
1305 path.push(localPath);
1306
1307 _removeOldContent(path, contentEl, xsdDoc);
1308
1309 path.pop();
1310 }
1311
1312 private static Log _log = LogFactoryUtil.getLog(JournalUtil.class);
1313
1314 private static Log _logOutputAfterListener = LogFactoryUtil.getLog(
1315 JournalUtil.class.getName() + ".OutputAfterListener");
1316
1317 private static Log _logOutputBeforeListener = LogFactoryUtil.getLog(
1318 JournalUtil.class.getName() + ".OutputBeforeListener");
1319
1320 private static Log _logScriptAfterListener = LogFactoryUtil.getLog(
1321 JournalUtil.class.getName() + ".ScriptAfterListener");
1322
1323 private static Log _logScriptBeforeListener = LogFactoryUtil.getLog(
1324 JournalUtil.class.getName() + ".ScriptBeforeListener");
1325
1326 private static Log _logTransfromAfter = LogFactoryUtil.getLog(
1327 JournalUtil.class.getName() + ".TransformAfter");
1328
1329 private static Log _logTransformBefore = LogFactoryUtil.getLog(
1330 JournalUtil.class.getName() + ".BeforeTransform");
1331
1332 private static Log _logTokens = LogFactoryUtil.getLog(
1333 JournalUtil.class.getName() + ".Tokens");
1334
1335 private static Log _logXmlAfterListener = LogFactoryUtil.getLog(
1336 JournalUtil.class.getName() + ".XmlAfterListener");
1337
1338 private static Log _logXmlBeforeListener = LogFactoryUtil.getLog(
1339 JournalUtil.class.getName() + ".XmlBeforeListener");
1340
1341}