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