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