001    /**
002     * Copyright (c) 2000-2013 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.portal.model.impl;
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.portlet.PortletLayoutListener;
023    import com.liferay.portal.kernel.util.ArrayUtil;
024    import com.liferay.portal.kernel.util.DateFormatFactoryUtil;
025    import com.liferay.portal.kernel.util.FastDateFormatFactoryUtil;
026    import com.liferay.portal.kernel.util.GetterUtil;
027    import com.liferay.portal.kernel.util.ListUtil;
028    import com.liferay.portal.kernel.util.PropsKeys;
029    import com.liferay.portal.kernel.util.StringPool;
030    import com.liferay.portal.kernel.util.StringUtil;
031    import com.liferay.portal.kernel.util.UnicodeProperties;
032    import com.liferay.portal.kernel.util.UniqueList;
033    import com.liferay.portal.kernel.util.Validator;
034    import com.liferay.portal.model.CustomizedPages;
035    import com.liferay.portal.model.Group;
036    import com.liferay.portal.model.Layout;
037    import com.liferay.portal.model.LayoutSet;
038    import com.liferay.portal.model.LayoutTemplate;
039    import com.liferay.portal.model.LayoutTypePortlet;
040    import com.liferay.portal.model.LayoutTypePortletConstants;
041    import com.liferay.portal.model.Plugin;
042    import com.liferay.portal.model.Portlet;
043    import com.liferay.portal.model.PortletConstants;
044    import com.liferay.portal.model.PortletPreferences;
045    import com.liferay.portal.model.PortletPreferencesIds;
046    import com.liferay.portal.model.Theme;
047    import com.liferay.portal.security.permission.ActionKeys;
048    import com.liferay.portal.security.permission.PermissionChecker;
049    import com.liferay.portal.security.permission.PermissionThreadLocal;
050    import com.liferay.portal.service.LayoutTemplateLocalServiceUtil;
051    import com.liferay.portal.service.PluginSettingLocalServiceUtil;
052    import com.liferay.portal.service.PortletLocalServiceUtil;
053    import com.liferay.portal.service.PortletPreferencesLocalServiceUtil;
054    import com.liferay.portal.service.permission.LayoutPermissionUtil;
055    import com.liferay.portal.service.permission.PortletPermissionUtil;
056    import com.liferay.portal.util.PortalUtil;
057    import com.liferay.portal.util.PortletKeys;
058    import com.liferay.portal.util.PropsUtil;
059    import com.liferay.portal.util.PropsValues;
060    import com.liferay.portlet.PortalPreferences;
061    import com.liferay.portlet.PortletPreferencesFactoryUtil;
062    import com.liferay.portlet.sites.util.SitesUtil;
063    import com.liferay.util.JS;
064    
065    import java.text.DateFormat;
066    import java.text.Format;
067    
068    import java.util.ArrayList;
069    import java.util.Date;
070    import java.util.List;
071    import java.util.Map;
072    
073    /**
074     * @author Brian Wing Shun Chan
075     * @author Berentey Zsolt
076     * @author Jorge Ferrer
077     * @author Raymond Aug??
078     */
079    public class LayoutTypePortletImpl
080            extends LayoutTypeImpl implements LayoutTypePortlet {
081    
082            public static String generateInstanceId() {
083                    return StringUtil.randomString(12);
084            }
085    
086            public LayoutTypePortletImpl(Layout layout) {
087                    super(layout);
088    
089                    if (_nestedPortletsNamespace == null) {
090                            _nestedPortletsNamespace = PortalUtil.getPortletNamespace(
091                                    PortletKeys.NESTED_PORTLETS);
092                    }
093    
094                    _layoutSetPrototypeLayout = SitesUtil.getLayoutSetPrototypeLayout(
095                            layout);
096            }
097    
098            @Override
099            public void addModeAboutPortletId(String portletId) {
100                    removeModesPortletId(portletId);
101                    setModeAbout(StringUtil.add(getModeAbout(), portletId));
102            }
103    
104            @Override
105            public void addModeConfigPortletId(String portletId) {
106                    removeModesPortletId(portletId);
107                    setModeConfig(StringUtil.add(getModeConfig(), portletId));
108            }
109    
110            @Override
111            public void addModeEditDefaultsPortletId(String portletId) {
112                    removeModesPortletId(portletId);
113                    setModeEditDefaults(StringUtil.add(getModeEditDefaults(), portletId));
114            }
115    
116            @Override
117            public void addModeEditGuestPortletId(String portletId) {
118                    removeModesPortletId(portletId);
119                    setModeEditGuest(StringUtil.add(getModeEditGuest(), portletId));
120            }
121    
122            @Override
123            public void addModeEditPortletId(String portletId) {
124                    removeModesPortletId(portletId);
125                    setModeEdit(StringUtil.add(getModeEdit(), portletId));
126            }
127    
128            @Override
129            public void addModeHelpPortletId(String portletId) {
130                    removeModesPortletId(portletId);
131                    setModeHelp(StringUtil.add(getModeHelp(), portletId));
132            }
133    
134            @Override
135            public void addModePreviewPortletId(String portletId) {
136                    removeModesPortletId(portletId);
137                    setModePreview(StringUtil.add(getModePreview(), portletId));
138            }
139    
140            @Override
141            public void addModePrintPortletId(String portletId) {
142                    removeModesPortletId(portletId);
143                    setModePrint(StringUtil.add(getModePrint(), portletId));
144            }
145    
146            @Override
147            public String addPortletId(long userId, String portletId)
148                    throws PortalException, SystemException {
149    
150                    return addPortletId(userId, portletId, true);
151            }
152    
153            @Override
154            public String addPortletId(
155                            long userId, String portletId, boolean checkPermission)
156                    throws PortalException, SystemException {
157    
158                    return addPortletId(userId, portletId, null, -1, checkPermission);
159            }
160    
161            @Override
162            public String addPortletId(
163                            long userId, String portletId, String columnId, int columnPos)
164                    throws PortalException, SystemException {
165    
166                    return addPortletId(userId, portletId, columnId, columnPos, true);
167            }
168    
169            @Override
170            public String addPortletId(
171                            long userId, String portletId, String columnId, int columnPos,
172                            boolean checkPermission)
173                    throws PortalException, SystemException {
174    
175                    return addPortletId(
176                            userId, portletId, columnId, columnPos, checkPermission, false);
177            }
178    
179            @Override
180            public void addPortletIds(
181                            long userId, String[] portletIds, boolean checkPermission)
182                    throws PortalException, SystemException {
183    
184                    for (String portletId : portletIds) {
185                            addPortletId(userId, portletId, checkPermission);
186                    }
187            }
188    
189            @Override
190            public void addPortletIds(
191                            long userId, String[] portletIds, String columnId,
192                            boolean checkPermission)
193                    throws PortalException, SystemException {
194    
195                    for (String portletId : portletIds) {
196                            addPortletId(userId, portletId, columnId, -1, checkPermission);
197                    }
198            }
199    
200            @Override
201            public void addStateMaxPortletId(String portletId) {
202                    removeStatesPortletId(portletId);
203                    //setStateMax(StringUtil.add(getStateMax(), portletId));
204                    setStateMax(StringUtil.add(StringPool.BLANK, portletId));
205            }
206    
207            @Override
208            public void addStateMinPortletId(String portletId) {
209                    removeStateMaxPortletId(portletId);
210                    setStateMin(StringUtil.add(getStateMin(), portletId));
211            }
212    
213            @Override
214            public List<Portlet> addStaticPortlets(
215                    List<Portlet> portlets, List<Portlet> startPortlets,
216                    List<Portlet> endPortlets) {
217    
218                    // Return the original array of portlets if no static portlets are
219                    // specified
220    
221                    if (startPortlets == null) {
222                            startPortlets = new ArrayList<Portlet>();
223                    }
224    
225                    if (endPortlets == null) {
226                            endPortlets = new ArrayList<Portlet>();
227                    }
228    
229                    if (startPortlets.isEmpty() && endPortlets.isEmpty()) {
230                            return portlets;
231                    }
232    
233                    // New array of portlets that contain the static portlets
234    
235                    List<Portlet> list = new ArrayList<Portlet>(
236                            portlets.size() + startPortlets.size() + endPortlets.size());
237    
238                    if (!startPortlets.isEmpty()) {
239                            list.addAll(startPortlets);
240                    }
241    
242                    for (int i = 0; i < portlets.size(); i++) {
243                            Portlet portlet = portlets.get(i);
244    
245                            // Add the portlet if and only if it is not also a static portlet
246    
247                            if (!startPortlets.contains(portlet) &&
248                                    !endPortlets.contains(portlet)) {
249    
250                                    list.add(portlet);
251                            }
252                    }
253    
254                    if (!endPortlets.isEmpty()) {
255                            list.addAll(endPortlets);
256                    }
257    
258                    return list;
259            }
260    
261            @Override
262            public List<Portlet> getAllPortlets()
263                    throws PortalException, SystemException {
264    
265                    List<Portlet> portlets = new ArrayList<Portlet>();
266    
267                    List<String> columns = getColumns();
268    
269                    for (int i = 0; i < columns.size(); i++) {
270                            String columnId = columns.get(i);
271    
272                            portlets.addAll(getAllPortlets(columnId));
273                    }
274    
275                    List<Portlet> staticPortlets = getStaticPortlets(
276                            PropsKeys.LAYOUT_STATIC_PORTLETS_ALL);
277    
278                    List<Portlet> embeddedPortlets = getEmbeddedPortlets(
279                            portlets, staticPortlets);
280    
281                    return addStaticPortlets(portlets, staticPortlets, embeddedPortlets);
282            }
283    
284            @Override
285            public List<Portlet> getAllPortlets(boolean includeSystem)
286                    throws PortalException, SystemException {
287    
288                    List<Portlet> filteredPortlets = new ArrayList<Portlet>();
289    
290                    List<Portlet> portlets = getAllPortlets();
291    
292                    for (Portlet portlet : portlets) {
293                            if (portlet.isSystem() && !includeSystem) {
294                                    continue;
295                            }
296    
297                            filteredPortlets.add(portlet);
298                    }
299    
300                    return filteredPortlets;
301            }
302    
303            @Override
304            public List<Portlet> getAllPortlets(String columnId)
305                    throws PortalException, SystemException {
306    
307                    String columnValue = getColumnValue(columnId);
308    
309                    String[] portletIds = StringUtil.split(columnValue);
310    
311                    List<Portlet> portlets = new ArrayList<Portlet>(portletIds.length);
312    
313                    for (String portletId : portletIds) {
314                            Portlet portlet = PortletLocalServiceUtil.getPortletById(
315                                    getCompanyId(), portletId);
316    
317                            if ((portlet != null) && !portlet.isUndeployedPortlet()) {
318                                    portlets.add(portlet);
319                            }
320                    }
321    
322                    List<Portlet> startPortlets = getStaticPortlets(
323                            PropsKeys.LAYOUT_STATIC_PORTLETS_START + columnId);
324    
325                    List<Portlet> endPortlets = getStaticPortlets(
326                            PropsKeys.LAYOUT_STATIC_PORTLETS_END + columnId);
327    
328                    return addStaticPortlets(portlets, startPortlets, endPortlets);
329            }
330    
331            @Override
332            public Layout getLayoutSetPrototypeLayout() {
333                    return _layoutSetPrototypeLayout;
334            }
335    
336            @Override
337            public String getLayoutSetPrototypeLayoutProperty(String key) {
338                    if (_layoutSetPrototypeLayout == null) {
339                            return StringPool.BLANK;
340                    }
341    
342                    UnicodeProperties typeSettingsProperties =
343                            _layoutSetPrototypeLayout.getTypeSettingsProperties();
344    
345                    return typeSettingsProperties.getProperty(key);
346            }
347    
348            @Override
349            public LayoutTemplate getLayoutTemplate() {
350                    String themeId = getThemeId();
351    
352                    LayoutTemplate layoutTemplate =
353                            LayoutTemplateLocalServiceUtil.getLayoutTemplate(
354                                    getLayoutTemplateId(), false, themeId);
355    
356                    if (layoutTemplate == null) {
357                            layoutTemplate = new LayoutTemplateImpl(
358                                    StringPool.BLANK, StringPool.BLANK);
359    
360                            List<String> columns = new ArrayList<String>();
361    
362                            for (int i = 1; i <= 10; i++) {
363                                    columns.add(LayoutTypePortletConstants.COLUMN_PREFIX + i);
364                            }
365    
366                            layoutTemplate.setColumns(columns);
367                    }
368    
369                    return layoutTemplate;
370            }
371    
372            @Override
373            public String getLayoutTemplateId() {
374                    return GetterUtil.getString(
375                            getTypeSettingsProperty(
376                                    LayoutTypePortletConstants.LAYOUT_TEMPLATE_ID));
377            }
378    
379            @Override
380            public String getModeAbout() {
381                    return getTypeSettingsProperty(LayoutTypePortletConstants.MODE_ABOUT);
382            }
383    
384            @Override
385            public String getModeConfig() {
386                    return getTypeSettingsProperty(LayoutTypePortletConstants.MODE_CONFIG);
387            }
388    
389            @Override
390            public String getModeEdit() {
391                    return getTypeSettingsProperty(LayoutTypePortletConstants.MODE_EDIT);
392            }
393    
394            @Override
395            public String getModeEditDefaults() {
396                    return getTypeSettingsProperty(
397                            LayoutTypePortletConstants.MODE_EDIT_DEFAULTS);
398            }
399    
400            @Override
401            public String getModeEditGuest() {
402                    return getTypeSettingsProperty(
403                            LayoutTypePortletConstants.MODE_EDIT_GUEST);
404            }
405    
406            @Override
407            public String getModeHelp() {
408                    return getTypeSettingsProperty(LayoutTypePortletConstants.MODE_HELP);
409            }
410    
411            @Override
412            public String getModePreview() {
413                    return getTypeSettingsProperty(LayoutTypePortletConstants.MODE_PREVIEW);
414            }
415    
416            @Override
417            public String getModePrint() {
418                    return getTypeSettingsProperty(LayoutTypePortletConstants.MODE_PRINT);
419            }
420    
421            @Override
422            public int getNumOfColumns() {
423                    return getLayoutTemplate().getColumns().size();
424            }
425    
426            @Override
427            public PortalPreferences getPortalPreferences() {
428                    return _portalPreferences;
429            }
430    
431            @Override
432            public List<String> getPortletIds() {
433                    List<String> portletIds = new ArrayList<String>();
434    
435                    List<String> columns = getColumns();
436    
437                    for (int i = 0; i < columns.size(); i++) {
438                            String columnId = columns.get(i);
439    
440                            String columnValue = getColumnValue(columnId);
441    
442                            portletIds.addAll(
443                                    ListUtil.fromArray(StringUtil.split(columnValue)));
444                    }
445    
446                    return portletIds;
447            }
448    
449            @Override
450            public List<Portlet> getPortlets() throws SystemException {
451                    List<String> portletIds = getPortletIds();
452    
453                    List<Portlet> portlets = new ArrayList<Portlet>(portletIds.size());
454    
455                    for (int i = 0; i < portletIds.size(); i++) {
456                            String portletId = portletIds.get(i);
457    
458                            Portlet portlet = PortletLocalServiceUtil.getPortletById(
459                                    getCompanyId(), portletId);
460    
461                            if (portlet != null) {
462                                    portlets.add(portlet);
463                            }
464                    }
465    
466                    return portlets;
467            }
468    
469            @Override
470            public String getStateMax() {
471                    return getTypeSettingsProperty(LayoutTypePortletConstants.STATE_MAX);
472            }
473    
474            @Override
475            public String getStateMaxPortletId() {
476                    String[] stateMax = StringUtil.split(getStateMax());
477    
478                    if (stateMax.length > 0) {
479                            return stateMax[0];
480                    }
481                    else {
482                            return StringPool.BLANK;
483                    }
484            }
485    
486            @Override
487            public String getStateMin() {
488                    return getTypeSettingsProperty(LayoutTypePortletConstants.STATE_MIN);
489            }
490    
491            @Override
492            public boolean hasDefaultScopePortletId(long groupId, String portletId)
493                    throws PortalException, SystemException {
494    
495                    if (hasPortletId(portletId)) {
496                            long scopeGroupId = PortalUtil.getScopeGroupId(
497                                    getLayout(), portletId);
498    
499                            if (groupId == scopeGroupId) {
500                                    return true;
501                            }
502                    }
503    
504                    return false;
505            }
506    
507            @Override
508            public boolean hasModeAboutPortletId(String portletId) {
509                    return StringUtil.contains(getModeAbout(), portletId);
510            }
511    
512            @Override
513            public boolean hasModeConfigPortletId(String portletId) {
514                    return StringUtil.contains(getModeConfig(), portletId);
515            }
516    
517            @Override
518            public boolean hasModeEditDefaultsPortletId(String portletId) {
519                    return StringUtil.contains(getModeEditDefaults(), portletId);
520            }
521    
522            @Override
523            public boolean hasModeEditGuestPortletId(String portletId) {
524                    return StringUtil.contains(getModeEditGuest(), portletId);
525            }
526    
527            @Override
528            public boolean hasModeEditPortletId(String portletId) {
529                    return StringUtil.contains(getModeEdit(), portletId);
530            }
531    
532            @Override
533            public boolean hasModeHelpPortletId(String portletId) {
534                    return StringUtil.contains(getModeHelp(), portletId);
535            }
536    
537            @Override
538            public boolean hasModePreviewPortletId(String portletId) {
539                    return StringUtil.contains(getModePreview(), portletId);
540            }
541    
542            @Override
543            public boolean hasModePrintPortletId(String portletId) {
544                    return StringUtil.contains(getModePrint(), portletId);
545            }
546    
547            @Override
548            public boolean hasModeViewPortletId(String portletId) {
549                    if (hasModeAboutPortletId(portletId) ||
550                            hasModeConfigPortletId(portletId) ||
551                            hasModeEditPortletId(portletId) ||
552                            hasModeEditDefaultsPortletId(portletId) ||
553                            hasModeEditGuestPortletId(portletId) ||
554                            hasModeHelpPortletId(portletId) ||
555                            hasModePreviewPortletId(portletId) ||
556                            hasModePrintPortletId(portletId)) {
557    
558                            return false;
559                    }
560                    else {
561                            return true;
562                    }
563            }
564    
565            @Override
566            public boolean hasPortletId(String portletId)
567                    throws PortalException, SystemException {
568    
569                    return hasPortletId(portletId, false);
570            }
571    
572            @Override
573            public boolean hasPortletId(String portletId, boolean strict)
574                    throws PortalException, SystemException {
575    
576                    List<String> columns = getColumns();
577    
578                    for (String columnId : columns) {
579                            if (hasNonstaticPortletId(columnId, portletId)) {
580                                    return true;
581                            }
582    
583                            if (hasStaticPortletId(columnId, portletId)) {
584                                    return true;
585                            }
586                    }
587    
588                    Layout layout = getLayout();
589    
590                    if (layout.isTypeControlPanel()) {
591                            return false;
592                    }
593    
594                    if (isCustomizable() && isCustomizedView()) {
595                            LayoutTypePortletImpl defaultLayoutTypePortletImpl =
596                                    getDefaultLayoutTypePortletImpl();
597    
598                            if (defaultLayoutTypePortletImpl.hasNonstaticPortletId(portletId)) {
599                                    return false;
600                            }
601                    }
602    
603                    if (!strict &&
604                            ((PortletPreferencesLocalServiceUtil.getPortletPreferencesCount(
605                                    PortletKeys.PREFS_OWNER_TYPE_LAYOUT, layout.getPlid(),
606                                    portletId) > 0) ||
607                             (PortletPreferencesLocalServiceUtil.getPortletPreferencesCount(
608                                    PortletKeys.PREFS_OWNER_TYPE_USER, layout.getPlid(),
609                                    portletId) > 0))) {
610    
611                            return true;
612                    }
613    
614                    return false;
615            }
616    
617            @Override
618            public boolean hasStateMax() {
619                    String[] stateMax = StringUtil.split(getStateMax());
620    
621                    if (stateMax.length > 0) {
622                            return true;
623                    }
624                    else {
625                            return false;
626                    }
627            }
628    
629            @Override
630            public boolean hasStateMaxPortletId(String portletId) {
631                    if (StringUtil.contains(getStateMax(), portletId)) {
632                            return true;
633                    }
634                    else {
635                            return false;
636                    }
637            }
638    
639            @Override
640            public boolean hasStateMin() {
641                    String[] stateMin = StringUtil.split(getStateMin());
642    
643                    if (stateMin.length > 0) {
644                            return true;
645                    }
646                    else {
647                            return false;
648                    }
649            }
650    
651            @Override
652            public boolean hasStateMinPortletId(String portletId) {
653                    if (StringUtil.contains(getStateMin(), portletId)) {
654                            return true;
655                    }
656                    else {
657                            return false;
658                    }
659            }
660    
661            @Override
662            public boolean hasStateNormalPortletId(String portletId) {
663                    if (hasStateMaxPortletId(portletId) ||
664                            hasStateMinPortletId(portletId)) {
665    
666                            return false;
667                    }
668                    else {
669                            return true;
670                    }
671            }
672    
673            @Override
674            public boolean hasUpdatePermission() {
675                    return _updatePermission;
676            }
677    
678            @Override
679            public boolean isCacheable() throws PortalException, SystemException {
680                    for (String columnId : getColumns()) {
681                            for (Portlet portlet : getAllPortlets(columnId)) {
682                                    Portlet rootPortlet = portlet.getRootPortlet();
683    
684                                    if (!rootPortlet.isLayoutCacheable()) {
685                                            return false;
686                                    }
687                            }
688                    }
689    
690                    return true;
691            }
692    
693            @Override
694            public boolean isColumnCustomizable(String columnId) {
695                    if (!isLayoutSetPrototype()) {
696                            String customizableString = getTypeSettingsProperty(
697                                    CustomizedPages.namespaceColumnId(columnId));
698    
699                            boolean customizable = GetterUtil.getBoolean(customizableString);
700    
701                            if (!customizable && hasUserPreferences()) {
702                                    String columnValue = _portalPreferences.getValue(
703                                            CustomizedPages.namespacePlid(getPlid()), columnId,
704                                            StringPool.NULL);
705    
706                                    if (!Validator.equals(columnValue, StringPool.NULL)) {
707                                            setUserPreference(columnId, null);
708                                    }
709                            }
710    
711                            return customizable;
712                    }
713    
714                    return false;
715            }
716    
717            @Override
718            public boolean isColumnDisabled(String columnId) {
719                    if ((isCustomizedView() && !isColumnCustomizable(columnId)) ||
720                            (!isCustomizedView() && !hasUpdatePermission())) {
721    
722                            return true;
723                    }
724    
725                    return false;
726            }
727    
728            @Override
729            public boolean isCustomizable() {
730                    for (String columnId : getColumns()) {
731                            if (isColumnCustomizable(columnId)) {
732                                    return true;
733                            }
734                    }
735    
736                    return false;
737            }
738    
739            @Override
740            public boolean isCustomizedView() {
741                    return _customizedView;
742            }
743    
744            @Override
745            public boolean isDefaultUpdated() {
746                    if (!isCustomizedView() || !hasUserPreferences()) {
747                            return false;
748                    }
749    
750                    String preferencesModifiedDateString = _portalPreferences.getValue(
751                            CustomizedPages.namespacePlid(getPlid()), _MODIFIED_DATE,
752                            _NULL_DATE);
753    
754                    DateFormat dateFormat = DateFormatFactoryUtil.getSimpleDateFormat(
755                            PropsValues.INDEX_DATE_FORMAT_PATTERN);
756    
757                    try {
758                            Date preferencesModifiedDate = dateFormat.parse(
759                                    preferencesModifiedDateString);
760    
761                            Layout layout = getLayout();
762    
763                            String propertiesModifiedDateString =
764                                    layout.getTypeSettingsProperty(_MODIFIED_DATE, _NULL_DATE);
765    
766                            Date propertiesModifiedDate = dateFormat.parse(
767                                    propertiesModifiedDateString);
768    
769                            return propertiesModifiedDate.after(preferencesModifiedDate);
770                    }
771                    catch (Exception e) {
772                            _log.error(e, e);
773                    }
774    
775                    return false;
776            }
777    
778            @Override
779            public boolean isPortletCustomizable(String portletId) {
780                    return isColumnCustomizable(getColumn(portletId));
781            }
782    
783            @Override
784            public void movePortletId(
785                            long userId, String portletId, String columnId, int columnPos)
786                    throws PortalException, SystemException {
787    
788                    if (!hasPortletId(portletId)) {
789                            return;
790                    }
791    
792                    _enablePortletLayoutListener = false;
793    
794                    try {
795                            removePortletId(userId, portletId, false);
796                            addPortletId(userId, portletId, columnId, columnPos, false, true);
797                    }
798                    finally {
799                            _enablePortletLayoutListener = true;
800                    }
801    
802                    Layout layout = getLayout();
803    
804                    try {
805                            Portlet portlet = PortletLocalServiceUtil.getPortletById(
806                                    layout.getCompanyId(), portletId);
807    
808                            if (portlet != null) {
809                                    PortletLayoutListener portletLayoutListener =
810                                            portlet.getPortletLayoutListenerInstance();
811    
812                                    if (portletLayoutListener != null) {
813                                            portletLayoutListener.onMoveInLayout(
814                                                    portletId, layout.getPlid());
815                                    }
816                            }
817                    }
818                    catch (Exception e) {
819                            _log.error("Unable to fire portlet layout listener event", e);
820                    }
821            }
822    
823            @Override
824            public void removeModeAboutPortletId(String portletId) {
825                    setModeAbout(StringUtil.remove(getModeAbout(), portletId));
826            }
827    
828            @Override
829            public void removeModeConfigPortletId(String portletId) {
830                    setModeConfig(StringUtil.remove(getModeConfig(), portletId));
831            }
832    
833            @Override
834            public void removeModeEditDefaultsPortletId(String portletId) {
835                    setModeEditDefaults(
836                            StringUtil.remove(getModeEditDefaults(), portletId));
837            }
838    
839            @Override
840            public void removeModeEditGuestPortletId(String portletId) {
841                    setModeEditGuest(StringUtil.remove(getModeEditGuest(), portletId));
842            }
843    
844            @Override
845            public void removeModeEditPortletId(String portletId) {
846                    setModeEdit(StringUtil.remove(getModeEdit(), portletId));
847            }
848    
849            @Override
850            public void removeModeHelpPortletId(String portletId) {
851                    setModeHelp(StringUtil.remove(getModeHelp(), portletId));
852            }
853    
854            @Override
855            public void removeModePreviewPortletId(String portletId) {
856                    setModePreview(StringUtil.remove(getModePreview(), portletId));
857            }
858    
859            @Override
860            public void removeModePrintPortletId(String portletId) {
861                    setModePrint(StringUtil.remove(getModePrint(), portletId));
862            }
863    
864            @Override
865            public void removeModesPortletId(String portletId) {
866                    removeModeAboutPortletId(portletId);
867                    removeModeConfigPortletId(portletId);
868                    removeModeEditPortletId(portletId);
869                    removeModeEditDefaultsPortletId(portletId);
870                    removeModeEditGuestPortletId(portletId);
871                    removeModeHelpPortletId(portletId);
872                    removeModePreviewPortletId(portletId);
873                    removeModePrintPortletId(portletId);
874            }
875    
876            @Override
877            public void removeNestedColumns(String portletNamespace) {
878                    UnicodeProperties typeSettingsProperties = getTypeSettingsProperties();
879    
880                    UnicodeProperties newTypeSettingsProperties = new UnicodeProperties();
881    
882                    for (Map.Entry<String, String> entry :
883                                    typeSettingsProperties.entrySet()) {
884    
885                            String key = entry.getKey();
886    
887                            if (!key.startsWith(portletNamespace)) {
888                                    newTypeSettingsProperties.setProperty(key, entry.getValue());
889                            }
890                    }
891    
892                    Layout layout = getLayout();
893    
894                    layout.setTypeSettingsProperties(newTypeSettingsProperties);
895    
896                    String nestedColumnIds = GetterUtil.getString(
897                            getTypeSettingsProperty(
898                                    LayoutTypePortletConstants.NESTED_COLUMN_IDS));
899    
900                    String[] nestedColumnIdsArray = ArrayUtil.removeByPrefix(
901                            StringUtil.split(nestedColumnIds), portletNamespace);
902    
903                    setTypeSettingsProperty(
904                            LayoutTypePortletConstants.NESTED_COLUMN_IDS,
905                            StringUtil.merge(nestedColumnIdsArray));
906            }
907    
908            @Override
909            public void removePortletId(long userId, String portletId) {
910                    removePortletId(userId, portletId, true);
911            }
912    
913            @Override
914            public void removePortletId(
915                    long userId, String portletId, boolean cleanUp) {
916    
917                    try {
918                            Portlet portlet = PortletLocalServiceUtil.getPortletById(
919                                    getCompanyId(), portletId);
920    
921                            if (portlet == null) {
922                                    _log.error(
923                                            "Portlet " + portletId +
924                                                    " cannot be removed because it is not registered");
925    
926                                    return;
927                            }
928    
929                            PermissionChecker permissionChecker =
930                                    PermissionThreadLocal.getPermissionChecker();
931    
932                            if (!LayoutPermissionUtil.contains(
933                                            permissionChecker, getLayout(), ActionKeys.UPDATE) &&
934                                    !isCustomizable()) {
935    
936                                    return;
937                            }
938                    }
939                    catch (Exception e) {
940                            _log.error(e, e);
941    
942                            return;
943                    }
944    
945                    List<String> columns = getColumns();
946    
947                    for (int i = 0; i < columns.size(); i++) {
948                            String columnId = columns.get(i);
949    
950                            if (isCustomizable() && isColumnDisabled(columnId)) {
951                                    continue;
952                            }
953    
954                            String columnValue = StringPool.BLANK;
955    
956                            if (hasUserPreferences()) {
957                                    columnValue = getUserPreference(columnId);
958                            }
959                            else {
960                                    columnValue = getTypeSettingsProperty(columnId);
961                            }
962    
963                            columnValue = StringUtil.remove(columnValue, portletId);
964    
965                            if (hasUserPreferences()) {
966                                    setUserPreference(columnId, columnValue);
967                            }
968                            else {
969                                    setTypeSettingsProperty(columnId, columnValue);
970                            }
971                    }
972    
973                    if (cleanUp) {
974                            try {
975                                    onRemoveFromLayout(new String[] {portletId});
976                            }
977                            catch (Exception e) {
978                                    _log.error(e, e);
979                            }
980                    }
981            }
982    
983            @Override
984            public void removeStateMaxPortletId(String portletId) {
985                    setStateMax(StringUtil.remove(getStateMax(), portletId));
986            }
987    
988            @Override
989            public void removeStateMinPortletId(String portletId) {
990                    setStateMin(StringUtil.remove(getStateMin(), portletId));
991            }
992    
993            @Override
994            public void removeStatesPortletId(String portletId) {
995                    removeStateMaxPortletId(portletId);
996                    removeStateMinPortletId(portletId);
997            }
998    
999            @Override
1000            public void reorganizePortlets(
1001                    List<String> newColumns, List<String> oldColumns) {
1002    
1003                    String lastNewColumnId = newColumns.get(newColumns.size() - 1);
1004                    String lastNewColumnValue = getTypeSettingsProperty(lastNewColumnId);
1005    
1006                    for (String oldColumnId : oldColumns) {
1007                            if (!newColumns.contains(oldColumnId)) {
1008                                    String oldColumnValue = getTypeSettingsProperties().remove(
1009                                            oldColumnId);
1010    
1011                                    String[] portletIds = StringUtil.split(oldColumnValue);
1012    
1013                                    for (String portletId : portletIds) {
1014                                            lastNewColumnValue = StringUtil.add(
1015                                                    lastNewColumnValue, portletId);
1016                                    }
1017                            }
1018                    }
1019    
1020                    setTypeSettingsProperty(lastNewColumnId, lastNewColumnValue);
1021            }
1022    
1023            @Override
1024            public void resetModes() {
1025                    setModeAbout(StringPool.BLANK);
1026                    setModeConfig(StringPool.BLANK);
1027                    setModeEdit(StringPool.BLANK);
1028                    setModeEditDefaults(StringPool.BLANK);
1029                    setModeEditGuest(StringPool.BLANK);
1030                    setModeHelp(StringPool.BLANK);
1031                    setModePreview(StringPool.BLANK);
1032                    setModePrint(StringPool.BLANK);
1033            }
1034    
1035            @Override
1036            public void resetStates() {
1037                    setStateMax(StringPool.BLANK);
1038                    setStateMin(StringPool.BLANK);
1039            }
1040    
1041            @Override
1042            public void resetUserPreferences() {
1043                    if (!hasUserPreferences()) {
1044                            return;
1045                    }
1046    
1047                    long plid = getPlid();
1048    
1049                    List<String> customPortletIds = new UniqueList<String>();
1050    
1051                    for (String columnId : getColumns()) {
1052                            String value = _portalPreferences.getValue(
1053                                    CustomizedPages.namespacePlid(plid), columnId);
1054    
1055                            for (String customPortletId : StringUtil.split(value)) {
1056                                    customPortletIds.add(customPortletId);
1057                            }
1058                    }
1059    
1060                    try {
1061                            onRemoveFromLayout(
1062                                    customPortletIds.toArray(new String[customPortletIds.size()]));
1063                    }
1064                    catch (Exception e) {
1065                            _log.error(e, e);
1066                    }
1067    
1068                    _portalPreferences.resetValues(CustomizedPages.namespacePlid(plid));
1069    
1070                    _portalPreferences.setValue(
1071                            CustomizedPages.namespacePlid(plid), _MODIFIED_DATE,
1072                            _dateFormat.format(new Date()));
1073            }
1074    
1075            @Override
1076            public void setCustomizedView(boolean customizedView) {
1077                    _customizedView = customizedView;
1078            }
1079    
1080            @Override
1081            public void setLayoutTemplateId(long userId, String newLayoutTemplateId) {
1082                    setLayoutTemplateId(userId, newLayoutTemplateId, true);
1083            }
1084    
1085            @Override
1086            public void setLayoutTemplateId(
1087                    long userId, String newLayoutTemplateId, boolean checkPermission) {
1088    
1089                    if (checkPermission &&
1090                            !PluginSettingLocalServiceUtil.hasPermission(
1091                                    userId, newLayoutTemplateId, Plugin.TYPE_LAYOUT_TEMPLATE)) {
1092    
1093                            return;
1094                    }
1095    
1096                    LayoutTemplate oldLayoutTemplate = getLayoutTemplate();
1097    
1098                    String themeId = getThemeId();
1099    
1100                    LayoutTemplate newLayoutTemplate =
1101                            LayoutTemplateLocalServiceUtil.getLayoutTemplate(
1102                                    newLayoutTemplateId, false, themeId);
1103    
1104                    if (newLayoutTemplate == null) {
1105                            if (_log.isWarnEnabled()) {
1106                                    _log.warn(
1107                                            "Unable to find layout template " + newLayoutTemplateId);
1108                            }
1109    
1110                            return;
1111                    }
1112    
1113                    setTypeSettingsProperty(
1114                            LayoutTypePortletConstants.LAYOUT_TEMPLATE_ID, newLayoutTemplateId);
1115    
1116                    List<String> oldColumns = oldLayoutTemplate.getColumns();
1117                    List<String> newColumns = newLayoutTemplate.getColumns();
1118    
1119                    reorganizePortlets(newColumns, oldColumns);
1120            }
1121    
1122            @Override
1123            public void setModeAbout(String modeAbout) {
1124                    setTypeSettingsProperty(
1125                            LayoutTypePortletConstants.MODE_ABOUT, modeAbout);
1126            }
1127    
1128            @Override
1129            public void setModeConfig(String modeConfig) {
1130                    setTypeSettingsProperty(
1131                            LayoutTypePortletConstants.MODE_CONFIG, modeConfig);
1132            }
1133    
1134            @Override
1135            public void setModeEdit(String modeEdit) {
1136                    setTypeSettingsProperty(LayoutTypePortletConstants.MODE_EDIT, modeEdit);
1137            }
1138    
1139            @Override
1140            public void setModeEditDefaults(String modeEditDefaults) {
1141                    setTypeSettingsProperty(
1142                            LayoutTypePortletConstants.MODE_EDIT_DEFAULTS, modeEditDefaults);
1143            }
1144    
1145            @Override
1146            public void setModeEditGuest(String modeEditGuest) {
1147                    setTypeSettingsProperty(
1148                            LayoutTypePortletConstants.MODE_EDIT_GUEST, modeEditGuest);
1149            }
1150    
1151            @Override
1152            public void setModeHelp(String modeHelp) {
1153                    setTypeSettingsProperty(LayoutTypePortletConstants.MODE_HELP, modeHelp);
1154            }
1155    
1156            @Override
1157            public void setModePreview(String modePreview) {
1158                    setTypeSettingsProperty(
1159                            LayoutTypePortletConstants.MODE_PREVIEW, modePreview);
1160            }
1161    
1162            @Override
1163            public void setModePrint(String modePrint) {
1164                    setTypeSettingsProperty(
1165                            LayoutTypePortletConstants.MODE_PRINT, modePrint);
1166            }
1167    
1168            @Override
1169            public void setPortalPreferences(PortalPreferences portalPreferences) {
1170                    _portalPreferences = portalPreferences;
1171            }
1172    
1173            @Override
1174            public void setStateMax(String stateMax) {
1175                    setTypeSettingsProperty(LayoutTypePortletConstants.STATE_MAX, stateMax);
1176            }
1177    
1178            @Override
1179            public void setStateMin(String stateMin) {
1180                    setTypeSettingsProperty(LayoutTypePortletConstants.STATE_MIN, stateMin);
1181            }
1182    
1183            @Override
1184            public void setUpdatePermission(boolean updatePermission) {
1185                    _updatePermission = updatePermission;
1186            }
1187    
1188            protected void addNestedColumn(String columnId) {
1189                    String nestedColumnIds = getTypeSettingsProperty(
1190                            LayoutTypePortletConstants.NESTED_COLUMN_IDS, StringPool.BLANK);
1191    
1192                    if (!nestedColumnIds.contains(columnId)) {
1193                            nestedColumnIds = StringUtil.add(nestedColumnIds, columnId);
1194    
1195                            setTypeSettingsProperty(
1196                                    LayoutTypePortletConstants.NESTED_COLUMN_IDS, nestedColumnIds);
1197                    }
1198            }
1199    
1200            protected String addPortletId(
1201                            long userId, String portletId, String columnId, int columnPos,
1202                            boolean checkPermission, boolean strictHasPortlet)
1203                    throws PortalException, SystemException {
1204    
1205                    portletId = JS.getSafeName(portletId);
1206    
1207                    Layout layout = getLayout();
1208    
1209                    Portlet portlet = null;
1210    
1211                    try {
1212                            portlet = PortletLocalServiceUtil.getPortletById(
1213                                    layout.getCompanyId(), portletId);
1214    
1215                            if (portlet == null) {
1216                                    if (_log.isWarnEnabled()) {
1217                                            _log.warn(
1218                                                    "Portlet " + portletId +
1219                                                            " cannot be added because it is not registered");
1220                                    }
1221    
1222                                    return null;
1223                            }
1224    
1225                            PermissionChecker permissionChecker =
1226                                    PermissionThreadLocal.getPermissionChecker();
1227    
1228                            if (checkPermission &&
1229                                    !PortletPermissionUtil.contains(
1230                                            permissionChecker, layout, portlet,
1231                                            ActionKeys.ADD_TO_PAGE)) {
1232    
1233                                    return null;
1234                            }
1235                    }
1236                    catch (Exception e) {
1237                            _log.error(e, e);
1238                    }
1239    
1240                    if (portlet.isSystem()) {
1241                            return null;
1242                    }
1243    
1244                    if (portlet.isInstanceable() &&
1245                            !PortletConstants.hasInstanceId(portletId)) {
1246    
1247                            portletId = PortletConstants.assemblePortletId(
1248                                    portletId, generateInstanceId());
1249                    }
1250    
1251                    if (hasPortletId(portletId, strictHasPortlet)) {
1252                            return null;
1253                    }
1254    
1255                    if (columnId == null) {
1256                            LayoutTemplate layoutTemplate = getLayoutTemplate();
1257    
1258                            List<String> columns = layoutTemplate.getColumns();
1259    
1260                            if (columns.size() > 0) {
1261                                    columnId = columns.get(0);
1262                            }
1263                    }
1264    
1265                    if (columnId == null) {
1266                            return null;
1267                    }
1268    
1269                    if (isCustomizable()) {
1270                            if (isColumnDisabled(columnId)) {
1271                                    return null;
1272                            }
1273    
1274                            if (PortletConstants.hasInstanceId(portletId) &&
1275                                    hasUserPreferences()) {
1276    
1277                                    portletId = PortletConstants.assemblePortletId(
1278                                            portletId, userId);
1279                            }
1280                    }
1281    
1282                    String columnValue = StringPool.BLANK;
1283    
1284                    if (hasUserPreferences()) {
1285                            columnValue = getUserPreference(columnId);
1286                    }
1287                    else {
1288                            columnValue = getTypeSettingsProperty(columnId);
1289                    }
1290    
1291                    if ((columnValue == null) &&
1292                            columnId.startsWith(_nestedPortletsNamespace)) {
1293    
1294                            addNestedColumn(columnId);
1295                    }
1296    
1297                    if (columnPos >= 0) {
1298                            List<String> portletIds = ListUtil.fromArray(
1299                                    StringUtil.split(columnValue));
1300    
1301                            if (columnPos <= portletIds.size()) {
1302                                    portletIds.add(columnPos, portletId);
1303                            }
1304                            else {
1305                                    portletIds.add(portletId);
1306                            }
1307    
1308                            columnValue = StringUtil.merge(portletIds);
1309                    }
1310                    else {
1311                            columnValue = StringUtil.add(columnValue, portletId);
1312                    }
1313    
1314                    if (hasUserPreferences()) {
1315                            setUserPreference(columnId, columnValue);
1316                    }
1317                    else {
1318                            setTypeSettingsProperty(columnId, columnValue);
1319                    }
1320    
1321                    try {
1322                            if (_enablePortletLayoutListener) {
1323                                    PortletLayoutListener portletLayoutListener =
1324                                            portlet.getPortletLayoutListenerInstance();
1325    
1326                                    if (portletLayoutListener != null) {
1327                                            portletLayoutListener.onAddToLayout(
1328                                                    portletId, layout.getPlid());
1329                                    }
1330                            }
1331                    }
1332                    catch (Exception e) {
1333                            _log.error("Unable to fire portlet layout listener event", e);
1334                    }
1335    
1336                    return portletId;
1337            }
1338    
1339            protected void copyPreferences(
1340                    long userId, String sourcePortletId, String targetPortletId) {
1341    
1342                    Layout layout = getLayout();
1343    
1344                    try {
1345                            PortletPreferencesIds portletPreferencesIds =
1346                                    PortletPreferencesFactoryUtil.getPortletPreferencesIds(
1347                                            layout.getGroupId(), 0, layout, sourcePortletId, false);
1348    
1349                            javax.portlet.PortletPreferences sourcePortletPreferences =
1350                                    PortletPreferencesLocalServiceUtil.getStrictPreferences(
1351                                            portletPreferencesIds);
1352    
1353                            portletPreferencesIds =
1354                                    PortletPreferencesFactoryUtil.getPortletPreferencesIds(
1355                                            layout.getGroupId(), userId, layout, targetPortletId,
1356                                            false);
1357    
1358                            PortletPreferencesLocalServiceUtil.updatePreferences(
1359                                    portletPreferencesIds.getOwnerId(),
1360                                    portletPreferencesIds.getOwnerType(),
1361                                    portletPreferencesIds.getPlid(),
1362                                    portletPreferencesIds.getPortletId(), sourcePortletPreferences);
1363                    }
1364                    catch (Exception e) {
1365                    }
1366            }
1367    
1368            protected String getColumn(String portletId) {
1369                    List<String> columns = getColumns();
1370    
1371                    for (String columnId : columns) {
1372                            String columnValue = getColumnValue(columnId);
1373    
1374                            String[] portletIds = StringUtil.split(columnValue);
1375    
1376                            for (String columnPortletId : portletIds) {
1377                                    if (PortletConstants.hasIdenticalRootPortletId(
1378                                                    columnPortletId, portletId)) {
1379    
1380                                            return columnId;
1381                                    }
1382                            }
1383                    }
1384    
1385                    return StringPool.BLANK;
1386            }
1387    
1388            protected List<String> getColumns() {
1389                    List<String> columns = new ArrayList<String>();
1390    
1391                    Layout layout = getLayout();
1392    
1393                    if (layout.isTypePortlet()) {
1394                            LayoutTemplate layoutTemplate = getLayoutTemplate();
1395    
1396                            columns.addAll(layoutTemplate.getColumns());
1397    
1398                            columns.addAll(getNestedColumns());
1399                    }
1400                    else if (layout.isTypePanel()) {
1401                            columns.add("panelSelectedPortlets");
1402                    }
1403    
1404                    return columns;
1405            }
1406    
1407            protected String getColumnValue(String columnId) {
1408                    if (hasUserPreferences() && isCustomizable() &&
1409                            !isColumnDisabled(columnId)) {
1410    
1411                            return getUserPreference(columnId);
1412                    }
1413    
1414                    return getTypeSettingsProperty(columnId);
1415            }
1416    
1417            protected long getCompanyId() {
1418                    Layout layout = getLayout();
1419    
1420                    return layout.getCompanyId();
1421            }
1422    
1423            protected LayoutTypePortletImpl getDefaultLayoutTypePortletImpl() {
1424                    if (!isCustomizedView()) {
1425                            return this;
1426                    }
1427    
1428                    LayoutTypePortletImpl defaultLayoutTypePortletImpl =
1429                            new LayoutTypePortletImpl(getLayout());
1430    
1431                    defaultLayoutTypePortletImpl._embeddedPortlets = _embeddedPortlets;
1432                    defaultLayoutTypePortletImpl._layoutSetPrototypeLayout =
1433                            _layoutSetPrototypeLayout;
1434                    defaultLayoutTypePortletImpl._updatePermission = _updatePermission;
1435    
1436                    return defaultLayoutTypePortletImpl;
1437            }
1438    
1439            protected List<Portlet> getEmbeddedPortlets(
1440                            List<Portlet> columnPortlets, List<Portlet> staticPortlets)
1441                    throws SystemException {
1442    
1443                    if (_embeddedPortlets != null) {
1444                            return _embeddedPortlets;
1445                    }
1446    
1447                    List<Portlet> portlets = new ArrayList<Portlet>();
1448    
1449                    Layout layout = getLayout();
1450    
1451                    List<PortletPreferences> portletPreferences =
1452                            PortletPreferencesLocalServiceUtil.getPortletPreferences(
1453                                    PortletKeys.PREFS_OWNER_ID_DEFAULT,
1454                                    PortletKeys.PREFS_OWNER_TYPE_LAYOUT, layout.getPlid());
1455    
1456                    if (isCustomizable() && hasUserPreferences()) {
1457                            portletPreferences = ListUtil.copy(portletPreferences);
1458    
1459                            portletPreferences.addAll(
1460                                    PortletPreferencesLocalServiceUtil.getPortletPreferences(
1461                                            _portalPreferences.getUserId(),
1462                                            PortletKeys.PREFS_OWNER_TYPE_USER, layout.getPlid()));
1463                    }
1464    
1465                    for (PortletPreferences portletPreference : portletPreferences) {
1466                            String portletId = portletPreference.getPortletId();
1467    
1468                            Portlet portlet = PortletLocalServiceUtil.getPortletById(
1469                                    getCompanyId(), portletId);
1470    
1471                            if (Validator.isNull(portletId) ||
1472                                    columnPortlets.contains(portlet) ||
1473                                    staticPortlets.contains(portlet) || !portlet.isReady() ||
1474                                    portlet.isUndeployedPortlet() || !portlet.isActive()) {
1475    
1476                                    continue;
1477                            }
1478    
1479                            if (portlet != null) {
1480                                    Portlet embeddedPortlet = portlet;
1481    
1482                                    if (portlet.isInstanceable()) {
1483    
1484                                            // Instanceable portlets do not need to be cloned because
1485                                            // they are already cloned. See the method getPortletById in
1486                                            // the class PortletLocalServiceImpl and how it references
1487                                            // the method getClonedInstance in the class PortletImpl.
1488    
1489                                    }
1490                                    else {
1491                                            embeddedPortlet = (Portlet)embeddedPortlet.clone();
1492                                    }
1493    
1494                                    // We set embedded portlets as static on order to avoid adding
1495                                    // the close and/or move icons.
1496    
1497                                    embeddedPortlet.setStatic(true);
1498    
1499                                    portlets.add(embeddedPortlet);
1500                            }
1501                    }
1502    
1503                    _embeddedPortlets = portlets;
1504    
1505                    return _embeddedPortlets;
1506            }
1507    
1508            protected List<String> getNestedColumns() {
1509                    String nestedColumnIds = getTypeSettingsProperty(
1510                            LayoutTypePortletConstants.NESTED_COLUMN_IDS);
1511    
1512                    return ListUtil.fromArray(StringUtil.split(nestedColumnIds));
1513            }
1514    
1515            protected long getPlid() {
1516                    Layout layout = getLayout();
1517    
1518                    return layout.getPlid();
1519            }
1520    
1521            protected String[] getStaticPortletIds(String position)
1522                    throws PortalException, SystemException {
1523    
1524                    Layout layout = getLayout();
1525    
1526                    String selector1 = StringPool.BLANK;
1527    
1528                    Group group = layout.getGroup();
1529    
1530                    if (group.isUser()) {
1531                            selector1 = LayoutTypePortletConstants.STATIC_PORTLET_USER_SELECTOR;
1532                    }
1533                    else if (group.isOrganization()) {
1534                            selector1 =
1535                                    LayoutTypePortletConstants.STATIC_PORTLET_ORGANIZATION_SELECTOR;
1536                    }
1537                    else if (group.isRegularSite()) {
1538                            selector1 =
1539                                    LayoutTypePortletConstants.STATIC_PORTLET_REGULAR_SITE_SELECTOR;
1540                    }
1541    
1542                    String selector2 = layout.getFriendlyURL();
1543    
1544                    String[] portletIds = PropsUtil.getArray(
1545                            position, new Filter(selector1, selector2));
1546    
1547                    for (int i = 0; i < portletIds.length; i++) {
1548                            portletIds[i] = JS.getSafeName(portletIds[i]);
1549                    }
1550    
1551                    return portletIds;
1552            }
1553    
1554            protected List<Portlet> getStaticPortlets(String position)
1555                    throws PortalException, SystemException {
1556    
1557                    String[] portletIds = getStaticPortletIds(position);
1558    
1559                    List<Portlet> portlets = new ArrayList<Portlet>();
1560    
1561                    for (String portletId : portletIds) {
1562                            if (Validator.isNull(portletId) ||
1563                                    hasNonstaticPortletId(portletId)) {
1564    
1565                                    continue;
1566                            }
1567    
1568                            Portlet portlet = PortletLocalServiceUtil.getPortletById(
1569                                    getCompanyId(), portletId);
1570    
1571                            if (portlet != null) {
1572                                    Portlet staticPortlet = portlet;
1573    
1574                                    if (portlet.isInstanceable()) {
1575    
1576                                            // Instanceable portlets do not need to be cloned because
1577                                            // they are already cloned. See the method getPortletById in
1578                                            // the class PortletLocalServiceImpl and how it references
1579                                            // the method getClonedInstance in the class PortletImpl.
1580    
1581                                    }
1582                                    else {
1583                                            staticPortlet = (Portlet)staticPortlet.clone();
1584                                    }
1585    
1586                                    staticPortlet.setStatic(true);
1587    
1588                                    if (position.startsWith("layout.static.portlets.start")) {
1589                                            staticPortlet.setStaticStart(true);
1590                                    }
1591    
1592                                    portlets.add(staticPortlet);
1593                            }
1594                    }
1595    
1596                    return portlets;
1597            }
1598    
1599            protected String getThemeId() {
1600                    String themeId = null;
1601    
1602                    try {
1603                            Layout layout = getLayout();
1604    
1605                            Theme theme = layout.getTheme();
1606    
1607                            if (theme != null) {
1608                                    themeId = theme.getThemeId();
1609                            }
1610                            else {
1611                                    themeId = layout.getThemeId();
1612                            }
1613                    }
1614                    catch (Exception e) {
1615                            _log.error(e, e);
1616                    }
1617    
1618                    return themeId;
1619            }
1620    
1621            protected String getUserPreference(String key) {
1622                    String value = StringPool.BLANK;
1623    
1624                    if (!hasUserPreferences()) {
1625                            return value;
1626                    }
1627    
1628                    value = _portalPreferences.getValue(
1629                            CustomizedPages.namespacePlid(getPlid()), key, StringPool.NULL);
1630    
1631                    if (!value.equals(StringPool.NULL)) {
1632                            return value;
1633                    }
1634    
1635                    value = getTypeSettingsProperty(key);
1636    
1637                    if (Validator.isNull(value)) {
1638                            return value;
1639                    }
1640    
1641                    List<String> newPortletIds = new ArrayList<String>();
1642    
1643                    PermissionChecker permissionChecker =
1644                            PermissionThreadLocal.getPermissionChecker();
1645    
1646                    String[] portletIds = StringUtil.split(value);
1647    
1648                    for (String portletId : portletIds) {
1649                            try {
1650                                    String rootPortletId = PortletConstants.getRootPortletId(
1651                                            portletId);
1652    
1653                                    if (!PortletPermissionUtil.contains(
1654                                                    permissionChecker, rootPortletId,
1655                                                    ActionKeys.ADD_TO_PAGE)) {
1656    
1657                                            continue;
1658                                    }
1659                            }
1660                            catch (Exception e) {
1661                                    _log.error(e, e);
1662                            }
1663    
1664                            String newPortletId = null;
1665    
1666                            if (PortletConstants.hasInstanceId(portletId)) {
1667                                    newPortletId = PortletConstants.assemblePortletId(
1668                                            portletId, _portalPreferences.getUserId(),
1669                                            generateInstanceId());
1670    
1671                                    copyPreferences(
1672                                            _portalPreferences.getUserId(), portletId, newPortletId);
1673                            }
1674                            else {
1675                                    newPortletId = portletId;
1676                            }
1677    
1678                            newPortletIds.add(newPortletId);
1679                    }
1680    
1681                    value = StringUtil.merge(newPortletIds);
1682    
1683                    setUserPreference(key, value);
1684    
1685                    return value;
1686            }
1687    
1688            protected boolean hasNonstaticPortletId(String portletId) {
1689                    LayoutTemplate layoutTemplate = getLayoutTemplate();
1690    
1691                    List<String> columns = layoutTemplate.getColumns();
1692    
1693                    for (int i = 0; i < columns.size(); i++) {
1694                            String columnId = columns.get(i);
1695    
1696                            if (hasNonstaticPortletId(columnId, portletId)) {
1697                                    return true;
1698                            }
1699                    }
1700    
1701                    return false;
1702            }
1703    
1704            protected boolean hasNonstaticPortletId(String columnId, String portletId) {
1705                    String columnValue = getColumnValue(columnId);
1706    
1707                    String[] columnValues = StringUtil.split(columnValue);
1708    
1709                    for (String nonstaticPortletId : columnValues) {
1710                            if (nonstaticPortletId.equals(portletId) ||
1711                                    PortletConstants.getRootPortletId(
1712                                            nonstaticPortletId).equals(portletId)) {
1713    
1714                                    return true;
1715                            }
1716                    }
1717    
1718                    return false;
1719            }
1720    
1721            protected boolean hasStaticPortletId(String columnId, String portletId)
1722                    throws PortalException, SystemException {
1723    
1724                    String[] staticPortletIdsStart = getStaticPortletIds(
1725                            PropsKeys.LAYOUT_STATIC_PORTLETS_START + columnId);
1726    
1727                    String[] staticPortletIdsEnd = getStaticPortletIds(
1728                            PropsKeys.LAYOUT_STATIC_PORTLETS_END + columnId);
1729    
1730                    for (String staticPortletId : staticPortletIdsStart) {
1731                            if (staticPortletId.equals(portletId) ||
1732                                    PortletConstants.getRootPortletId(
1733                                            staticPortletId).equals(portletId)) {
1734    
1735                                    return true;
1736                            }
1737                    }
1738    
1739                    for (String staticPortletId : staticPortletIdsEnd) {
1740                            if (staticPortletId.equals(portletId) ||
1741                                    PortletConstants.getRootPortletId(
1742                                            staticPortletId).equals(portletId)) {
1743    
1744                                    return true;
1745                            }
1746                    }
1747    
1748                    return false;
1749            }
1750    
1751            protected boolean hasUserPreferences() {
1752                    if (_portalPreferences != null) {
1753                            return true;
1754                    }
1755    
1756                    return false;
1757            }
1758    
1759            protected boolean isLayoutSetPrototype() {
1760                    try {
1761                            Layout layout = getLayout();
1762    
1763                            LayoutSet layoutSet = layout.getLayoutSet();
1764    
1765                            Group group = layoutSet.getGroup();
1766    
1767                            return group.isLayoutSetPrototype();
1768                    }
1769                    catch (Exception e) {
1770                            _log.error(e, e);
1771                    }
1772    
1773                    return false;
1774            }
1775    
1776            protected void onRemoveFromLayout(String[] portletIds)
1777                    throws SystemException {
1778    
1779                    List<String> portletIdList = new UniqueList<String>();
1780    
1781                    for (String portletId : portletIds) {
1782                            removeModesPortletId(portletId);
1783                            removeStatesPortletId(portletId);
1784    
1785                            portletIdList.add(portletId);
1786    
1787                            String rootPortletId = PortletConstants.getRootPortletId(portletId);
1788    
1789                            if (rootPortletId.equals(PortletKeys.NESTED_PORTLETS)) {
1790                                    String portletNamespace = PortalUtil.getPortletNamespace(
1791                                            portletId);
1792    
1793                                    UnicodeProperties typeSettingsProperties =
1794                                            getTypeSettingsProperties();
1795    
1796                                    for (Map.Entry<String, String> entry :
1797                                                    typeSettingsProperties.entrySet()) {
1798    
1799                                            String key = entry.getKey();
1800    
1801                                            if (!key.startsWith(portletNamespace)) {
1802                                                    continue;
1803                                            }
1804    
1805                                            String nestedPortletIds = entry.getValue();
1806    
1807                                            for (String nestedPortletId :
1808                                                            StringUtil.split(nestedPortletIds)) {
1809    
1810                                                    removeModesPortletId(nestedPortletId);
1811                                                    removeStatesPortletId(nestedPortletId);
1812    
1813                                                    portletIdList.add(nestedPortletId);
1814                                            }
1815                                    }
1816    
1817                                    removeNestedColumns(portletNamespace);
1818                            }
1819                    }
1820    
1821                    try {
1822                            PortletLocalServiceUtil.deletePortlets(
1823                                    getCompanyId(),
1824                                    portletIdList.toArray(new String[portletIdList.size()]),
1825                                    getPlid());
1826                    }
1827                    catch (PortalException pe) {
1828                            _log.error(pe, pe);
1829                    }
1830            }
1831    
1832            protected void setUserPreference(String key, String value) {
1833                    if (!hasUserPreferences()) {
1834                            return;
1835                    }
1836    
1837                    _portalPreferences.setValue(
1838                            CustomizedPages.namespacePlid(getPlid()), key, value);
1839    
1840                    _portalPreferences.setValue(
1841                            CustomizedPages.namespacePlid(getPlid()), _MODIFIED_DATE,
1842                            _dateFormat.format(new Date()));
1843            }
1844    
1845            private static final String _MODIFIED_DATE = "modifiedDate";
1846    
1847            private static final String _NULL_DATE = "00000000000000";
1848    
1849            private static Log _log = LogFactoryUtil.getLog(
1850                    LayoutTypePortletImpl.class);
1851    
1852            private static String _nestedPortletsNamespace;
1853    
1854            private boolean _customizedView;
1855            private Format _dateFormat = FastDateFormatFactoryUtil.getSimpleDateFormat(
1856                    PropsValues.INDEX_DATE_FORMAT_PATTERN);
1857            private List<Portlet> _embeddedPortlets;
1858            private boolean _enablePortletLayoutListener = true;
1859            private Layout _layoutSetPrototypeLayout;
1860            private PortalPreferences _portalPreferences;
1861            private boolean _updatePermission;
1862    
1863    }