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