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(
553 document.get(Field.SCOPE_GROUP_ID));
554 String articleId = document.get("articleId");
555
556 try {
557 JournalArticle article =
558 JournalArticleLocalServiceUtil.getArticle(
559 groupId, articleId);
560
561 articles.add(article);
562 }
563 catch (NoSuchArticleException nsae) {
564 corruptIndex = true;
565
566 Indexer indexer = IndexerRegistryUtil.getIndexer(
567 JournalArticle.class);
568
569 long companyId = GetterUtil.getLong(
570 document.get(Field.COMPANY_ID));
571
572 indexer.delete(companyId, document.getUID());
573 }
574 }
575
576 return new Tuple(articles, corruptIndex);
577 }
578
579 public static String getEmailArticleAddedBody(
580 PortletPreferences preferences) {
581
582 String emailArticleAddedBody = preferences.getValue(
583 "emailArticleAddedBody", StringPool.BLANK);
584
585 if (Validator.isNotNull(emailArticleAddedBody)) {
586 return emailArticleAddedBody;
587 }
588 else {
589 return ContentUtil.get(
590 PropsUtil.get(PropsKeys.JOURNAL_EMAIL_ARTICLE_ADDED_BODY));
591 }
592 }
593
594 public static boolean getEmailArticleAddedEnabled(
595 PortletPreferences preferences) {
596
597 String emailArticleAddedEnabled = preferences.getValue(
598 "emailArticleAddedEnabled", StringPool.BLANK);
599
600 if (Validator.isNotNull(emailArticleAddedEnabled)) {
601 return GetterUtil.getBoolean(emailArticleAddedEnabled);
602 }
603 else {
604 return GetterUtil.getBoolean(
605 PropsUtil.get(PropsKeys.JOURNAL_EMAIL_ARTICLE_ADDED_ENABLED));
606 }
607 }
608
609 public static String getEmailArticleAddedSubject(
610 PortletPreferences preferences) {
611
612 String emailArticleAddedSubject = preferences.getValue(
613 "emailArticleAddedSubject", StringPool.BLANK);
614
615 if (Validator.isNotNull(emailArticleAddedSubject)) {
616 return emailArticleAddedSubject;
617 }
618 else {
619 return ContentUtil.get(
620 PropsUtil.get(PropsKeys.JOURNAL_EMAIL_ARTICLE_ADDED_SUBJECT));
621 }
622 }
623
624 public static String getEmailArticleApprovalDeniedBody(
625 PortletPreferences preferences) {
626
627 String emailArticleApprovalDeniedBody = preferences.getValue(
628 "emailArticleApprovalDeniedBody", StringPool.BLANK);
629
630 if (Validator.isNotNull(emailArticleApprovalDeniedBody)) {
631 return emailArticleApprovalDeniedBody;
632 }
633 else {
634 return ContentUtil.get(
635 PropsUtil.get(
636 PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_DENIED_BODY));
637 }
638 }
639
640 public static boolean getEmailArticleApprovalDeniedEnabled(
641 PortletPreferences preferences) {
642
643 String emailArticleApprovalDeniedEnabled = preferences.getValue(
644 "emailArticleApprovalDeniedEnabled", StringPool.BLANK);
645
646 if (Validator.isNotNull(emailArticleApprovalDeniedEnabled)) {
647 return GetterUtil.getBoolean(emailArticleApprovalDeniedEnabled);
648 }
649 else {
650 return GetterUtil.getBoolean(
651 PropsUtil.get(
652 PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_DENIED_ENABLED));
653 }
654 }
655
656 public static String getEmailArticleApprovalDeniedSubject(
657 PortletPreferences preferences) {
658
659 String emailArticleApprovalDeniedSubject = preferences.getValue(
660 "emailArticleApprovalDeniedSubject", StringPool.BLANK);
661
662 if (Validator.isNotNull(emailArticleApprovalDeniedSubject)) {
663 return emailArticleApprovalDeniedSubject;
664 }
665 else {
666 return ContentUtil.get(
667 PropsUtil.get(
668 PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_DENIED_SUBJECT));
669 }
670 }
671
672 public static String getEmailArticleApprovalGrantedBody(
673 PortletPreferences preferences) {
674
675 String emailArticleApprovalGrantedBody = preferences.getValue(
676 "emailArticleApprovalGrantedBody", StringPool.BLANK);
677
678 if (Validator.isNotNull(emailArticleApprovalGrantedBody)) {
679 return emailArticleApprovalGrantedBody;
680 }
681 else {
682 return ContentUtil.get(
683 PropsUtil.get(
684 PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_GRANTED_BODY));
685 }
686 }
687
688 public static boolean getEmailArticleApprovalGrantedEnabled(
689 PortletPreferences preferences) {
690
691 String emailArticleApprovalGrantedEnabled = preferences.getValue(
692 "emailArticleApprovalGrantedEnabled", StringPool.BLANK);
693
694 if (Validator.isNotNull(emailArticleApprovalGrantedEnabled)) {
695 return GetterUtil.getBoolean(emailArticleApprovalGrantedEnabled);
696 }
697 else {
698 return GetterUtil.getBoolean(
699 PropsUtil.get(
700 PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_GRANTED_ENABLED));
701 }
702 }
703
704 public static String getEmailArticleApprovalGrantedSubject(
705 PortletPreferences preferences) {
706
707 String emailArticleApprovalGrantedSubject = preferences.getValue(
708 "emailArticleApprovalGrantedSubject", StringPool.BLANK);
709
710 if (Validator.isNotNull(emailArticleApprovalGrantedSubject)) {
711 return emailArticleApprovalGrantedSubject;
712 }
713 else {
714 return ContentUtil.get(
715 PropsUtil.get(
716 PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_GRANTED_SUBJECT));
717 }
718 }
719
720 public static String getEmailArticleApprovalRequestedBody(
721 PortletPreferences preferences) {
722
723 String emailArticleApprovalRequestedBody = preferences.getValue(
724 "emailArticleApprovalRequestedBody", StringPool.BLANK);
725
726 if (Validator.isNotNull(emailArticleApprovalRequestedBody)) {
727 return emailArticleApprovalRequestedBody;
728 }
729 else {
730 return ContentUtil.get(
731 PropsUtil.get(
732 PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_REQUESTED_BODY));
733 }
734 }
735
736 public static boolean getEmailArticleApprovalRequestedEnabled(
737 PortletPreferences preferences) {
738
739 String emailArticleApprovalRequestedEnabled = preferences.getValue(
740 "emailArticleApprovalRequestedEnabled", StringPool.BLANK);
741
742 if (Validator.isNotNull(emailArticleApprovalRequestedEnabled)) {
743 return GetterUtil.getBoolean(emailArticleApprovalRequestedEnabled);
744 }
745 else {
746 return GetterUtil.getBoolean(
747 PropsUtil.get(
748 PropsKeys.
749 JOURNAL_EMAIL_ARTICLE_APPROVAL_REQUESTED_ENABLED));
750 }
751 }
752
753 public static String getEmailArticleApprovalRequestedSubject(
754 PortletPreferences preferences) {
755
756 String emailArticleApprovalRequestedSubject = preferences.getValue(
757 "emailArticleApprovalRequestedSubject", StringPool.BLANK);
758
759 if (Validator.isNotNull(emailArticleApprovalRequestedSubject)) {
760 return emailArticleApprovalRequestedSubject;
761 }
762 else {
763 return ContentUtil.get(
764 PropsUtil.get(
765 PropsKeys.
766 JOURNAL_EMAIL_ARTICLE_APPROVAL_REQUESTED_SUBJECT));
767 }
768 }
769
770 public static String getEmailArticleReviewBody(
771 PortletPreferences preferences) {
772
773 String emailArticleReviewBody = preferences.getValue(
774 "emailArticleReviewBody", StringPool.BLANK);
775
776 if (Validator.isNotNull(emailArticleReviewBody)) {
777 return emailArticleReviewBody;
778 }
779 else {
780 return ContentUtil.get(
781 PropsUtil.get(PropsKeys.JOURNAL_EMAIL_ARTICLE_REVIEW_BODY));
782 }
783 }
784
785 public static boolean getEmailArticleReviewEnabled(
786 PortletPreferences preferences) {
787
788 String emailArticleReviewEnabled = preferences.getValue(
789 "emailArticleReviewEnabled", StringPool.BLANK);
790
791 if (Validator.isNotNull(emailArticleReviewEnabled)) {
792 return GetterUtil.getBoolean(emailArticleReviewEnabled);
793 }
794 else {
795 return GetterUtil.getBoolean(
796 PropsUtil.get(PropsKeys.JOURNAL_EMAIL_ARTICLE_REVIEW_ENABLED));
797 }
798 }
799
800 public static String getEmailArticleReviewSubject(
801 PortletPreferences preferences) {
802
803 String emailArticleReviewSubject = preferences.getValue(
804 "emailArticleReviewSubject", StringPool.BLANK);
805
806 if (Validator.isNotNull(emailArticleReviewSubject)) {
807 return emailArticleReviewSubject;
808 }
809 else {
810 return ContentUtil.get(
811 PropsUtil.get(PropsKeys.JOURNAL_EMAIL_ARTICLE_REVIEW_SUBJECT));
812 }
813 }
814
815 public static String getEmailArticleUpdatedBody(
816 PortletPreferences preferences) {
817
818 String emailArticleUpdatedBody = preferences.getValue(
819 "emailArticleUpdatedBody", StringPool.BLANK);
820
821 if (Validator.isNotNull(emailArticleUpdatedBody)) {
822 return emailArticleUpdatedBody;
823 }
824 else {
825 return ContentUtil.get(
826 PropsUtil.get(PropsKeys.JOURNAL_EMAIL_ARTICLE_UPDATED_BODY));
827 }
828 }
829
830 public static boolean getEmailArticleUpdatedEnabled(
831 PortletPreferences preferences) {
832
833 String emailArticleUpdatedEnabled = preferences.getValue(
834 "emailArticleUpdatedEnabled", StringPool.BLANK);
835
836 if (Validator.isNotNull(emailArticleUpdatedEnabled)) {
837 return GetterUtil.getBoolean(emailArticleUpdatedEnabled);
838 }
839 else {
840 return GetterUtil.getBoolean(
841 PropsUtil.get(PropsKeys.JOURNAL_EMAIL_ARTICLE_UPDATED_ENABLED));
842 }
843 }
844
845 public static String getEmailArticleUpdatedSubject(
846 PortletPreferences preferences) {
847
848 String emailArticleUpdatedSubject = preferences.getValue(
849 "emailArticleUpdatedSubject", StringPool.BLANK);
850
851 if (Validator.isNotNull(emailArticleUpdatedSubject)) {
852 return emailArticleUpdatedSubject;
853 }
854 else {
855 return ContentUtil.get(
856 PropsUtil.get(PropsKeys.JOURNAL_EMAIL_ARTICLE_UPDATED_SUBJECT));
857 }
858 }
859
860 public static String getEmailFromAddress(
861 PortletPreferences preferences, long companyId)
862 throws SystemException {
863
864 return PortalUtil.getEmailFromAddress(
865 preferences, companyId, PropsValues.JOURNAL_EMAIL_FROM_ADDRESS);
866 }
867
868 public static String getEmailFromName(
869 PortletPreferences preferences, long companyId)
870 throws SystemException {
871
872 return PortalUtil.getEmailFromName(
873 preferences, companyId, PropsValues.JOURNAL_EMAIL_FROM_NAME);
874 }
875
876 public static String getJournalControlPanelLink(
877 PortletRequest portletRequest, long folderId)
878 throws PortalException, SystemException {
879
880 ThemeDisplay themeDisplay = (ThemeDisplay)portletRequest.getAttribute(
881 WebKeys.THEME_DISPLAY);
882
883 PortletURL portletURL = PortletURLFactoryUtil.create(
884 portletRequest, PortletKeys.JOURNAL,
885 PortalUtil.getControlPanelPlid(themeDisplay.getCompanyId()),
886 PortletRequest.RENDER_PHASE);
887
888 portletURL.setParameter("struts_action", "/journal/view");
889 portletURL.setParameter("folderId", String.valueOf(folderId));
890
891 return portletURL.toString();
892 }
893
894 public static long getPreviewPlid(
895 JournalArticle article, ThemeDisplay themeDisplay)
896 throws Exception {
897
898 if ((article != null) && Validator.isNotNull(article.getLayoutUuid())) {
899 Layout layout =
900 LayoutLocalServiceUtil.getLayoutByUuidAndCompanyId(
901 article.getLayoutUuid(), themeDisplay.getCompanyId());
902
903 return layout.getPlid();
904 }
905
906 Layout layout = LayoutLocalServiceUtil.fetchFirstLayout(
907 themeDisplay.getScopeGroupId(), false,
908 LayoutConstants.DEFAULT_PARENT_LAYOUT_ID);
909
910 if (layout == null) {
911 layout = LayoutLocalServiceUtil.fetchFirstLayout(
912 themeDisplay.getScopeGroupId(), true,
913 LayoutConstants.DEFAULT_PARENT_LAYOUT_ID);
914 }
915
916 if (layout != null) {
917 return layout.getPlid();
918 }
919
920 return themeDisplay.getPlid();
921 }
922
923 public static Stack<JournalArticle> getRecentArticles(
924 PortletRequest portletRequest) {
925
926 PortletSession portletSession = portletRequest.getPortletSession();
927
928 Stack<JournalArticle> recentArticles =
929 (Stack<JournalArticle>)portletSession.getAttribute(
930 WebKeys.JOURNAL_RECENT_ARTICLES);
931
932 if (recentArticles == null) {
933 recentArticles = new FiniteUniqueStack<JournalArticle>(
934 MAX_STACK_SIZE);
935
936 portletSession.setAttribute(
937 WebKeys.JOURNAL_RECENT_ARTICLES, recentArticles);
938 }
939
940 return recentArticles;
941 }
942
943 public static Stack<DDMStructure> getRecentDDMStructures(
944 PortletRequest portletRequest) {
945
946 PortletSession portletSession = portletRequest.getPortletSession();
947
948 Stack<DDMStructure> recentDDMStructures =
949 (Stack<DDMStructure>)portletSession.getAttribute(
950 WebKeys.JOURNAL_RECENT_DYNAMIC_DATA_MAPPING_STRUCTURES);
951
952 if (recentDDMStructures == null) {
953 recentDDMStructures = new FiniteUniqueStack<DDMStructure>(
954 MAX_STACK_SIZE);
955
956 portletSession.setAttribute(
957 WebKeys.JOURNAL_RECENT_DYNAMIC_DATA_MAPPING_STRUCTURES,
958 recentDDMStructures);
959 }
960
961 return recentDDMStructures;
962 }
963
964 public static Stack<DDMTemplate> getRecentDDMTemplates(
965 PortletRequest portletRequest) {
966
967 PortletSession portletSession = portletRequest.getPortletSession();
968
969 Stack<DDMTemplate> recentDDMTemplates =
970 (Stack<DDMTemplate>)portletSession.getAttribute(
971 WebKeys.JOURNAL_RECENT_DYNAMIC_DATA_MAPPING_TEMPLATES);
972
973 if (recentDDMTemplates == null) {
974 recentDDMTemplates = new FiniteUniqueStack<DDMTemplate>(
975 MAX_STACK_SIZE);
976
977 portletSession.setAttribute(
978 WebKeys.JOURNAL_RECENT_DYNAMIC_DATA_MAPPING_TEMPLATES,
979 recentDDMTemplates);
980 }
981
982 return recentDDMTemplates;
983 }
984
985 public static long[] getStructureClassPKs(
986 long[] groupIds, String structureId)
987 throws SystemException {
988
989 List<Long> classPKs = new ArrayList<Long>();
990
991 for (long groupId : groupIds) {
992 @SuppressWarnings("deprecation")
993 JournalStructure structure =
994 com.liferay.portlet.journal.service.
995 JournalStructureLocalServiceUtil.fetchStructure(
996 groupId, structureId);
997
998 if (structure != null) {
999 classPKs.add(structure.getId());
1000 }
1001 }
1002
1003 return ArrayUtil.toLongArray(classPKs);
1004 }
1005
1006 public static String getTemplateScript(
1007 DDMTemplate ddmTemplate, Map<String, String> tokens, String languageId,
1008 boolean transform) {
1009
1010 String script = ddmTemplate.getScript();
1011
1012 if (!transform) {
1013 return script;
1014 }
1015
1016 String[] transformerListenerClassNames = PropsUtil.getArray(
1017 PropsKeys.JOURNAL_TRANSFORMER_LISTENER);
1018
1019 for (String transformerListenerClassName :
1020 transformerListenerClassNames) {
1021
1022 TransformerListener transformerListener = null;
1023
1024 try {
1025 transformerListener =
1026 (TransformerListener)InstanceFactory.newInstance(
1027 transformerListenerClassName);
1028
1029 continue;
1030 }
1031 catch (Exception e) {
1032 _log.error(e, e);
1033 }
1034
1035 script = transformerListener.onScript(
1036 script, null, languageId, tokens);
1037 }
1038
1039 return script;
1040 }
1041
1042 public static String getTemplateScript(
1043 long groupId, String ddmTemplateKey, Map<String, String> tokens,
1044 String languageId)
1045 throws PortalException, SystemException {
1046
1047 return getTemplateScript(
1048 groupId, ddmTemplateKey, tokens, languageId, true);
1049 }
1050
1051 public static String getTemplateScript(
1052 long groupId, String ddmTemplateKey, Map<String, String> tokens,
1053 String languageId, boolean transform)
1054 throws PortalException, SystemException {
1055
1056 DDMTemplate ddmTemplate = DDMTemplateLocalServiceUtil.getTemplate(
1057 groupId, PortalUtil.getClassNameId(DDMStructure.class),
1058 ddmTemplateKey, true);
1059
1060 return getTemplateScript(ddmTemplate, tokens, languageId, transform);
1061 }
1062
1063 public static Map<String, String> getTokens(
1064 long articleGroupId, ThemeDisplay themeDisplay)
1065 throws PortalException, SystemException {
1066
1067 return getTokens(articleGroupId, themeDisplay, null);
1068 }
1069
1070 public static Map<String, String> getTokens(
1071 long articleGroupId, ThemeDisplay themeDisplay, String xmlRequest)
1072 throws PortalException, SystemException {
1073
1074 Map<String, String> tokens = new HashMap<String, String>();
1075
1076 if (themeDisplay != null) {
1077 _populateTokens(tokens, articleGroupId, themeDisplay);
1078 }
1079 else if (Validator.isNotNull(xmlRequest)) {
1080 try {
1081 _populateTokens(tokens, articleGroupId, xmlRequest);
1082 }
1083 catch (Exception e) {
1084 if (_log.isWarnEnabled()) {
1085 _log.warn(e, e);
1086 }
1087 }
1088 }
1089
1090 return tokens;
1091 }
1092
1093 public static String getUrlTitle(long id, String title) {
1094 if (title == null) {
1095 return String.valueOf(id);
1096 }
1097
1098 title = StringUtil.toLowerCase(title.trim());
1099
1100 if (Validator.isNull(title) || Validator.isNumber(title) ||
1101 title.equals("rss")) {
1102
1103 title = String.valueOf(id);
1104 }
1105 else {
1106 title = FriendlyURLNormalizerUtil.normalize(
1107 title, _friendlyURLPattern);
1108 }
1109
1110 return ModelHintsUtil.trimString(
1111 JournalArticle.class.getName(), "urlTitle", title);
1112 }
1113
1114 public static String mergeArticleContent(
1115 String curContent, String newContent, boolean removeNullElements) {
1116
1117 try {
1118 Document curDocument = SAXReaderUtil.read(curContent);
1119 Document newDocument = SAXReaderUtil.read(newContent);
1120
1121 Element curRootElement = curDocument.getRootElement();
1122 Element newRootElement = newDocument.getRootElement();
1123
1124 curRootElement.addAttribute(
1125 "default-locale",
1126 newRootElement.attributeValue("default-locale"));
1127 curRootElement.addAttribute(
1128 "available-locales",
1129 newRootElement.attributeValue("available-locales"));
1130
1131 _mergeArticleContentUpdate(
1132 curDocument, newRootElement,
1133 LocaleUtil.toLanguageId(LocaleUtil.getSiteDefault()));
1134
1135 if (removeNullElements) {
1136 _mergeArticleContentDelete(curRootElement, newDocument);
1137 }
1138
1139 curContent = DDMXMLUtil.formatXML(curDocument);
1140 }
1141 catch (Exception e) {
1142 _log.error(e, e);
1143 }
1144
1145 return curContent;
1146 }
1147
1148 public static String prepareLocalizedContentForImport(
1149 String content, Locale defaultImportLocale)
1150 throws LocaleException {
1151
1152 try {
1153 Document curDocument = SAXReaderUtil.read(content);
1154
1155 Document updatedDocument = SAXReaderUtil.read(content);
1156
1157 Element updatedRootElement = updatedDocument.getRootElement();
1158
1159 Attribute availableLocales = updatedRootElement.attribute(
1160 "available-locales");
1161
1162 if (Validator.isNull(availableLocales)) {
1163 updatedRootElement = updatedRootElement.addAttribute(
1164 "available-locales", StringPool.BLANK);
1165
1166 availableLocales = updatedRootElement.attribute(
1167 "available-locales");
1168 }
1169
1170 String defaultImportLocaleId = LocaleUtil.toLanguageId(
1171 defaultImportLocale);
1172
1173 if (!StringUtil.contains(
1174 availableLocales.getValue(), defaultImportLocaleId)) {
1175
1176 if (Validator.isNull(availableLocales.getValue())) {
1177 availableLocales.setValue(defaultImportLocaleId);
1178 }
1179 else {
1180 StringBundler sb = new StringBundler(3);
1181
1182 sb.append(availableLocales.getValue());
1183 sb.append(StringPool.COMMA);
1184 sb.append(defaultImportLocaleId);
1185
1186 availableLocales.setValue(sb.toString());
1187 }
1188
1189 _mergeArticleContentUpdate(
1190 curDocument, updatedRootElement,
1191 LocaleUtil.toLanguageId(defaultImportLocale));
1192
1193 content = DDMXMLUtil.formatXML(updatedDocument);
1194 }
1195
1196 Attribute defaultLocale = updatedRootElement.attribute(
1197 "default-locale");
1198
1199 if (Validator.isNull(defaultLocale)) {
1200 updatedRootElement = updatedRootElement.addAttribute(
1201 "default-locale", StringPool.BLANK);
1202
1203 defaultLocale = updatedRootElement.attribute("default-locale");
1204 }
1205
1206 Locale defaultContentLocale = LocaleUtil.fromLanguageId(
1207 defaultLocale.getValue());
1208
1209 if (!LocaleUtil.equals(defaultContentLocale, defaultImportLocale)) {
1210 defaultLocale.setValue(defaultImportLocaleId);
1211
1212 content = DDMXMLUtil.formatXML(updatedDocument);
1213 }
1214 }
1215 catch (Exception e) {
1216 throw new LocaleException(
1217 LocaleException.TYPE_CONTENT,
1218 "The locale " + defaultImportLocale + " is not available");
1219 }
1220
1221 return content;
1222 }
1223
1224 public static void removeArticleLocale(Element element, String languageId)
1225 throws PortalException, SystemException {
1226
1227 for (Element dynamicElementElement :
1228 element.elements("dynamic-element")) {
1229
1230 for (Element dynamicContentElement :
1231 dynamicElementElement.elements("dynamic-content")) {
1232
1233 String curLanguageId = GetterUtil.getString(
1234 dynamicContentElement.attributeValue("language-id"));
1235
1236 if (curLanguageId.equals(languageId)) {
1237 long id = GetterUtil.getLong(
1238 dynamicContentElement.attributeValue("id"));
1239
1240 if (id > 0) {
1241 ImageLocalServiceUtil.deleteImage(id);
1242 }
1243
1244 dynamicContentElement.detach();
1245 }
1246 }
1247
1248 removeArticleLocale(dynamicElementElement, languageId);
1249 }
1250 }
1251
1252 public static String removeArticleLocale(
1253 String content, String languageId) {
1254
1255 try {
1256 Document document = SAXReaderUtil.read(content);
1257
1258 Element rootElement = document.getRootElement();
1259
1260 String availableLocales = rootElement.attributeValue(
1261 "available-locales");
1262
1263 if (availableLocales == null) {
1264 return content;
1265 }
1266
1267 availableLocales = StringUtil.remove(availableLocales, languageId);
1268
1269 if (availableLocales.endsWith(",")) {
1270 availableLocales = availableLocales.substring(
1271 0, availableLocales.length() - 1);
1272 }
1273
1274 rootElement.addAttribute("available-locales", availableLocales);
1275
1276 removeArticleLocale(rootElement, languageId);
1277
1278 content = DDMXMLUtil.formatXML(document);
1279 }
1280 catch (Exception e) {
1281 _log.error(e, e);
1282 }
1283
1284 return content;
1285 }
1286
1287 public static String removeOldContent(String content, String xsd) {
1288 try {
1289 Document contentDoc = SAXReaderUtil.read(content);
1290 Document xsdDoc = SAXReaderUtil.read(xsd);
1291
1292 Element contentRoot = contentDoc.getRootElement();
1293
1294 Stack<String> path = new Stack<String>();
1295
1296 path.push(contentRoot.getName());
1297
1298 _removeOldContent(path, contentRoot, xsdDoc);
1299
1300 content = DDMXMLUtil.formatXML(contentDoc);
1301 }
1302 catch (Exception e) {
1303 _log.error(e, e);
1304 }
1305
1306 return content;
1307 }
1308
1309 public static void removeRecentArticle(
1310 PortletRequest portletRequest, String articleId) {
1311
1312 removeRecentArticle(portletRequest, articleId, 0);
1313 }
1314
1315 public static void removeRecentArticle(
1316 PortletRequest portletRequest, String articleId, double version) {
1317
1318 Stack<JournalArticle> stack = getRecentArticles(portletRequest);
1319
1320 Iterator<JournalArticle> itr = stack.iterator();
1321
1322 while (itr.hasNext()) {
1323 JournalArticle journalArticle = itr.next();
1324
1325 if (journalArticle.getArticleId().equals(articleId) &&
1326 ((journalArticle.getVersion() == version) ||
1327 (version == 0))) {
1328
1329 itr.remove();
1330 }
1331 }
1332 }
1333
1334 public static void removeRecentDDMStructure(
1335 PortletRequest portletRequest, String ddmStructureKey) {
1336
1337 Stack<DDMStructure> stack = getRecentDDMStructures(portletRequest);
1338
1339 Iterator<DDMStructure> itr = stack.iterator();
1340
1341 while (itr.hasNext()) {
1342 DDMStructure ddmStructure = itr.next();
1343
1344 if (ddmStructureKey.equals(ddmStructure.getStructureKey())) {
1345 itr.remove();
1346
1347 break;
1348 }
1349 }
1350 }
1351
1352 public static void removeRecentDDMTemplate(
1353 PortletRequest portletRequest, String ddmTemplateKey) {
1354
1355 Stack<DDMTemplate> stack = getRecentDDMTemplates(portletRequest);
1356
1357 Iterator<DDMTemplate> itr = stack.iterator();
1358
1359 while (itr.hasNext()) {
1360 DDMTemplate ddmTemplate = itr.next();
1361
1362 if (ddmTemplateKey.equals(ddmTemplate.getTemplateKey())) {
1363 itr.remove();
1364
1365 break;
1366 }
1367 }
1368 }
1369
1370 public static List<JournalStructure> toJournalStructures(
1371 List<DDMStructure> ddmStructures)
1372 throws SystemException {
1373
1374 List<JournalStructure> structures = new ArrayList<JournalStructure>();
1375
1376 for (DDMStructure ddmStructure : ddmStructures) {
1377 JournalStructure structure = new JournalStructureAdapter(
1378 ddmStructure);
1379
1380 structures.add(structure);
1381 }
1382
1383 return new UnmodifiableList<JournalStructure>(structures);
1384 }
1385
1386 public static List<JournalTemplate> toJournalTemplates(
1387 List<DDMTemplate> ddmTemplates) {
1388
1389 List<JournalTemplate> templates = new ArrayList<JournalTemplate>();
1390
1391 for (DDMTemplate ddmTemplate : ddmTemplates) {
1392 JournalTemplate template = new JournalTemplateAdapter(ddmTemplate);
1393
1394 templates.add(template);
1395 }
1396
1397 return new UnmodifiableList<JournalTemplate>(templates);
1398 }
1399
1400 public static String transform(
1401 ThemeDisplay themeDisplay, Map<String, String> tokens,
1402 String viewMode, String languageId, String xml, String script,
1403 String langType)
1404 throws Exception {
1405
1406 return _transformer.transform(
1407 themeDisplay, tokens, viewMode, languageId, xml, script, langType);
1408 }
1409
1410 private static void _addElementOptions(
1411 Element curContentElement, Element newContentElement) {
1412
1413 List<Element> newElementOptions = newContentElement.elements("option");
1414
1415 for (Element newElementOption : newElementOptions) {
1416 Element curElementOption = SAXReaderUtil.createElement("option");
1417
1418 curElementOption.addCDATA(newElementOption.getText());
1419
1420 curContentElement.add(curElementOption);
1421 }
1422 }
1423
1424 private static Element _getElementByInstanceId(
1425 Document document, String instanceId) {
1426
1427 if (Validator.isNull(instanceId)) {
1428 return null;
1429 }
1430
1431 XPath xPathSelector = SAXReaderUtil.createXPath(
1432 "
1433 HtmlUtil.escapeXPathAttribute(instanceId) + "]");
1434
1435 List<Node> nodes = xPathSelector.selectNodes(document);
1436
1437 if (nodes.size() == 1) {
1438 return (Element)nodes.get(0);
1439 }
1440 else {
1441 return null;
1442 }
1443 }
1444
1445 private static void _mergeArticleContentDelete(
1446 Element curParentElement, Document newDocument)
1447 throws Exception {
1448
1449 List<Element> curElements = curParentElement.elements(
1450 "dynamic-element");
1451
1452 for (int i = 0; i < curElements.size(); i++) {
1453 Element curElement = curElements.get(i);
1454
1455 _mergeArticleContentDelete(curElement, newDocument);
1456
1457 String instanceId = curElement.attributeValue("instance-id");
1458
1459 Element newElement = _getElementByInstanceId(
1460 newDocument, instanceId);
1461
1462 if (newElement == null) {
1463 curElement.detach();
1464 }
1465 }
1466 }
1467
1468 private static void _mergeArticleContentUpdate(
1469 Document curDocument, Element newParentElement, Element newElement,
1470 int pos, String defaultLocale)
1471 throws Exception {
1472
1473 _mergeArticleContentUpdate(curDocument, newElement, defaultLocale);
1474
1475 String instanceId = newElement.attributeValue("instance-id");
1476
1477 Element curElement = _getElementByInstanceId(curDocument, instanceId);
1478
1479 if (curElement != null) {
1480 _mergeArticleContentUpdate(curElement, newElement, defaultLocale);
1481 }
1482 else {
1483 String parentInstanceId = newParentElement.attributeValue(
1484 "instance-id");
1485
1486 if (Validator.isNull(parentInstanceId)) {
1487 Element curRoot = curDocument.getRootElement();
1488
1489 List<Element> curRootElements = curRoot.elements();
1490
1491 curRootElements.add(pos, newElement.createCopy());
1492 }
1493 else {
1494 Element curParentElement = _getElementByInstanceId(
1495 curDocument, parentInstanceId);
1496
1497 if (curParentElement != null) {
1498 List<Element> curParentElements =
1499 curParentElement.elements();
1500
1501 curParentElements.add(pos, newElement.createCopy());
1502 }
1503 }
1504 }
1505 }
1506
1507 private static void _mergeArticleContentUpdate(
1508 Document curDocument, Element newParentElement,
1509 String defaultLocale)
1510 throws Exception {
1511
1512 List<Element> newElements = newParentElement.elements(
1513 "dynamic-element");
1514
1515 for (int i = 0; i < newElements.size(); i++) {
1516 Element newElement = newElements.get(i);
1517
1518 _mergeArticleContentUpdate(
1519 curDocument, newParentElement, newElement, i, defaultLocale);
1520 }
1521 }
1522
1523 private static void _mergeArticleContentUpdate(
1524 Element curElement, Element newElement, String defaultLocale) {
1525
1526 Attribute curTypeAttribute = curElement.attribute("type");
1527 Attribute newTypeAttribute = newElement.attribute("type");
1528
1529 curTypeAttribute.setValue(newTypeAttribute.getValue());
1530
1531 Attribute curIndexTypeAttribute = curElement.attribute("index-type");
1532 Attribute newIndexTypeAttribute = newElement.attribute("index-type");
1533
1534 if (newIndexTypeAttribute != null) {
1535 if (curIndexTypeAttribute == null) {
1536 curElement.addAttribute(
1537 "index-type", newIndexTypeAttribute.getValue());
1538 }
1539 else {
1540 curIndexTypeAttribute.setValue(
1541 newIndexTypeAttribute.getValue());
1542 }
1543 }
1544
1545 List<Element> elements = newElement.elements("dynamic-content");
1546
1547 if ((elements == null) || elements.isEmpty()) {
1548 return;
1549 }
1550
1551 Element newContentElement = elements.get(0);
1552
1553 String newLanguageId = newContentElement.attributeValue("language-id");
1554 String newValue = newContentElement.getText();
1555
1556 String indexType = newElement.attributeValue("index-type");
1557
1558 if (Validator.isNotNull(indexType)) {
1559 curElement.addAttribute("index-type", indexType);
1560 }
1561
1562 List<Element> curContentElements = curElement.elements(
1563 "dynamic-content");
1564
1565 if (Validator.isNull(newLanguageId)) {
1566 for (Element curContentElement : curContentElements) {
1567 curContentElement.detach();
1568 }
1569
1570 Element curContentElement = SAXReaderUtil.createElement(
1571 "dynamic-content");
1572
1573 if (newContentElement.element("option") != null) {
1574 _addElementOptions(curContentElement, newContentElement);
1575 }
1576 else {
1577 curContentElement.addCDATA(newValue);
1578 }
1579
1580 curElement.add(curContentElement);
1581 }
1582 else {
1583 boolean alreadyExists = false;
1584
1585 for (Element curContentElement : curContentElements) {
1586 String curLanguageId = curContentElement.attributeValue(
1587 "language-id");
1588
1589 if (newLanguageId.equals(curLanguageId)) {
1590 alreadyExists = true;
1591
1592 curContentElement.clearContent();
1593
1594 if (newContentElement.element("option") != null) {
1595 _addElementOptions(
1596 curContentElement, newContentElement);
1597 }
1598 else {
1599 curContentElement.addCDATA(newValue);
1600 }
1601
1602 break;
1603 }
1604 }
1605
1606 if (!alreadyExists) {
1607 Element curContentElement = curContentElements.get(0);
1608
1609 String curLanguageId = curContentElement.attributeValue(
1610 "language-id");
1611
1612 if (Validator.isNull(curLanguageId)) {
1613 if (newLanguageId.equals(defaultLocale)) {
1614 curContentElement.clearContent();
1615
1616 if (newContentElement.element("option") != null) {
1617 _addElementOptions(
1618 curContentElement, newContentElement);
1619 }
1620 else {
1621 curContentElement.addCDATA(newValue);
1622 }
1623 }
1624 else {
1625 curElement.add(newContentElement.createCopy());
1626 }
1627
1628 curContentElement.addAttribute(
1629 "language-id", defaultLocale);
1630 }
1631 else {
1632 curElement.add(newContentElement.createCopy());
1633 }
1634 }
1635 }
1636 }
1637
1638 private static void _populateCustomTokens(Map<String, String> tokens) {
1639 if (_customTokens == null) {
1640 synchronized (JournalUtil.class) {
1641 _customTokens = new HashMap<String, String>();
1642
1643 for (String customToken :
1644 PropsValues.JOURNAL_ARTICLE_CUSTOM_TOKENS) {
1645
1646 String value = PropsUtil.get(
1647 PropsKeys.JOURNAL_ARTICLE_CUSTOM_TOKEN_VALUE,
1648 new Filter(customToken));
1649
1650 _customTokens.put(customToken, value);
1651 }
1652 }
1653 }
1654
1655 if (!_customTokens.isEmpty()) {
1656 tokens.putAll(_customTokens);
1657 }
1658 }
1659
1660 private static void _populateTokens(
1661 Map<String, String> tokens, long articleGroupId, String xmlRequest)
1662 throws Exception {
1663
1664 Document requestDocument = SAXReaderUtil.read(xmlRequest);
1665
1666 Element rootElement = requestDocument.getRootElement();
1667
1668 Element themeDisplayElement = rootElement.element("theme-display");
1669
1670 Layout layout = LayoutLocalServiceUtil.getLayout(
1671 GetterUtil.getLong(themeDisplayElement.elementText("plid")));
1672
1673 Group group = layout.getGroup();
1674
1675 LayoutSet layoutSet = layout.getLayoutSet();
1676
1677 String friendlyUrlCurrent = null;
1678
1679 if (layout.isPublicLayout()) {
1680 friendlyUrlCurrent = themeDisplayElement.elementText(
1681 "path-friendly-url-public");
1682 }
1683 else if (group.isUserGroup()) {
1684 friendlyUrlCurrent = themeDisplayElement.elementText(
1685 "path-friendly-url-private-user");
1686 }
1687 else {
1688 friendlyUrlCurrent = themeDisplayElement.elementText(
1689 "path-friendly-url-private-group");
1690 }
1691
1692 String layoutSetFriendlyUrl = themeDisplayElement.elementText(
1693 "i18n-path");
1694
1695 String virtualHostname = layoutSet.getVirtualHostname();
1696
1697 if (Validator.isNull(virtualHostname) ||
1698 !virtualHostname.equals(
1699 themeDisplayElement.elementText("server-name"))) {
1700
1701 layoutSetFriendlyUrl = friendlyUrlCurrent + group.getFriendlyURL();
1702 }
1703
1704 tokens.put("article_group_id", String.valueOf(articleGroupId));
1705 tokens.put("cdn_host", themeDisplayElement.elementText("cdn-host"));
1706 tokens.put("company_id", themeDisplayElement.elementText("company-id"));
1707 tokens.put("friendly_url_current", friendlyUrlCurrent);
1708 tokens.put(
1709 "friendly_url_private_group",
1710 themeDisplayElement.elementText("path-friendly-url-private-group"));
1711 tokens.put(
1712 "friendly_url_private_user",
1713 themeDisplayElement.elementText("path-friendly-url-private-user"));
1714 tokens.put(
1715 "friendly_url_public",
1716 themeDisplayElement.elementText("path-friendly-url-public"));
1717 tokens.put("group_friendly_url", group.getFriendlyURL());
1718 tokens.put("image_path", themeDisplayElement.elementText("path-image"));
1719 tokens.put("layout_set_friendly_url", layoutSetFriendlyUrl);
1720 tokens.put("main_path", themeDisplayElement.elementText("path-main"));
1721 tokens.put(
1722 "portal_ctx", themeDisplayElement.elementText("path-context"));
1723 tokens.put(
1724 "portal_url",
1725 HttpUtil.removeProtocol(
1726 themeDisplayElement.elementText("url-portal")));
1727 tokens.put(
1728 "protocol",
1729 HttpUtil.getProtocol(
1730 themeDisplayElement.elementText("url-portal")));
1731 tokens.put(
1732 "root_path", themeDisplayElement.elementText("path-context"));
1733 tokens.put(
1734 "scope_group_id",
1735 themeDisplayElement.elementText("scope-group-id"));
1736 tokens.put(
1737 "site_group_id", themeDisplayElement.elementText("site-group-id"));
1738 tokens.put(
1739 "theme_image_path",
1740 themeDisplayElement.elementText("path-theme-images"));
1741
1742 _populateCustomTokens(tokens);
1743
1744
1745
1746 tokens.put(
1747 "friendly_url",
1748 themeDisplayElement.elementText("path-friendly-url-public"));
1749 tokens.put(
1750 "friendly_url_private",
1751 themeDisplayElement.elementText("path-friendly-url-private-group"));
1752 tokens.put("group_id", String.valueOf(articleGroupId));
1753 tokens.put(
1754 "page_url",
1755 themeDisplayElement.elementText("path-friendly-url-public"));
1756 }
1757
1758 private static void _populateTokens(
1759 Map<String, String> tokens, long articleGroupId,
1760 ThemeDisplay themeDisplay)
1761 throws PortalException, SystemException {
1762
1763 Layout layout = themeDisplay.getLayout();
1764
1765 Group group = layout.getGroup();
1766
1767 LayoutSet layoutSet = layout.getLayoutSet();
1768
1769 String friendlyUrlCurrent = null;
1770
1771 if (layout.isPublicLayout()) {
1772 friendlyUrlCurrent = themeDisplay.getPathFriendlyURLPublic();
1773 }
1774 else if (group.isUserGroup()) {
1775 friendlyUrlCurrent = themeDisplay.getPathFriendlyURLPrivateUser();
1776 }
1777 else {
1778 friendlyUrlCurrent = themeDisplay.getPathFriendlyURLPrivateGroup();
1779 }
1780
1781 String layoutSetFriendlyUrl = themeDisplay.getI18nPath();
1782
1783 String virtualHostname = layoutSet.getVirtualHostname();
1784
1785 if (Validator.isNull(virtualHostname) ||
1786 !virtualHostname.equals(themeDisplay.getServerName())) {
1787
1788 layoutSetFriendlyUrl = friendlyUrlCurrent + group.getFriendlyURL();
1789 }
1790
1791 tokens.put("article_group_id", String.valueOf(articleGroupId));
1792 tokens.put("cdn_host", themeDisplay.getCDNHost());
1793 tokens.put("company_id", String.valueOf(themeDisplay.getCompanyId()));
1794 tokens.put("friendly_url_current", friendlyUrlCurrent);
1795 tokens.put(
1796 "friendly_url_private_group",
1797 themeDisplay.getPathFriendlyURLPrivateGroup());
1798 tokens.put(
1799 "friendly_url_private_user",
1800 themeDisplay.getPathFriendlyURLPrivateUser());
1801 tokens.put(
1802 "friendly_url_public", themeDisplay.getPathFriendlyURLPublic());
1803 tokens.put("group_friendly_url", group.getFriendlyURL());
1804 tokens.put("image_path", themeDisplay.getPathImage());
1805 tokens.put("layout_set_friendly_url", layoutSetFriendlyUrl);
1806 tokens.put("main_path", themeDisplay.getPathMain());
1807 tokens.put("portal_ctx", themeDisplay.getPathContext());
1808 tokens.put(
1809 "portal_url", HttpUtil.removeProtocol(themeDisplay.getURLPortal()));
1810 tokens.put(
1811 "protocol", HttpUtil.getProtocol(themeDisplay.getURLPortal()));
1812 tokens.put("root_path", themeDisplay.getPathContext());
1813 tokens.put(
1814 "site_group_id", String.valueOf(themeDisplay.getSiteGroupId()));
1815 tokens.put(
1816 "scope_group_id", String.valueOf(themeDisplay.getScopeGroupId()));
1817 tokens.put("theme_image_path", themeDisplay.getPathThemeImages());
1818
1819 _populateCustomTokens(tokens);
1820
1821
1822
1823 tokens.put("friendly_url", themeDisplay.getPathFriendlyURLPublic());
1824 tokens.put(
1825 "friendly_url_private",
1826 themeDisplay.getPathFriendlyURLPrivateGroup());
1827 tokens.put("group_id", String.valueOf(articleGroupId));
1828 tokens.put("page_url", themeDisplay.getPathFriendlyURLPublic());
1829 }
1830
1831 private static void _removeOldContent(
1832 Stack<String> path, Element contentElement, Document xsdDocument)
1833 throws SystemException {
1834
1835 String elementPath = "";
1836
1837 for (int i = 0; i < path.size(); i++) {
1838 elementPath += "/" + path.elementAt(i);
1839 }
1840
1841 for (int i = 0; i < contentElement.nodeCount(); i++) {
1842 Node contentNode = contentElement.node(i);
1843
1844 if (contentNode instanceof Element) {
1845 _removeOldContent(
1846 path, (Element)contentNode, xsdDocument, elementPath);
1847 }
1848 }
1849 }
1850
1851 private static void _removeOldContent(
1852 Stack<String> path, Element contentElement, Document xsdDocument,
1853 String elementPath)
1854 throws SystemException {
1855
1856 String name = contentElement.attributeValue("name");
1857
1858 if (Validator.isNull(name)) {
1859 return;
1860 }
1861
1862 String localPath =
1863 "dynamic-element[@name=" + HtmlUtil.escapeXPathAttribute(name) +
1864 "]";
1865
1866 String fullPath = elementPath + "/" + localPath;
1867
1868 XPath xPathSelector = SAXReaderUtil.createXPath(fullPath);
1869
1870 List<Node> curNodes = xPathSelector.selectNodes(xsdDocument);
1871
1872 if (curNodes.size() == 0) {
1873 contentElement.detach();
1874 }
1875
1876 path.push(localPath);
1877
1878 _removeOldContent(path, contentElement, xsdDocument);
1879
1880 path.pop();
1881 }
1882
1883 private static Log _log = LogFactoryUtil.getLog(JournalUtil.class);
1884
1885 private static Map<String, String> _customTokens;
1886 private static Pattern _friendlyURLPattern = Pattern.compile("[^a-z0-9_-]");
1887 private static Transformer _transformer = new Transformer(
1888 PropsKeys.JOURNAL_TRANSFORMER_LISTENER,
1889 PropsKeys.JOURNAL_ERROR_TEMPLATE, true);
1890
1891 }