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