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