001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.journal.util;
016    
017    import com.liferay.portal.kernel.configuration.Filter;
018    import com.liferay.portal.kernel.exception.PortalException;
019    import com.liferay.portal.kernel.exception.SystemException;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.search.Field;
023    import com.liferay.portal.kernel.search.Hits;
024    import com.liferay.portal.kernel.search.Indexer;
025    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
026    import com.liferay.portal.kernel.templateparser.Transformer;
027    import com.liferay.portal.kernel.templateparser.TransformerListener;
028    import com.liferay.portal.kernel.util.CharPool;
029    import com.liferay.portal.kernel.util.FriendlyURLNormalizerUtil;
030    import com.liferay.portal.kernel.util.GetterUtil;
031    import com.liferay.portal.kernel.util.HttpUtil;
032    import com.liferay.portal.kernel.util.LocaleUtil;
033    import com.liferay.portal.kernel.util.OrderByComparator;
034    import com.liferay.portal.kernel.util.PropsKeys;
035    import com.liferay.portal.kernel.util.StringPool;
036    import com.liferay.portal.kernel.util.StringUtil;
037    import com.liferay.portal.kernel.util.Time;
038    import com.liferay.portal.kernel.util.Tuple;
039    import com.liferay.portal.kernel.util.Validator;
040    import com.liferay.portal.kernel.xml.Attribute;
041    import com.liferay.portal.kernel.xml.Document;
042    import com.liferay.portal.kernel.xml.Element;
043    import com.liferay.portal.kernel.xml.Node;
044    import com.liferay.portal.kernel.xml.SAXReaderUtil;
045    import com.liferay.portal.kernel.xml.XPath;
046    import com.liferay.portal.model.Group;
047    import com.liferay.portal.model.Layout;
048    import com.liferay.portal.model.LayoutSet;
049    import com.liferay.portal.model.User;
050    import com.liferay.portal.service.ImageLocalServiceUtil;
051    import com.liferay.portal.service.LayoutLocalServiceUtil;
052    import com.liferay.portal.service.UserLocalServiceUtil;
053    import com.liferay.portal.theme.ThemeDisplay;
054    import com.liferay.portal.util.PortalUtil;
055    import com.liferay.portal.util.PropsUtil;
056    import com.liferay.portal.util.PropsValues;
057    import com.liferay.portal.util.WebKeys;
058    import com.liferay.portlet.asset.service.AssetTagLocalServiceUtil;
059    import com.liferay.portlet.dynamicdatamapping.util.DDMXMLUtil;
060    import com.liferay.portlet.journal.NoSuchArticleException;
061    import com.liferay.portlet.journal.model.JournalArticle;
062    import com.liferay.portlet.journal.model.JournalStructure;
063    import com.liferay.portlet.journal.model.JournalStructureConstants;
064    import com.liferay.portlet.journal.model.JournalTemplate;
065    import com.liferay.portlet.journal.service.JournalArticleImageLocalServiceUtil;
066    import com.liferay.portlet.journal.service.JournalArticleLocalServiceUtil;
067    import com.liferay.portlet.journal.service.JournalTemplateLocalServiceUtil;
068    import com.liferay.portlet.journal.util.comparator.ArticleCreateDateComparator;
069    import com.liferay.portlet.journal.util.comparator.ArticleDisplayDateComparator;
070    import com.liferay.portlet.journal.util.comparator.ArticleIDComparator;
071    import com.liferay.portlet.journal.util.comparator.ArticleModifiedDateComparator;
072    import com.liferay.portlet.journal.util.comparator.ArticleReviewDateComparator;
073    import com.liferay.portlet.journal.util.comparator.ArticleTitleComparator;
074    import com.liferay.portlet.journal.util.comparator.ArticleVersionComparator;
075    import com.liferay.util.ContentUtil;
076    import com.liferay.util.FiniteUniqueStack;
077    
078    import java.util.ArrayList;
079    import java.util.Date;
080    import java.util.HashMap;
081    import java.util.Iterator;
082    import java.util.List;
083    import java.util.Map;
084    import java.util.Stack;
085    
086    import javax.portlet.PortletPreferences;
087    import javax.portlet.PortletRequest;
088    import javax.portlet.PortletSession;
089    
090    /**
091     * @author Brian Wing Shun Chan
092     * @author Raymond Augé
093     * @author Wesley Gong
094     * @author Angelo Jefferson
095     * @author Hugo Huijser
096     */
097    public class JournalUtil {
098    
099            public static final int MAX_STACK_SIZE = 20;
100    
101            public static void addAllReservedEls(
102                    Element rootElement, Map<String, String> tokens, JournalArticle article,
103                    String languageId) {
104    
105                    JournalUtil.addReservedEl(
106                            rootElement, tokens, JournalStructureConstants.RESERVED_ARTICLE_ID,
107                            article.getArticleId());
108    
109                    JournalUtil.addReservedEl(
110                            rootElement, tokens,
111                            JournalStructureConstants.RESERVED_ARTICLE_VERSION,
112                            article.getVersion());
113    
114                    JournalUtil.addReservedEl(
115                            rootElement, tokens,
116                            JournalStructureConstants.RESERVED_ARTICLE_TITLE,
117                            article.getTitle(languageId));
118    
119                    JournalUtil.addReservedEl(
120                            rootElement, tokens,
121                            JournalStructureConstants.RESERVED_ARTICLE_URL_TITLE,
122                            article.getUrlTitle());
123    
124                    JournalUtil.addReservedEl(
125                            rootElement, tokens,
126                            JournalStructureConstants.RESERVED_ARTICLE_DESCRIPTION,
127                            article.getDescription(languageId));
128    
129                    JournalUtil.addReservedEl(
130                            rootElement, tokens,
131                            JournalStructureConstants.RESERVED_ARTICLE_TYPE, article.getType());
132    
133                    JournalUtil.addReservedEl(
134                            rootElement, tokens,
135                            JournalStructureConstants.RESERVED_ARTICLE_CREATE_DATE,
136                            article.getCreateDate());
137    
138                    JournalUtil.addReservedEl(
139                            rootElement, tokens,
140                            JournalStructureConstants.RESERVED_ARTICLE_MODIFIED_DATE,
141                            article.getModifiedDate());
142    
143                    if (article.getDisplayDate() != null) {
144                            JournalUtil.addReservedEl(
145                                    rootElement, tokens,
146                                    JournalStructureConstants.RESERVED_ARTICLE_DISPLAY_DATE,
147                                    article.getDisplayDate());
148                    }
149    
150                    JournalUtil.addReservedEl(
151                            rootElement, tokens,
152                            JournalStructureConstants.RESERVED_ARTICLE_SMALL_IMAGE_URL,
153                            article.getSmallImageURL());
154    
155                    String[] assetTagNames = new String[0];
156    
157                    try {
158                            assetTagNames = AssetTagLocalServiceUtil.getTagNames(
159                                    JournalArticle.class.getName(), article.getResourcePrimKey());
160                    }
161                    catch (SystemException se) {
162                    }
163    
164                    JournalUtil.addReservedEl(
165                            rootElement, tokens,
166                            JournalStructureConstants.RESERVED_ARTICLE_ASSET_TAG_NAMES,
167                            StringUtil.merge(assetTagNames));
168    
169                    JournalUtil.addReservedEl(
170                            rootElement, tokens,
171                            JournalStructureConstants.RESERVED_ARTICLE_AUTHOR_ID,
172                            String.valueOf(article.getUserId()));
173    
174                    String userName = StringPool.BLANK;
175                    String userEmailAddress = StringPool.BLANK;
176                    String userComments = StringPool.BLANK;
177                    String userJobTitle = StringPool.BLANK;
178    
179                    User user = null;
180    
181                    try {
182                            user = UserLocalServiceUtil.getUserById(article.getUserId());
183    
184                            userName = user.getFullName();
185                            userEmailAddress = user.getEmailAddress();
186                            userComments = user.getComments();
187                            userJobTitle = user.getJobTitle();
188                    }
189                    catch (PortalException pe) {
190                    }
191                    catch (SystemException se) {
192                    }
193    
194                    JournalUtil.addReservedEl(
195                            rootElement, tokens,
196                            JournalStructureConstants.RESERVED_ARTICLE_AUTHOR_NAME, userName);
197    
198                    JournalUtil.addReservedEl(
199                            rootElement, tokens,
200                            JournalStructureConstants.RESERVED_ARTICLE_AUTHOR_EMAIL_ADDRESS,
201                            userEmailAddress);
202    
203                    JournalUtil.addReservedEl(
204                            rootElement, tokens,
205                            JournalStructureConstants.RESERVED_ARTICLE_AUTHOR_COMMENTS,
206                            userComments);
207    
208                    JournalUtil.addReservedEl(
209                            rootElement, tokens,
210                            JournalStructureConstants.RESERVED_ARTICLE_AUTHOR_JOB_TITLE,
211                            userJobTitle);
212            }
213    
214            public static void addRecentArticle(
215                    PortletRequest portletRequest, JournalArticle article) {
216    
217                    if (article != null) {
218                            Stack<JournalArticle> stack = getRecentArticles(portletRequest);
219    
220                            stack.push(article);
221                    }
222            }
223    
224            public static void addRecentStructure(
225                    PortletRequest portletRequest, JournalStructure structure) {
226    
227                    if (structure != null) {
228                            Stack<JournalStructure> stack = getRecentStructures(portletRequest);
229    
230                            stack.push(structure);
231                    }
232            }
233    
234            public static void addRecentTemplate(
235                    PortletRequest portletRequest, JournalTemplate template) {
236    
237                    if (template != null) {
238                            Stack<JournalTemplate> stack = getRecentTemplates(portletRequest);
239    
240                            stack.push(template);
241                    }
242            }
243    
244            public static void addReservedEl(
245                    Element rootElement, Map<String, String> tokens, String name,
246                    Date value) {
247    
248                    addReservedEl(rootElement, tokens, name, Time.getRFC822(value));
249            }
250    
251            public static void addReservedEl(
252                    Element rootElement, Map<String, String> tokens, String name,
253                    double value) {
254    
255                    addReservedEl(rootElement, tokens, name, String.valueOf(value));
256            }
257    
258            public static void addReservedEl(
259                    Element rootElement, Map<String, String> tokens, String name,
260                    String value) {
261    
262                    // XML
263    
264                    if (rootElement != null) {
265                            Element dynamicElementElement = SAXReaderUtil.createElement(
266                                    "dynamic-element");
267    
268                            Attribute nameAttribute = SAXReaderUtil.createAttribute(
269                                    dynamicElementElement, "name", name);
270    
271                            dynamicElementElement.add(nameAttribute);
272    
273                            Attribute typeAttribute = SAXReaderUtil.createAttribute(
274                                    dynamicElementElement, "type", "text");
275    
276                            dynamicElementElement.add(typeAttribute);
277    
278                            Element dynamicContentElement = SAXReaderUtil.createElement(
279                                    "dynamic-content");
280    
281                            //dynamicContentElement.setText("<![CDATA[" + value + "]]>");
282                            dynamicContentElement.setText(value);
283    
284                            dynamicElementElement.add(dynamicContentElement);
285    
286                            rootElement.add(dynamicElementElement);
287                    }
288    
289                    // Tokens
290    
291                    tokens.put(
292                            StringUtil.replace(name, CharPool.DASH, CharPool.UNDERLINE), value);
293            }
294    
295            public static String formatVM(String vm) {
296                    return vm;
297            }
298    
299            public static OrderByComparator getArticleOrderByComparator(
300                    String orderByCol, String orderByType) {
301    
302                    boolean orderByAsc = false;
303    
304                    if (orderByType.equals("asc")) {
305                            orderByAsc = true;
306                    }
307    
308                    OrderByComparator orderByComparator = null;
309    
310                    if (orderByCol.equals("create-date")) {
311                            orderByComparator = new ArticleCreateDateComparator(orderByAsc);
312                    }
313                    else if (orderByCol.equals("display-date")) {
314                            orderByComparator = new ArticleDisplayDateComparator(orderByAsc);
315                    }
316                    else if (orderByCol.equals("id")) {
317                            orderByComparator = new ArticleIDComparator(orderByAsc);
318                    }
319                    else if (orderByCol.equals("modified-date")) {
320                            orderByComparator = new ArticleModifiedDateComparator(orderByAsc);
321                    }
322                    else if (orderByCol.equals("review-date")) {
323                            orderByComparator = new ArticleReviewDateComparator(orderByAsc);
324                    }
325                    else if (orderByCol.equals("title")) {
326                            orderByComparator = new ArticleTitleComparator(orderByAsc);
327                    }
328                    else if (orderByCol.equals("version")) {
329                            orderByComparator = new ArticleVersionComparator(orderByAsc);
330                    }
331    
332                    return orderByComparator;
333            }
334    
335            public static Tuple getArticles(Hits hits)
336                    throws PortalException, SystemException {
337    
338                    List<JournalArticle> articles = new ArrayList<JournalArticle>();
339                    boolean corruptIndex = false;
340    
341                    List<com.liferay.portal.kernel.search.Document> documents =
342                            hits.toList();
343    
344                    for (com.liferay.portal.kernel.search.Document document : documents) {
345                            long groupId = GetterUtil.getLong(document.get(Field.GROUP_ID));
346                            String articleId = document.get("articleId");
347    
348                            try {
349                                    JournalArticle article =
350                                            JournalArticleLocalServiceUtil.getArticle(
351                                                    groupId, articleId);
352    
353                                    articles.add(article);
354                            }
355                            catch (NoSuchArticleException nsae) {
356                                    corruptIndex = true;
357    
358                                    Indexer indexer = IndexerRegistryUtil.getIndexer(
359                                            JournalArticle.class);
360    
361                                    long companyId = GetterUtil.getLong(
362                                            document.get(Field.COMPANY_ID));
363    
364                                    indexer.delete(companyId, document.getUID());
365                            }
366                    }
367    
368                    return new Tuple(articles, corruptIndex);
369            }
370    
371            public static String getEmailArticleAddedBody(
372                    PortletPreferences preferences) {
373    
374                    String emailArticleAddedBody = preferences.getValue(
375                            "emailArticleAddedBody", StringPool.BLANK);
376    
377                    if (Validator.isNotNull(emailArticleAddedBody)) {
378                            return emailArticleAddedBody;
379                    }
380                    else {
381                            return ContentUtil.get(PropsUtil.get(
382                                    PropsKeys.JOURNAL_EMAIL_ARTICLE_ADDED_BODY));
383                    }
384            }
385    
386            public static boolean getEmailArticleAddedEnabled(
387                    PortletPreferences preferences) {
388    
389                    String emailArticleAddedEnabled = preferences.getValue(
390                            "emailArticleAddedEnabled", StringPool.BLANK);
391    
392                    if (Validator.isNotNull(emailArticleAddedEnabled)) {
393                            return GetterUtil.getBoolean(emailArticleAddedEnabled);
394                    }
395                    else {
396                            return GetterUtil.getBoolean(PropsUtil.get(
397                                    PropsKeys.JOURNAL_EMAIL_ARTICLE_ADDED_ENABLED));
398                    }
399            }
400    
401            public static String getEmailArticleAddedSubject(
402                    PortletPreferences preferences) {
403    
404                    String emailArticleAddedSubject = preferences.getValue(
405                            "emailArticleAddedSubject", StringPool.BLANK);
406    
407                    if (Validator.isNotNull(emailArticleAddedSubject)) {
408                            return emailArticleAddedSubject;
409                    }
410                    else {
411                            return ContentUtil.get(PropsUtil.get(
412                                    PropsKeys.JOURNAL_EMAIL_ARTICLE_ADDED_SUBJECT));
413                    }
414            }
415    
416            public static String getEmailArticleApprovalDeniedBody(
417                    PortletPreferences preferences) {
418    
419                    String emailArticleApprovalDeniedBody = preferences.getValue(
420                            "emailArticleApprovalDeniedBody", StringPool.BLANK);
421    
422                    if (Validator.isNotNull(emailArticleApprovalDeniedBody)) {
423                            return emailArticleApprovalDeniedBody;
424                    }
425                    else {
426                            return ContentUtil.get(PropsUtil.get(
427                                    PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_DENIED_BODY));
428                    }
429            }
430    
431            public static boolean getEmailArticleApprovalDeniedEnabled(
432                    PortletPreferences preferences) {
433    
434                    String emailArticleApprovalDeniedEnabled = preferences.getValue(
435                            "emailArticleApprovalDeniedEnabled", StringPool.BLANK);
436    
437                    if (Validator.isNotNull(emailArticleApprovalDeniedEnabled)) {
438                            return GetterUtil.getBoolean(emailArticleApprovalDeniedEnabled);
439                    }
440                    else {
441                            return GetterUtil.getBoolean(PropsUtil.get(
442                                    PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_DENIED_ENABLED));
443                    }
444            }
445    
446            public static String getEmailArticleApprovalDeniedSubject(
447                    PortletPreferences preferences) {
448    
449                    String emailArticleApprovalDeniedSubject = preferences.getValue(
450                            "emailArticleApprovalDeniedSubject", StringPool.BLANK);
451    
452                    if (Validator.isNotNull(emailArticleApprovalDeniedSubject)) {
453                            return emailArticleApprovalDeniedSubject;
454                    }
455                    else {
456                            return ContentUtil.get(PropsUtil.get(
457                                    PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_DENIED_SUBJECT));
458                    }
459            }
460    
461            public static String getEmailArticleApprovalGrantedBody(
462                    PortletPreferences preferences) {
463    
464                    String emailArticleApprovalGrantedBody = preferences.getValue(
465                            "emailArticleApprovalGrantedBody", StringPool.BLANK);
466    
467                    if (Validator.isNotNull(emailArticleApprovalGrantedBody)) {
468                            return emailArticleApprovalGrantedBody;
469                    }
470                    else {
471                            return ContentUtil.get(PropsUtil.get(
472                                    PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_GRANTED_BODY));
473                    }
474            }
475    
476            public static boolean getEmailArticleApprovalGrantedEnabled(
477                    PortletPreferences preferences) {
478    
479                    String emailArticleApprovalGrantedEnabled = preferences.getValue(
480                            "emailArticleApprovalGrantedEnabled", StringPool.BLANK);
481    
482                    if (Validator.isNotNull(emailArticleApprovalGrantedEnabled)) {
483                            return GetterUtil.getBoolean(emailArticleApprovalGrantedEnabled);
484                    }
485                    else {
486                            return GetterUtil.getBoolean(PropsUtil.get(
487                                    PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_GRANTED_ENABLED));
488                    }
489            }
490    
491            public static String getEmailArticleApprovalGrantedSubject(
492                    PortletPreferences preferences) {
493    
494                    String emailArticleApprovalGrantedSubject = preferences.getValue(
495                            "emailArticleApprovalGrantedSubject", StringPool.BLANK);
496    
497                    if (Validator.isNotNull(emailArticleApprovalGrantedSubject)) {
498                            return emailArticleApprovalGrantedSubject;
499                    }
500                    else {
501                            return ContentUtil.get(PropsUtil.get(
502                                    PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_GRANTED_SUBJECT));
503                    }
504            }
505    
506            public static String getEmailArticleApprovalRequestedBody(
507                    PortletPreferences preferences) {
508    
509                    String emailArticleApprovalRequestedBody = preferences.getValue(
510                            "emailArticleApprovalRequestedBody", StringPool.BLANK);
511    
512                    if (Validator.isNotNull(emailArticleApprovalRequestedBody)) {
513                            return emailArticleApprovalRequestedBody;
514                    }
515                    else {
516                            return ContentUtil.get(PropsUtil.get(
517                                    PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_REQUESTED_BODY));
518                    }
519            }
520    
521            public static boolean getEmailArticleApprovalRequestedEnabled(
522                    PortletPreferences preferences) {
523    
524                    String emailArticleApprovalRequestedEnabled = preferences.getValue(
525                            "emailArticleApprovalRequestedEnabled", StringPool.BLANK);
526    
527                    if (Validator.isNotNull(emailArticleApprovalRequestedEnabled)) {
528                            return GetterUtil.getBoolean(emailArticleApprovalRequestedEnabled);
529                    }
530                    else {
531                            return GetterUtil.getBoolean(PropsUtil.get(
532                                    PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_REQUESTED_ENABLED));
533                    }
534            }
535    
536            public static String getEmailArticleApprovalRequestedSubject(
537                    PortletPreferences preferences) {
538    
539                    String emailArticleApprovalRequestedSubject = preferences.getValue(
540                            "emailArticleApprovalRequestedSubject", StringPool.BLANK);
541    
542                    if (Validator.isNotNull(emailArticleApprovalRequestedSubject)) {
543                            return emailArticleApprovalRequestedSubject;
544                    }
545                    else {
546                            return ContentUtil.get(PropsUtil.get(
547                                    PropsKeys.JOURNAL_EMAIL_ARTICLE_APPROVAL_REQUESTED_SUBJECT));
548                    }
549            }
550    
551            public static String getEmailArticleReviewBody(
552                    PortletPreferences preferences) {
553    
554                    String emailArticleReviewBody = preferences.getValue(
555                            "emailArticleReviewBody", StringPool.BLANK);
556    
557                    if (Validator.isNotNull(emailArticleReviewBody)) {
558                            return emailArticleReviewBody;
559                    }
560                    else {
561                            return ContentUtil.get(PropsUtil.get(
562                                    PropsKeys.JOURNAL_EMAIL_ARTICLE_REVIEW_BODY));
563                    }
564            }
565    
566            public static boolean getEmailArticleReviewEnabled(
567                    PortletPreferences preferences) {
568    
569                    String emailArticleReviewEnabled = preferences.getValue(
570                            "emailArticleReviewEnabled", StringPool.BLANK);
571    
572                    if (Validator.isNotNull(emailArticleReviewEnabled)) {
573                            return GetterUtil.getBoolean(emailArticleReviewEnabled);
574                    }
575                    else {
576                            return GetterUtil.getBoolean(PropsUtil.get(
577                                    PropsKeys.JOURNAL_EMAIL_ARTICLE_REVIEW_ENABLED));
578                    }
579            }
580    
581            public static String getEmailArticleReviewSubject(
582                    PortletPreferences preferences) {
583    
584                    String emailArticleReviewSubject = preferences.getValue(
585                            "emailArticleReviewSubject", StringPool.BLANK);
586    
587                    if (Validator.isNotNull(emailArticleReviewSubject)) {
588                            return emailArticleReviewSubject;
589                    }
590                    else {
591                            return ContentUtil.get(PropsUtil.get(
592                                    PropsKeys.JOURNAL_EMAIL_ARTICLE_REVIEW_SUBJECT));
593                    }
594            }
595    
596            public static String getEmailArticleUpdatedBody(
597                    PortletPreferences preferences) {
598    
599                    String emailArticleUpdatedBody = preferences.getValue(
600                            "emailArticleUpdatedBody", StringPool.BLANK);
601    
602                    if (Validator.isNotNull(emailArticleUpdatedBody)) {
603                            return emailArticleUpdatedBody;
604                    }
605                    else {
606                            return ContentUtil.get(PropsUtil.get(
607                                    PropsKeys.JOURNAL_EMAIL_ARTICLE_UPDATED_BODY));
608                    }
609            }
610    
611            public static boolean getEmailArticleUpdatedEnabled(
612                    PortletPreferences preferences) {
613    
614                    String emailArticleUpdatedEnabled = preferences.getValue(
615                            "emailArticleUpdatedEnabled", StringPool.BLANK);
616    
617                    if (Validator.isNotNull(emailArticleUpdatedEnabled)) {
618                            return GetterUtil.getBoolean(emailArticleUpdatedEnabled);
619                    }
620                    else {
621                            return GetterUtil.getBoolean(PropsUtil.get(
622                                    PropsKeys.JOURNAL_EMAIL_ARTICLE_UPDATED_ENABLED));
623                    }
624            }
625    
626            public static String getEmailArticleUpdatedSubject(
627                    PortletPreferences preferences) {
628    
629                    String emailArticleUpdatedSubject = preferences.getValue(
630                            "emailArticleUpdatedSubject", StringPool.BLANK);
631    
632                    if (Validator.isNotNull(emailArticleUpdatedSubject)) {
633                            return emailArticleUpdatedSubject;
634                    }
635                    else {
636                            return ContentUtil.get(PropsUtil.get(
637                                    PropsKeys.JOURNAL_EMAIL_ARTICLE_UPDATED_SUBJECT));
638                    }
639            }
640    
641            public static String getEmailFromAddress(
642                            PortletPreferences preferences, long companyId)
643                    throws SystemException {
644    
645                    return PortalUtil.getEmailFromAddress(
646                            preferences, companyId, PropsValues.JOURNAL_EMAIL_FROM_ADDRESS);
647            }
648    
649            public static String getEmailFromName(
650                            PortletPreferences preferences, long companyId)
651                    throws SystemException {
652    
653                    return PortalUtil.getEmailFromName(
654                            preferences, companyId, PropsValues.JOURNAL_EMAIL_FROM_NAME);
655            }
656    
657            public static Stack<JournalArticle> getRecentArticles(
658                    PortletRequest portletRequest) {
659    
660                    PortletSession portletSession = portletRequest.getPortletSession();
661    
662                    Stack<JournalArticle> recentArticles =
663                            (Stack<JournalArticle>)portletSession.getAttribute(
664                                    WebKeys.JOURNAL_RECENT_ARTICLES);
665    
666                    if (recentArticles == null) {
667                            recentArticles = new FiniteUniqueStack<JournalArticle>(
668                                    MAX_STACK_SIZE);
669    
670                            portletSession.setAttribute(
671                                    WebKeys.JOURNAL_RECENT_ARTICLES, recentArticles);
672                    }
673    
674                    return recentArticles;
675            }
676    
677            public static Stack<JournalStructure> getRecentStructures(
678                    PortletRequest portletRequest) {
679    
680                    PortletSession portletSession = portletRequest.getPortletSession();
681    
682                    Stack<JournalStructure> recentStructures =
683                            (Stack<JournalStructure>)portletSession.getAttribute(
684                                    WebKeys.JOURNAL_RECENT_STRUCTURES);
685    
686                    if (recentStructures == null) {
687                            recentStructures = new FiniteUniqueStack<JournalStructure>(
688                                    MAX_STACK_SIZE);
689    
690                            portletSession.setAttribute(
691                                    WebKeys.JOURNAL_RECENT_STRUCTURES, recentStructures);
692                    }
693    
694                    return recentStructures;
695            }
696    
697            public static Stack<JournalTemplate> getRecentTemplates(
698                    PortletRequest portletRequest) {
699    
700                    PortletSession portletSession = portletRequest.getPortletSession();
701    
702                    Stack<JournalTemplate> recentTemplates =
703                            (Stack<JournalTemplate>)portletSession.getAttribute(
704                                    WebKeys.JOURNAL_RECENT_TEMPLATES);
705    
706                    if (recentTemplates == null) {
707                            recentTemplates = new FiniteUniqueStack<JournalTemplate>(
708                                    MAX_STACK_SIZE);
709    
710                            portletSession.setAttribute(
711                                    WebKeys.JOURNAL_RECENT_TEMPLATES, recentTemplates);
712                    }
713    
714                    return recentTemplates;
715            }
716    
717            public static String getTemplateScript(
718                    JournalTemplate template, Map<String, String> tokens, String languageId,
719                    boolean transform) {
720    
721                    String script = template.getXsl();
722    
723                    if (transform) {
724    
725                            // Listeners
726    
727                            String[] listeners = PropsUtil.getArray(
728                                    PropsKeys.JOURNAL_TRANSFORMER_LISTENER);
729    
730                            for (int i = 0; i < listeners.length; i++) {
731                                    TransformerListener listener = null;
732    
733                                    try {
734                                            listener =
735                                                    (TransformerListener)Class.forName(
736                                                            listeners[i]).newInstance();
737    
738                                            listener.setTemplateDriven(true);
739                                            listener.setLanguageId(languageId);
740                                            listener.setTokens(tokens);
741                                    }
742                                    catch (Exception e) {
743                                            _log.error(e, e);
744                                    }
745    
746                                    // Modify transform script
747    
748                                    if (listener != null) {
749                                            script = listener.onScript(script);
750                                    }
751                            }
752                    }
753    
754                    return script;
755            }
756    
757            public static String getTemplateScript(
758                            long groupId, String templateId, Map<String, String> tokens,
759                            String languageId)
760                    throws PortalException, SystemException {
761    
762                    return getTemplateScript(groupId, templateId, tokens, languageId, true);
763            }
764    
765            public static String getTemplateScript(
766                            long groupId, String templateId, Map<String, String> tokens,
767                            String languageId, boolean transform)
768                    throws PortalException, SystemException {
769    
770                    JournalTemplate template = JournalTemplateLocalServiceUtil.getTemplate(
771                            groupId, templateId);
772    
773                    return getTemplateScript(template, tokens, languageId, transform);
774            }
775    
776            public static Map<String, String> getTokens(
777                            long groupId, ThemeDisplay themeDisplay)
778                    throws PortalException, SystemException {
779    
780                    return getTokens(groupId, themeDisplay, null);
781            }
782    
783            public static Map<String, String> getTokens(
784                            long groupId, ThemeDisplay themeDisplay, String xmlRequest)
785                    throws PortalException, SystemException {
786    
787                    Map<String, String> tokens = new HashMap<String, String>();
788    
789                    if (themeDisplay != null) {
790                            _populateTokens(tokens, groupId, themeDisplay);
791                    }
792                    else if (Validator.isNotNull(xmlRequest)) {
793                            try {
794                                    _populateTokens(tokens, groupId, xmlRequest);
795                            }
796                            catch (Exception e) {
797                                    if (_log.isWarnEnabled()) {
798                                            _log.warn(e, e);
799                                    }
800                            }
801                    }
802    
803                    return tokens;
804            }
805    
806            public static String getUrlTitle(long id, String title) {
807                    title = title.trim().toLowerCase();
808    
809                    if (Validator.isNull(title) || Validator.isNumber(title) ||
810                            title.equals("rss")) {
811    
812                            return String.valueOf(id);
813                    }
814                    else {
815                            return FriendlyURLNormalizerUtil.normalize(
816                                    title, _URL_TITLE_REPLACE_CHARS);
817                    }
818            }
819    
820            public static String mergeArticleContent(
821                    String curContent, String newContent, boolean removeNullElements) {
822    
823                    try {
824                            Document curDocument = SAXReaderUtil.read(curContent);
825                            Document newDocument = SAXReaderUtil.read(newContent);
826    
827                            Element curRootElement = curDocument.getRootElement();
828                            Element newRootElement = newDocument.getRootElement();
829    
830                            curRootElement.addAttribute(
831                                    "default-locale",
832                                    newRootElement.attributeValue("default-locale"));
833                            curRootElement.addAttribute(
834                                    "available-locales",
835                                    newRootElement.attributeValue("available-locales"));
836    
837                            _mergeArticleContentUpdate(
838                                    curDocument, newRootElement,
839                                    LocaleUtil.toLanguageId(LocaleUtil.getDefault()));
840    
841                            if (removeNullElements) {
842                                    _mergeArticleContentDelete(curRootElement, newDocument);
843                            }
844    
845                            curContent = DDMXMLUtil.formatXML(curDocument);
846                    }
847                    catch (Exception e) {
848                            _log.error(e, e);
849                    }
850    
851                    return curContent;
852            }
853    
854            public static void removeArticleLocale(Element element, String languageId)
855                    throws PortalException, SystemException {
856    
857                    for (Element dynamicElementElement :
858                                    element.elements("dynamic-element")) {
859    
860                            for (Element dynamicContentElement :
861                                            dynamicElementElement.elements("dynamic-content")) {
862    
863                                    String curLanguageId = GetterUtil.getString(
864                                            dynamicContentElement.attributeValue("language-id"));
865    
866                                    if (curLanguageId.equals(languageId)) {
867                                            long id = GetterUtil.getLong(
868                                                    dynamicContentElement.attributeValue("id"));
869    
870                                            if (id > 0) {
871                                                    ImageLocalServiceUtil.deleteImage(id);
872                                            }
873    
874                                            dynamicContentElement.detach();
875                                    }
876                            }
877    
878                            removeArticleLocale(dynamicElementElement, languageId);
879                    }
880            }
881    
882            public static String removeArticleLocale(
883                    String content, String languageId) {
884    
885                    try {
886                            Document document = SAXReaderUtil.read(content);
887    
888                            Element rootElement = document.getRootElement();
889    
890                            String availableLocales = rootElement.attributeValue(
891                                    "available-locales");
892    
893                            if (availableLocales == null) {
894                                    return content;
895                            }
896    
897                            availableLocales = StringUtil.remove(availableLocales, languageId);
898    
899                            if (availableLocales.endsWith(",")) {
900                                    availableLocales = availableLocales.substring(
901                                            0, availableLocales.length() - 1);
902                            }
903    
904                            rootElement.addAttribute("available-locales", availableLocales);
905    
906                            removeArticleLocale(rootElement, languageId);
907    
908                            content = DDMXMLUtil.formatXML(document);
909                    }
910                    catch (Exception e) {
911                            _log.error(e, e);
912                    }
913    
914                    return content;
915            }
916    
917            public static String removeOldContent(String content, String xsd) {
918                    try {
919                            Document contentDoc = SAXReaderUtil.read(content);
920                            Document xsdDoc = SAXReaderUtil.read(xsd);
921    
922                            Element contentRoot = contentDoc.getRootElement();
923    
924                            Stack<String> path = new Stack<String>();
925    
926                            path.push(contentRoot.getName());
927    
928                            _removeOldContent(path, contentRoot, xsdDoc);
929    
930                            content = DDMXMLUtil.formatXML(contentDoc);
931                    }
932                    catch (Exception e) {
933                            _log.error(e, e);
934                    }
935    
936                    return content;
937            }
938    
939            public static void removeRecentArticle(
940                    PortletRequest portletRequest, String articleId) {
941    
942                    removeRecentArticle(portletRequest, articleId, 0);
943            }
944    
945            public static void removeRecentArticle(
946                    PortletRequest portletRequest, String articleId, double version) {
947    
948                    Stack<JournalArticle> stack = getRecentArticles(portletRequest);
949    
950                    Iterator<JournalArticle> itr = stack.iterator();
951    
952                    while (itr.hasNext()) {
953                            JournalArticle journalArticle = itr.next();
954    
955                            if (journalArticle.getArticleId().equals(articleId) &&
956                                    ((journalArticle.getVersion() == version) ||
957                                     (version == 0))) {
958    
959                                    itr.remove();
960                            }
961                    }
962            }
963    
964            public static void removeRecentStructure(
965                    PortletRequest portletRequest, String structureId) {
966    
967                    Stack<JournalStructure> stack = getRecentStructures(portletRequest);
968    
969                    Iterator<JournalStructure> itr = stack.iterator();
970    
971                    while (itr.hasNext()) {
972                            JournalStructure journalStructure = itr.next();
973    
974                            if (journalStructure.getStructureId().equals(structureId)) {
975                                    itr.remove();
976    
977                                    break;
978                            }
979                    }
980            }
981    
982            public static void removeRecentTemplate(
983                    PortletRequest portletRequest, String templateId) {
984    
985                    Stack<JournalTemplate> stack = getRecentTemplates(portletRequest);
986    
987                    Iterator<JournalTemplate> itr = stack.iterator();
988    
989                    while (itr.hasNext()) {
990                            JournalTemplate journalTemplate = itr.next();
991    
992                            if (journalTemplate.getTemplateId().equals(templateId)) {
993                                    itr.remove();
994    
995                                    break;
996                            }
997                    }
998            }
999    
1000            public static String transform(
1001                            ThemeDisplay themeDisplay, Map<String, String> tokens,
1002                            String viewMode, String languageId, String xml, String script,
1003                            String langType)
1004                    throws Exception {
1005    
1006                    return _transformer.transform(
1007                            themeDisplay, tokens, viewMode, languageId, xml, script, langType);
1008            }
1009    
1010            private static void _addElementOptions(
1011                    Element curContentElement, Element newContentElement) {
1012    
1013                    List<Element> newElementOptions = newContentElement.elements("option");
1014    
1015                    for (Element newElementOption : newElementOptions) {
1016                            Element curElementOption = SAXReaderUtil.createElement("option");
1017    
1018                            curElementOption.addCDATA(newElementOption.getText());
1019    
1020                            curContentElement.add(curElementOption);
1021                    }
1022            }
1023    
1024            private static Element _getElementByInstanceId(
1025                    Document document, String instanceId) {
1026    
1027                    XPath xPathSelector = SAXReaderUtil.createXPath(
1028                            "//dynamic-element[@instance-id='" + instanceId + "']");
1029    
1030                    List<Node> nodes = xPathSelector.selectNodes(document);
1031    
1032                    if (nodes.size() == 1) {
1033                            return (Element)nodes.get(0);
1034                    }
1035                    else {
1036                            return null;
1037                    }
1038            }
1039    
1040            private static void _mergeArticleContentDelete(
1041                            Element curParentElement, Document newDocument)
1042                    throws Exception {
1043    
1044                    List<Element> curElements = curParentElement.elements(
1045                            "dynamic-element");
1046    
1047                    for (int i = 0; i < curElements.size(); i++) {
1048                            Element curElement = curElements.get(i);
1049    
1050                            _mergeArticleContentDelete(curElement, newDocument);
1051    
1052                            String instanceId = curElement.attributeValue("instance-id");
1053    
1054                            Element newElement = _getElementByInstanceId(
1055                                    newDocument, instanceId);
1056    
1057                            if (newElement == null) {
1058                                    curElement.detach();
1059    
1060                                    String type = curElement.attributeValue("type");
1061    
1062                                    if (type.equals("image")) {
1063                                            _mergeArticleContentDeleteImages(
1064                                                    curElement.elements("dynamic-content"));
1065                                    }
1066                            }
1067                    }
1068            }
1069    
1070            private static void _mergeArticleContentDeleteImages(List<Element> elements)
1071                    throws Exception {
1072    
1073                    for (Element element : elements) {
1074                            long articleImageId = GetterUtil.getLong(
1075                                    element.attributeValue("id"));
1076    
1077                            JournalArticleImageLocalServiceUtil.deleteArticleImage(
1078                                    articleImageId);
1079                    }
1080            }
1081    
1082            private static void _mergeArticleContentUpdate(
1083                            Document curDocument, Element newParentElement, Element newElement,
1084                            int pos, String defaultLocale)
1085                    throws Exception {
1086    
1087                    _mergeArticleContentUpdate(curDocument, newElement, defaultLocale);
1088    
1089                    String instanceId = newElement.attributeValue("instance-id");
1090    
1091                    Element curElement = _getElementByInstanceId(curDocument, instanceId);
1092    
1093                    if (curElement != null) {
1094                            _mergeArticleContentUpdate(curElement, newElement, defaultLocale);
1095                    }
1096                    else {
1097                            String parentInstanceId = newParentElement.attributeValue(
1098                                    "instance-id");
1099    
1100                            if (Validator.isNull(parentInstanceId)) {
1101                                    Element curRoot = curDocument.getRootElement();
1102    
1103                                    List<Element> curRootElements = curRoot.elements();
1104    
1105                                    curRootElements.add(pos, newElement.createCopy());
1106                            }
1107                            else {
1108                                    Element curParentElement = _getElementByInstanceId(
1109                                            curDocument, parentInstanceId);
1110    
1111                                    if (curParentElement != null) {
1112                                            List<Element> curParentElements =
1113                                                    curParentElement.elements();
1114    
1115                                            curParentElements.add(pos, newElement.createCopy());
1116                                    }
1117                            }
1118                    }
1119            }
1120    
1121            private static void _mergeArticleContentUpdate(
1122                            Document curDocument, Element newParentElement,
1123                            String defaultLocale)
1124                    throws Exception {
1125    
1126                    List<Element> newElements = newParentElement.elements(
1127                            "dynamic-element");
1128    
1129                    for (int i = 0; i < newElements.size(); i++) {
1130                            Element newElement = newElements.get(i);
1131    
1132                            _mergeArticleContentUpdate(
1133                                    curDocument, newParentElement, newElement, i, defaultLocale);
1134                    }
1135            }
1136    
1137            private static void _mergeArticleContentUpdate(
1138                    Element curElement, Element newElement, String defaultLocale) {
1139    
1140                    Attribute curTypeAttribute = curElement.attribute("type");
1141                    Attribute newTypeAttribute = newElement.attribute("type");
1142    
1143                    curTypeAttribute.setValue(newTypeAttribute.getValue());
1144    
1145                    Attribute curIndexTypeAttribute = curElement.attribute("index-type");
1146                    Attribute newIndexTypeAttribute = newElement.attribute("index-type");
1147    
1148                    if (newIndexTypeAttribute != null) {
1149                            if (curIndexTypeAttribute == null) {
1150                                    curElement.addAttribute(
1151                                            "index-type", newIndexTypeAttribute.getValue());
1152                            } else {
1153                                    curIndexTypeAttribute.setValue(
1154                                            newIndexTypeAttribute.getValue());
1155                            }
1156                    }
1157    
1158                    Element newContentElement = newElement.elements(
1159                            "dynamic-content").get(0);
1160    
1161                    String newLanguageId = newContentElement.attributeValue("language-id");
1162                    String newValue = newContentElement.getText();
1163    
1164                    String indexType = newElement.attributeValue("index-type");
1165    
1166                    if (Validator.isNotNull(indexType)) {
1167                            curElement.addAttribute("index-type", indexType);
1168                    }
1169    
1170                    List<Element> curContentElements = curElement.elements(
1171                            "dynamic-content");
1172    
1173                    if (Validator.isNull(newLanguageId)) {
1174                            for (Element curContentElement : curContentElements) {
1175                                    curContentElement.detach();
1176                            }
1177    
1178                            Element curContentElement = SAXReaderUtil.createElement(
1179                                    "dynamic-content");
1180    
1181                            if (newContentElement.element("option") != null) {
1182                                    _addElementOptions(curContentElement, newContentElement);
1183                            }
1184                            else {
1185                                    curContentElement.addCDATA(newValue);
1186                            }
1187    
1188                            curElement.add(curContentElement);
1189                    }
1190                    else {
1191                            boolean alreadyExists = false;
1192    
1193                            for (Element curContentElement : curContentElements) {
1194                                    String curLanguageId = curContentElement.attributeValue(
1195                                            "language-id");
1196    
1197                                    if (newLanguageId.equals(curLanguageId)) {
1198                                            alreadyExists = true;
1199    
1200                                            curContentElement.clearContent();
1201    
1202                                            if (newContentElement.element("option") != null) {
1203                                                    _addElementOptions(
1204                                                            curContentElement, newContentElement);
1205                                            }
1206                                            else {
1207                                                    curContentElement.addCDATA(newValue);
1208                                            }
1209    
1210                                            break;
1211                                    }
1212                            }
1213    
1214                            if (!alreadyExists) {
1215                                    Element curContentElement = curContentElements.get(0);
1216    
1217                                    String curLanguageId = curContentElement.attributeValue(
1218                                            "language-id");
1219    
1220                                    if (Validator.isNull(curLanguageId)) {
1221                                            if (newLanguageId.equals(defaultLocale)) {
1222                                                    curContentElement.clearContent();
1223    
1224                                                    if (newContentElement.element("option") != null) {
1225                                                            _addElementOptions(
1226                                                                    curContentElement, newContentElement);
1227                                                    }
1228                                                    else {
1229                                                            curContentElement.addCDATA(newValue);
1230                                                    }
1231                                            }
1232                                            else {
1233                                                    curElement.add(newContentElement.createCopy());
1234                                            }
1235    
1236                                            curContentElement.addAttribute(
1237                                                    "language-id", defaultLocale);
1238                                    }
1239                                    else {
1240                                            curElement.add(newContentElement.createCopy());
1241                                    }
1242                            }
1243                    }
1244            }
1245    
1246            private static void _populateCustomTokens(Map<String, String> tokens) {
1247                    if (_customTokens == null) {
1248                            synchronized (JournalUtil.class) {
1249                                    _customTokens = new HashMap<String, String>();
1250    
1251                                    for (String customToken :
1252                                                    PropsValues.JOURNAL_ARTICLE_CUSTOM_TOKENS) {
1253    
1254                                            String value = PropsUtil.get(
1255                                                    PropsKeys.JOURNAL_ARTICLE_CUSTOM_TOKEN_VALUE,
1256                                                    new Filter(customToken));
1257    
1258                                            _customTokens.put(customToken, value);
1259                                    }
1260                            }
1261                    }
1262    
1263                    if (!_customTokens.isEmpty()) {
1264                            tokens.putAll(_customTokens);
1265                    }
1266            }
1267    
1268            private static void _populateTokens(
1269                            Map<String, String> tokens, long groupId, String xmlRequest)
1270                    throws Exception {
1271    
1272                    Document requestDocument = SAXReaderUtil.read(xmlRequest);
1273    
1274                    Element rootElement = requestDocument.getRootElement();
1275    
1276                    Element themeDisplayElement = rootElement.element("theme-display");
1277    
1278                    Layout layout = LayoutLocalServiceUtil.getLayout(
1279                            GetterUtil.getLong(themeDisplayElement.elementText("plid")));
1280    
1281                    Group group = layout.getGroup();
1282    
1283                    LayoutSet layoutSet = layout.getLayoutSet();
1284    
1285                    String friendlyUrlCurrent = null;
1286    
1287                    if (layout.isPublicLayout()) {
1288                            friendlyUrlCurrent = themeDisplayElement.elementText(
1289                                    "path-friendly-url-public");
1290                    }
1291                    else if (group.isUserGroup()) {
1292                            friendlyUrlCurrent = themeDisplayElement.elementText(
1293                                    "path-friendly-url-private-user");
1294                    }
1295                    else {
1296                            friendlyUrlCurrent = themeDisplayElement.elementText(
1297                                    "path-friendly-url-private-group");
1298                    }
1299    
1300                    String layoutSetFriendlyUrl = StringPool.BLANK;
1301    
1302                    String virtualHostname = layoutSet.getVirtualHostname();
1303    
1304                    if (Validator.isNull(virtualHostname) ||
1305                            !virtualHostname.equals(
1306                                    themeDisplayElement.elementText("server-name"))) {
1307    
1308                            layoutSetFriendlyUrl = friendlyUrlCurrent + group.getFriendlyURL();
1309                    }
1310    
1311                    tokens.put("cdn_host", themeDisplayElement.elementText("cdn-host"));
1312                    tokens.put("company_id", themeDisplayElement.elementText("company-id"));
1313                    tokens.put("friendly_url_current", friendlyUrlCurrent);
1314                    tokens.put(
1315                            "friendly_url_private_group",
1316                            themeDisplayElement.elementText("path-friendly-url-private-group"));
1317                    tokens.put(
1318                            "friendly_url_private_user",
1319                            themeDisplayElement.elementText("path-friendly-url-private-user"));
1320                    tokens.put(
1321                            "friendly_url_public",
1322                            themeDisplayElement.elementText("path-friendly-url-public"));
1323                    tokens.put("group_friendly_url", group.getFriendlyURL());
1324                    tokens.put("group_id", String.valueOf(groupId));
1325                    tokens.put("image_path", themeDisplayElement.elementText("path-image"));
1326                    tokens.put("layout_set_friendly_url", layoutSetFriendlyUrl);
1327                    tokens.put("main_path", themeDisplayElement.elementText("path-main"));
1328                    tokens.put(
1329                            "portal_ctx", themeDisplayElement.elementText("path-context"));
1330                    tokens.put(
1331                            "portal_url",
1332                            HttpUtil.removeProtocol(
1333                                    themeDisplayElement.elementText("url-portal")));
1334                    tokens.put(
1335                            "protocol",
1336                            HttpUtil.getProtocol(
1337                                    themeDisplayElement.elementText("url-portal")));
1338                    tokens.put(
1339                            "root_path", themeDisplayElement.elementText("path-context"));
1340                    tokens.put(
1341                            "theme_image_path",
1342                            themeDisplayElement.elementText("path-theme-images"));
1343    
1344                    _populateCustomTokens(tokens);
1345    
1346                    // Deprecated tokens
1347    
1348                    tokens.put(
1349                            "friendly_url",
1350                            themeDisplayElement.elementText("path-friendly-url-public"));
1351                    tokens.put(
1352                            "friendly_url_private",
1353                            themeDisplayElement.elementText("path-friendly-url-private-group"));
1354                    tokens.put(
1355                            "page_url",
1356                            themeDisplayElement.elementText("path-friendly-url-public"));
1357            }
1358    
1359            private static void _populateTokens(
1360                            Map<String, String> tokens, long groupId, ThemeDisplay themeDisplay)
1361                    throws PortalException, SystemException {
1362    
1363                    Layout layout = themeDisplay.getLayout();
1364    
1365                    Group group = layout.getGroup();
1366    
1367                    LayoutSet layoutSet = layout.getLayoutSet();
1368    
1369                    String friendlyUrlCurrent = null;
1370    
1371                    if (layout.isPublicLayout()) {
1372                            friendlyUrlCurrent = themeDisplay.getPathFriendlyURLPublic();
1373                    }
1374                    else if (group.isUserGroup()) {
1375                            friendlyUrlCurrent = themeDisplay.getPathFriendlyURLPrivateUser();
1376                    }
1377                    else {
1378                            friendlyUrlCurrent = themeDisplay.getPathFriendlyURLPrivateGroup();
1379                    }
1380    
1381                    String layoutSetFriendlyUrl = StringPool.BLANK;
1382    
1383                    String virtualHostname = layoutSet.getVirtualHostname();
1384    
1385                    if (Validator.isNull(virtualHostname) ||
1386                            !virtualHostname.equals(themeDisplay.getServerName())) {
1387    
1388                            layoutSetFriendlyUrl = friendlyUrlCurrent + group.getFriendlyURL();
1389                    }
1390    
1391                    tokens.put("cdn_host", themeDisplay.getCDNHost());
1392                    tokens.put("company_id", String.valueOf(themeDisplay.getCompanyId()));
1393                    tokens.put("friendly_url_current", friendlyUrlCurrent);
1394                    tokens.put(
1395                            "friendly_url_private_group",
1396                            themeDisplay.getPathFriendlyURLPrivateGroup());
1397                    tokens.put(
1398                            "friendly_url_private_user",
1399                            themeDisplay.getPathFriendlyURLPrivateUser());
1400                    tokens.put(
1401                            "friendly_url_public", themeDisplay.getPathFriendlyURLPublic());
1402                    tokens.put("group_friendly_url", group.getFriendlyURL());
1403                    tokens.put("group_id", String.valueOf(groupId));
1404                    tokens.put("image_path", themeDisplay.getPathImage());
1405                    tokens.put("layout_set_friendly_url", layoutSetFriendlyUrl);
1406                    tokens.put("main_path", themeDisplay.getPathMain());
1407                    tokens.put("portal_ctx", themeDisplay.getPathContext());
1408                    tokens.put(
1409                            "portal_url", HttpUtil.removeProtocol(themeDisplay.getURLPortal()));
1410                    tokens.put(
1411                            "protocol", HttpUtil.getProtocol(themeDisplay.getURLPortal()));
1412                    tokens.put("root_path", themeDisplay.getPathContext());
1413                    tokens.put("theme_image_path", themeDisplay.getPathThemeImages());
1414    
1415                    _populateCustomTokens(tokens);
1416    
1417                    // Deprecated tokens
1418    
1419                    tokens.put("friendly_url", themeDisplay.getPathFriendlyURLPublic());
1420                    tokens.put(
1421                            "friendly_url_private",
1422                            themeDisplay.getPathFriendlyURLPrivateGroup());
1423                    tokens.put("page_url", themeDisplay.getPathFriendlyURLPublic());
1424            }
1425    
1426            private static void _removeOldContent(
1427                            Stack<String> path, Element contentElement, Document xsdDocument)
1428                    throws SystemException {
1429    
1430                    String elementPath = "";
1431    
1432                    for (int i = 0; i < path.size(); i++) {
1433                            elementPath += "/" + path.elementAt(i);
1434                    }
1435    
1436                    for (int i = 0; i < contentElement.nodeCount(); i++) {
1437                            Node contentNode = contentElement.node(i);
1438    
1439                            if (contentNode instanceof Element) {
1440                                    _removeOldContent(
1441                                            path, (Element)contentNode, xsdDocument, elementPath);
1442                            }
1443                    }
1444            }
1445    
1446            private static void _removeOldContent(
1447                            Stack<String> path, Element contentElement, Document xsdDocument,
1448                            String elementPath)
1449                    throws SystemException {
1450    
1451                    String name = contentElement.attributeValue("name");
1452    
1453                    if (Validator.isNull(name)) {
1454                            return;
1455                    }
1456    
1457                    String localPath = "dynamic-element[@name='" + name + "']";
1458    
1459                    String fullPath = elementPath + "/" + localPath;
1460    
1461                    XPath xPathSelector = SAXReaderUtil.createXPath(fullPath);
1462    
1463                    List<Node> curNodes = xPathSelector.selectNodes(xsdDocument);
1464    
1465                    if (curNodes.size() == 0) {
1466                            contentElement.detach();
1467                    }
1468    
1469                    path.push(localPath);
1470    
1471                    _removeOldContent(path, contentElement, xsdDocument);
1472    
1473                    path.pop();
1474            }
1475    
1476            private static final char[] _URL_TITLE_REPLACE_CHARS = new char[] {
1477                    '.', '/'
1478            };
1479    
1480            private static Log _log = LogFactoryUtil.getLog(JournalUtil.class);
1481    
1482            private static Map<String, String> _customTokens;
1483            private static Transformer _transformer = new JournalTransformer();
1484    
1485    }