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