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