1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.model.impl;
24  
25  import com.liferay.portal.SystemException;
26  import com.liferay.portal.kernel.configuration.Filter;
27  import com.liferay.portal.kernel.log.Log;
28  import com.liferay.portal.kernel.log.LogFactoryUtil;
29  import com.liferay.portal.kernel.portlet.PortletLayoutListener;
30  import com.liferay.portal.kernel.util.ArrayUtil;
31  import com.liferay.portal.kernel.util.GetterUtil;
32  import com.liferay.portal.kernel.util.ListUtil;
33  import com.liferay.portal.kernel.util.PropsKeys;
34  import com.liferay.portal.kernel.util.StringPool;
35  import com.liferay.portal.kernel.util.StringUtil;
36  import com.liferay.portal.kernel.util.UnicodeProperties;
37  import com.liferay.portal.kernel.util.Validator;
38  import com.liferay.portal.model.Group;
39  import com.liferay.portal.model.Layout;
40  import com.liferay.portal.model.LayoutTemplate;
41  import com.liferay.portal.model.LayoutTypePortlet;
42  import com.liferay.portal.model.Plugin;
43  import com.liferay.portal.model.Portlet;
44  import com.liferay.portal.model.PortletConstants;
45  import com.liferay.portal.model.PortletPreferences;
46  import com.liferay.portal.model.Theme;
47  import com.liferay.portal.service.LayoutTemplateLocalServiceUtil;
48  import com.liferay.portal.service.PluginSettingLocalServiceUtil;
49  import com.liferay.portal.service.PortletLocalServiceUtil;
50  import com.liferay.portal.service.PortletPreferencesLocalServiceUtil;
51  import com.liferay.portal.util.PortalUtil;
52  import com.liferay.portal.util.PortletKeys;
53  import com.liferay.portal.util.PropsUtil;
54  import com.liferay.portal.util.PropsValues;
55  import com.liferay.util.JS;
56  import com.liferay.util.PwdGenerator;
57  
58  import java.util.ArrayList;
59  import java.util.Iterator;
60  import java.util.List;
61  
62  /**
63   * <a href="LayoutTypePortletImpl.java.html"><b><i>View Source</i></b></a>
64   *
65   * @author Brian Wing Shun Chan
66   * @author Berentey Zsolt
67   * @author Jorge Ferrer
68   */
69  public class LayoutTypePortletImpl
70      extends LayoutTypeImpl implements LayoutTypePortlet {
71  
72      public static final String LAYOUT_TEMPLATE_ID = "layout-template-id";
73  
74      public static final String NESTED_COLUMN_IDS = "nested-column-ids";
75  
76      public static final String STATE_MAX = "state-max";
77  
78      public static final String STATE_MIN = "state-min";
79  
80      public static final String MODE_ABOUT = "mode-about";
81  
82      public static final String MODE_CONFIG = "mode-config";
83  
84      public static final String MODE_EDIT = "mode-edit";
85  
86      public static final String MODE_EDIT_DEFAULTS = "mode-edit-defaults";
87  
88      public static final String MODE_EDIT_GUEST = "mode-edit-guest";
89  
90      public static final String MODE_HELP = "mode-help";
91  
92      public static final String MODE_PREVIEW = "mode-preview";
93  
94      public static final String MODE_PRINT = "mode-print";
95  
96      public static final String STATIC_PORTLET_COMMUNITY_SELECTOR = "community";
97  
98      public static final String STATIC_PORTLET_ORGANIZATION_SELECTOR =
99          "organization";
100 
101     public static final String STATIC_PORTLET_USER_SELECTOR = "user";
102 
103     public static String getFullInstanceSeparator() {
104         String instanceId = PwdGenerator.getPassword(
105             PwdGenerator.KEY1 + PwdGenerator.KEY2 + PwdGenerator.KEY3, 4);
106 
107         return PortletConstants.INSTANCE_SEPARATOR + instanceId;
108     }
109 
110     public LayoutTypePortletImpl(LayoutImpl layout) {
111         super(layout);
112     }
113 
114     public LayoutTemplate getLayoutTemplate() {
115         LayoutTemplate layoutTemplate =
116             LayoutTemplateLocalServiceUtil.getLayoutTemplate(
117                 getLayoutTemplateId(), false, null);
118 
119         if (layoutTemplate == null) {
120             layoutTemplate = new LayoutTemplateImpl(
121                 StringPool.BLANK, StringPool.BLANK);
122 
123             List<String> columns = new ArrayList<String>();
124 
125             for (int i = 1; i <= 10; i++) {
126                 columns.add("column-" + i);
127             }
128 
129             layoutTemplate.setColumns(columns);
130         }
131 
132         return layoutTemplate;
133     }
134 
135     public String getLayoutTemplateId() {
136         String layoutTemplateId =
137             getTypeSettingsProperties().getProperty(LAYOUT_TEMPLATE_ID);
138 
139         if (Validator.isNull(layoutTemplateId)) {
140             layoutTemplateId = StringPool.BLANK;
141         }
142 
143         return layoutTemplateId;
144     }
145 
146     public void setLayoutTemplateId(long userId, String newLayoutTemplateId) {
147         setLayoutTemplateId(userId, newLayoutTemplateId, true);
148     }
149 
150     public void setLayoutTemplateId(
151         long userId, String newLayoutTemplateId, boolean checkPermission) {
152 
153         if (checkPermission &&
154             !PluginSettingLocalServiceUtil.hasPermission(
155                 userId, newLayoutTemplateId, Plugin.TYPE_LAYOUT_TEMPLATE)) {
156 
157             return;
158         }
159 
160         String oldLayoutTemplateId = getLayoutTemplateId();
161 
162         if (Validator.isNull(oldLayoutTemplateId)) {
163             oldLayoutTemplateId = PropsValues.DEFAULT_LAYOUT_TEMPLATE_ID;
164         }
165 
166         getTypeSettingsProperties().setProperty(
167             LAYOUT_TEMPLATE_ID, newLayoutTemplateId);
168 
169         String themeId = null;
170 
171         try {
172             Layout layout = getLayout();
173 
174             Theme theme = layout.getTheme();
175 
176             if (theme != null) {
177                 themeId = theme.getThemeId();
178             }
179             else {
180                 themeId = layout.getThemeId();
181             }
182         }
183         catch (Exception e) {
184             _log.error(e, e);
185         }
186 
187         LayoutTemplate oldLayoutTemplate =
188             LayoutTemplateLocalServiceUtil.getLayoutTemplate(
189                 oldLayoutTemplateId, false, themeId);
190 
191         if (oldLayoutTemplate == null) {
192             return;
193         }
194 
195         LayoutTemplate newLayoutTemplate =
196             LayoutTemplateLocalServiceUtil.getLayoutTemplate(
197                 newLayoutTemplateId, false, themeId);
198 
199         List<String> oldColumns = oldLayoutTemplate.getColumns();
200         List<String> newColumns = newLayoutTemplate.getColumns();
201 
202         reorganizePortlets(newColumns, oldColumns);
203     }
204 
205     public int getNumOfColumns() {
206         return getLayoutTemplate().getColumns().size();
207     }
208 
209     public List<Portlet> getAllPortlets() throws SystemException {
210         List<Portlet> portlets = new ArrayList<Portlet>();
211 
212         List<String> columns = getColumns();
213 
214         for (int i = 0; i < columns.size(); i++) {
215             String columnId = columns.get(i);
216 
217             portlets.addAll(getAllPortlets(columnId));
218 
219         }
220 
221         return portlets;
222     }
223 
224     public List<Portlet> getAllPortlets(String columnId)
225         throws SystemException {
226 
227         String columnValue =
228             getTypeSettingsProperties().getProperty(columnId);
229 
230         String[] portletIds = StringUtil.split(columnValue);
231 
232         List<Portlet> portlets = new ArrayList<Portlet>(portletIds.length);
233 
234         for (int i = 0; i < portletIds.length; i++) {
235             Portlet portlet = PortletLocalServiceUtil.getPortletById(
236                 getLayout().getCompanyId(), portletIds[i]);
237 
238             if (portlet != null) {
239                 portlets.add(portlet);
240             }
241         }
242 
243         List<Portlet> startPortlets = getStaticPortlets(
244             PropsKeys.LAYOUT_STATIC_PORTLETS_START + columnId);
245 
246         List<Portlet> endPortlets = getStaticPortlets(
247             PropsKeys.LAYOUT_STATIC_PORTLETS_END + columnId);
248 
249         return addStaticPortlets(portlets, startPortlets, endPortlets);
250     }
251 
252     public List<Portlet> addStaticPortlets(
253         List<Portlet> portlets, List<Portlet> startPortlets,
254         List<Portlet> endPortlets) {
255 
256         // Return the original array of portlets if no static portlets are
257         // specified
258 
259         if (startPortlets == null) {
260             startPortlets = new ArrayList<Portlet>();
261         }
262 
263         if (endPortlets == null) {
264             endPortlets = new ArrayList<Portlet>();
265         }
266 
267         if ((startPortlets.isEmpty()) && (endPortlets.isEmpty())) {
268             return portlets;
269         }
270 
271         // New array of portlets that contain the static portlets
272 
273         List<Portlet> list = new ArrayList<Portlet>(
274             portlets.size() + startPortlets.size() + endPortlets.size());
275 
276         if (startPortlets != null) {
277             list.addAll(startPortlets);
278         }
279 
280         for (int i = 0; i < portlets.size(); i++) {
281             Portlet portlet = portlets.get(i);
282 
283             // Add the portlet if and only if it is not also a static portlet
284 
285             if (!startPortlets.contains(portlet) &&
286                 !endPortlets.contains(portlet)) {
287 
288                 list.add(portlet);
289             }
290         }
291 
292         if (endPortlets != null) {
293             list.addAll(endPortlets);
294         }
295 
296         return list;
297     }
298 
299     // Modify portlets
300 
301     public String addPortletId(long userId, String portletId) {
302         return addPortletId(userId, portletId, true);
303     }
304 
305     public String addPortletId(
306         long userId, String portletId, boolean checkPermission) {
307 
308         return addPortletId(userId, portletId, null, -1, checkPermission);
309     }
310 
311     public String addPortletId(
312         long userId, String portletId, String columnId, int columnPos) {
313 
314         return addPortletId(userId, portletId, columnId, columnPos, true);
315     }
316 
317     public String addPortletId(
318         long userId, String portletId, String columnId, int columnPos,
319         boolean checkPermission) {
320 
321         portletId = JS.getSafeName(portletId);
322 
323         Layout layout = getLayout();
324 
325         Portlet portlet = null;
326 
327         try {
328             portlet = PortletLocalServiceUtil.getPortletById(
329                 layout.getCompanyId(), portletId);
330 
331             if (portlet == null) {
332                 _log.error(
333                     "Portlet " + portletId +
334                         " cannot be added because it is not registered");
335 
336                 return null;
337             }
338 
339             if (checkPermission && !portlet.hasAddPortletPermission(userId)) {
340                 return null;
341             }
342         }
343         catch (Exception e) {
344             _log.error(e, e);
345         }
346 
347         if (portlet.isSystem()) {
348             return null;
349         }
350 
351         if ((portlet.isInstanceable()) &&
352             (PortletConstants.getInstanceId(portlet.getPortletId()) == null)) {
353 
354             portletId = portletId + getFullInstanceSeparator();
355         }
356 
357         if (hasPortletId(portletId)) {
358             return null;
359         }
360 
361         if (columnId == null) {
362             LayoutTemplate layoutTemplate = getLayoutTemplate();
363 
364             List<String> columns = layoutTemplate.getColumns();
365 
366             if (columns.size() > 0) {
367                 columnId = columns.get(0);
368             }
369         }
370 
371         if (columnId != null) {
372             String columnValue = getTypeSettingsProperties().getProperty(
373                 columnId);
374 
375             if ((columnValue == null) &&
376                 (columnId.startsWith(_NESTED_PORTLETS_NAMESPACE))) {
377 
378                 addNestedColumn(columnId);
379             }
380 
381             if (columnPos >= 0) {
382                 List<String> portletIds = ListUtil.fromArray(
383                     StringUtil.split(columnValue));
384 
385                 if (columnPos <= portletIds.size()) {
386                     portletIds.add(columnPos, portletId);
387                 }
388                 else {
389                     portletIds.add(portletId);
390                 }
391 
392                 columnValue = StringUtil.merge(portletIds);
393             }
394             else {
395                 columnValue = StringUtil.add(columnValue, portletId);
396             }
397 
398             getTypeSettingsProperties().setProperty(columnId, columnValue);
399         }
400 
401         try {
402             PortletLayoutListener portletLayoutListener =
403                 portlet.getPortletLayoutListenerInstance();
404 
405             if (_enablePortletLayoutListener &&
406                 (portletLayoutListener != null)) {
407 
408                 portletLayoutListener.onAddToLayout(
409                     portletId, layout.getPlid());
410             }
411         }
412         catch (Exception e) {
413             _log.error("Unable to fire portlet layout listener event", e);
414         }
415 
416         return portletId;
417     }
418 
419     public void addPortletIds(
420         long userId, String[] portletIds, boolean checkPermission) {
421 
422         for (int i = 0; i < portletIds.length; i++) {
423             String portletId = portletIds[i];
424 
425             addPortletId(userId, portletId, checkPermission);
426         }
427     }
428 
429     public void addPortletIds(
430         long userId, String[] portletIds, String columnId,
431         boolean checkPermission) {
432 
433         for (int i = 0; i < portletIds.length; i++) {
434             String portletId = portletIds[i];
435 
436             addPortletId(userId, portletId, columnId, -1, checkPermission);
437         }
438     }
439 
440     public List<Portlet> getPortlets() throws SystemException {
441         List<String> portletIds = getPortletIds();
442 
443         List<Portlet> portlets = new ArrayList<Portlet>(portletIds.size());
444 
445         for (int i = 0; i < portletIds.size(); i++) {
446             String portletId = portletIds.get(i);
447 
448             Portlet portlet = PortletLocalServiceUtil.getPortletById(
449                 getLayout().getCompanyId(), portletId);
450 
451             if (portlet != null) {
452                 portlets.add(portlet);
453             }
454         }
455 
456         return portlets;
457     }
458 
459     public List<String> getPortletIds() {
460         List<String> portletIds = new ArrayList<String>();
461 
462         List<String> columns = getColumns();
463 
464         for (int i = 0; i < columns.size(); i++) {
465             String columnId = columns.get(i);
466 
467             String columnValue =
468                 getTypeSettingsProperties().getProperty(columnId);
469 
470             portletIds.addAll(
471                 ListUtil.fromArray(StringUtil.split(columnValue)));
472 
473         }
474 
475         return portletIds;
476     }
477 
478     public boolean hasPortletId(String portletId) {
479         List<String> columns = getColumns();
480 
481         for (int i = 0; i < columns.size(); i++) {
482             String columnId = columns.get(i);
483 
484             if (hasNonstaticPortletId(columnId, portletId)) {
485                 return true;
486             }
487 
488             if (hasStaticPortletId(columnId, portletId)) {
489                 return true;
490             }
491         }
492 
493         if (hasStateMaxPortletId(portletId)) {
494             return true;
495         }
496 
497         return false;
498     }
499 
500     public void movePortletId(
501         long userId, String portletId, String columnId, int columnPos) {
502 
503         _enablePortletLayoutListener = false;
504 
505         try {
506             removePortletId(userId, portletId, false);
507             addPortletId(userId, portletId, columnId, columnPos);
508         }
509         finally {
510             _enablePortletLayoutListener = true;
511         }
512 
513         Layout layout = getLayout();
514 
515         try {
516             Portlet portlet = PortletLocalServiceUtil.getPortletById(
517                 layout.getCompanyId(), portletId);
518 
519             if (portlet != null) {
520                 PortletLayoutListener portletLayoutListener =
521                     portlet.getPortletLayoutListenerInstance();
522 
523                 if (portletLayoutListener != null) {
524                     portletLayoutListener.onMoveInLayout(
525                         portletId, layout.getPlid());
526                 }
527             }
528         }
529         catch (Exception e) {
530             _log.error("Unable to fire portlet layout listener event", e);
531         }
532     }
533 
534     public void removePortletId(long userId, String portletId) {
535         removePortletId(userId, portletId, true);
536     }
537 
538     public void removePortletId (
539         long userId, String portletId, boolean cleanUp) {
540 
541         try {
542             Layout layout = getLayout();
543 
544             Portlet portlet = PortletLocalServiceUtil.getPortletById(
545                 layout.getCompanyId(), portletId);
546 
547             if (portlet == null) {
548                 _log.error(
549                     "Portlet " + portletId +
550                         " cannot be removed because it is not registered");
551 
552                 return;
553             }
554 
555             if (!portlet.hasAddPortletPermission(userId)) {
556                 return;
557             }
558         }
559         catch (Exception e) {
560             _log.error(e, e);
561         }
562 
563         List<String> columns = getColumns();
564 
565         for (int i = 0; i < columns.size(); i++) {
566             String columnId = columns.get(i);
567 
568             String columnValue =
569                 getTypeSettingsProperties().getProperty(columnId);
570 
571             columnValue = StringUtil.remove(columnValue, portletId);
572 
573             getTypeSettingsProperties().setProperty(columnId, columnValue);
574         }
575 
576         if (cleanUp) {
577             removeStatesPortletId(portletId);
578             removeModesPortletId(portletId);
579 
580             try {
581                 onRemoveFromLayout(portletId);
582             }
583             catch (Exception e) {
584                 _log.error("Unable to fire portlet layout listener event", e);
585             }
586         }
587     }
588 
589     public void setPortletIds(String columnId, String portletIds) {
590         getTypeSettingsProperties().setProperty(columnId, portletIds);
591     }
592 
593     public void reorganizePortlets(
594         List<String> newColumns, List<String> oldColumns) {
595 
596         String lastNewColumnId = newColumns.get(newColumns.size() - 1);
597         String lastNewColumnValue =
598             getTypeSettingsProperties().getProperty(lastNewColumnId);
599 
600         Iterator<String> itr = oldColumns.iterator();
601 
602         while (itr.hasNext()) {
603             String oldColumnId = itr.next();
604 
605             if (!newColumns.contains(oldColumnId)) {
606                 String oldColumnValue = getTypeSettingsProperties().remove(
607                     oldColumnId);
608 
609                 String[] portletIds = StringUtil.split(oldColumnValue);
610 
611                 for (String portletId : portletIds) {
612                     lastNewColumnValue = StringUtil.add(
613                         lastNewColumnValue, portletId);
614                 }
615             }
616         }
617 
618         getTypeSettingsProperties().setProperty(
619             lastNewColumnId, lastNewColumnValue);
620     }
621 
622     // Maximized state
623 
624     public String getStateMax() {
625         return getTypeSettingsProperties().getProperty(STATE_MAX);
626     }
627 
628     public void setStateMax(String stateMax) {
629         getTypeSettingsProperties().setProperty(STATE_MAX, stateMax);
630     }
631 
632     public boolean hasStateMax() {
633         String[] stateMax = StringUtil.split(getStateMax());
634 
635         if (stateMax.length > 0) {
636             return true;
637         }
638         else {
639             return false;
640         }
641     }
642 
643     public void addStateMaxPortletId(String portletId) {
644         removeStatesPortletId(portletId);
645         //setStateMax(StringUtil.add(getStateMax(), portletId));
646         setStateMax(StringUtil.add(StringPool.BLANK, portletId));
647     }
648 
649     public String getStateMaxPortletId() {
650         String[] stateMax = StringUtil.split(getStateMax());
651 
652         if (stateMax.length > 0) {
653             return stateMax[0];
654         }
655         else {
656             return StringPool.BLANK;
657         }
658     }
659 
660     public boolean hasStateMaxPortletId(String portletId) {
661         if (StringUtil.contains(getStateMax(), portletId)) {
662             return true;
663         }
664         else {
665             return false;
666         }
667     }
668 
669     public void removeStateMaxPortletId(String portletId) {
670         setStateMax(StringUtil.remove(getStateMax(), portletId));
671     }
672 
673     // Minimized state
674 
675     public String getStateMin() {
676         return getTypeSettingsProperties().getProperty(STATE_MIN);
677     }
678 
679     public void setStateMin(String stateMin) {
680         getTypeSettingsProperties().setProperty(STATE_MIN, stateMin);
681     }
682 
683     public boolean hasStateMin() {
684         String[] stateMin = StringUtil.split(getStateMin());
685 
686         if (stateMin.length > 0) {
687             return true;
688         }
689         else {
690             return false;
691         }
692     }
693 
694     public void addStateMinPortletId(String portletId) {
695         removeStateMaxPortletId(portletId);
696         setStateMin(StringUtil.add(getStateMin(), portletId));
697     }
698 
699     public boolean hasStateMinPortletId(String portletId) {
700         if (StringUtil.contains(getStateMin(), portletId)) {
701             return true;
702         }
703         else {
704             return false;
705         }
706     }
707 
708     public void removeStateMinPortletId(String portletId) {
709         setStateMin(StringUtil.remove(getStateMin(), portletId));
710     }
711 
712     // Normal state
713 
714     public boolean hasStateNormalPortletId(String portletId) {
715         if (hasStateMaxPortletId(portletId) ||
716             hasStateMinPortletId(portletId)) {
717 
718             return false;
719         }
720         else {
721             return true;
722         }
723     }
724 
725     // All states
726 
727     public void resetStates() {
728         setStateMax(StringPool.BLANK);
729         setStateMin(StringPool.BLANK);
730     }
731 
732     public void removeStatesPortletId(String portletId) {
733         removeStateMaxPortletId(portletId);
734         removeStateMinPortletId(portletId);
735     }
736 
737     // About mode
738 
739     public String getModeAbout() {
740         return getTypeSettingsProperties().getProperty(MODE_ABOUT);
741     }
742 
743     public void setModeAbout(String modeAbout) {
744         getTypeSettingsProperties().setProperty(MODE_ABOUT, modeAbout);
745     }
746 
747     public void addModeAboutPortletId(String portletId) {
748         removeModesPortletId(portletId);
749         setModeAbout(StringUtil.add(getModeAbout(), portletId));
750     }
751 
752     public boolean hasModeAboutPortletId(String portletId) {
753         return StringUtil.contains(getModeAbout(), portletId);
754     }
755 
756     public void removeModeAboutPortletId(String portletId) {
757         setModeAbout(StringUtil.remove(getModeAbout(), portletId));
758     }
759 
760     // Config mode
761 
762     public String getModeConfig() {
763         return getTypeSettingsProperties().getProperty(MODE_CONFIG);
764     }
765 
766     public void setModeConfig(String modeConfig) {
767         getTypeSettingsProperties().setProperty(MODE_CONFIG, modeConfig);
768     }
769 
770     public void addModeConfigPortletId(String portletId) {
771         removeModesPortletId(portletId);
772         setModeConfig(StringUtil.add(getModeConfig(), portletId));
773     }
774 
775     public boolean hasModeConfigPortletId(String portletId) {
776         return StringUtil.contains(getModeConfig(), portletId);
777     }
778 
779     public void removeModeConfigPortletId(String portletId) {
780         setModeConfig(StringUtil.remove(getModeConfig(), portletId));
781     }
782 
783     // Edit mode
784 
785     public String getModeEdit() {
786         return getTypeSettingsProperties().getProperty(MODE_EDIT);
787     }
788 
789     public void setModeEdit(String modeEdit) {
790         getTypeSettingsProperties().setProperty(MODE_EDIT, modeEdit);
791     }
792 
793     public void addModeEditPortletId(String portletId) {
794         removeModesPortletId(portletId);
795         setModeEdit(StringUtil.add(getModeEdit(), portletId));
796     }
797 
798     public boolean hasModeEditPortletId(String portletId) {
799         return StringUtil.contains(getModeEdit(), portletId);
800     }
801 
802     public void removeModeEditPortletId(String portletId) {
803         setModeEdit(StringUtil.remove(getModeEdit(), portletId));
804     }
805 
806     // Edit defaults mode
807 
808     public String getModeEditDefaults() {
809         return getTypeSettingsProperties().getProperty(MODE_EDIT_DEFAULTS);
810     }
811 
812     public void setModeEditDefaults(String modeEditDefaults) {
813         getTypeSettingsProperties().setProperty(
814             MODE_EDIT_DEFAULTS, modeEditDefaults);
815     }
816 
817     public void addModeEditDefaultsPortletId(String portletId) {
818         removeModesPortletId(portletId);
819         setModeEditDefaults(StringUtil.add(getModeEditDefaults(), portletId));
820     }
821 
822     public boolean hasModeEditDefaultsPortletId(String portletId) {
823         return StringUtil.contains(getModeEditDefaults(), portletId);
824     }
825 
826     public void removeModeEditDefaultsPortletId(String portletId) {
827         setModeEditDefaults(
828             StringUtil.remove(getModeEditDefaults(), portletId));
829     }
830 
831     // Edit guest mode
832 
833     public String getModeEditGuest() {
834         return getTypeSettingsProperties().getProperty(MODE_EDIT_GUEST);
835     }
836 
837     public void setModeEditGuest(String modeEditGuest) {
838         getTypeSettingsProperties().setProperty(MODE_EDIT_GUEST, modeEditGuest);
839     }
840 
841     public void addModeEditGuestPortletId(String portletId) {
842         removeModesPortletId(portletId);
843         setModeEditGuest(StringUtil.add(getModeEditGuest(), portletId));
844     }
845 
846     public boolean hasModeEditGuestPortletId(String portletId) {
847         return StringUtil.contains(getModeEditGuest(), portletId);
848     }
849 
850     public void removeModeEditGuestPortletId(String portletId) {
851         setModeEditGuest(StringUtil.remove(getModeEditGuest(), portletId));
852     }
853 
854     // Help mode
855 
856     public String getModeHelp() {
857         return getTypeSettingsProperties().getProperty(MODE_HELP);
858     }
859 
860     public void setModeHelp(String modeHelp) {
861         getTypeSettingsProperties().setProperty(MODE_HELP, modeHelp);
862     }
863 
864     public void addModeHelpPortletId(String portletId) {
865         removeModesPortletId(portletId);
866         setModeHelp(StringUtil.add(getModeHelp(), portletId));
867     }
868 
869     public boolean hasModeHelpPortletId(String portletId) {
870         return StringUtil.contains(getModeHelp(), portletId);
871     }
872 
873     public void removeModeHelpPortletId(String portletId) {
874         setModeHelp(StringUtil.remove(getModeHelp(), portletId));
875     }
876 
877     // Preview mode
878 
879     public String getModePreview() {
880         return getTypeSettingsProperties().getProperty(MODE_PREVIEW);
881     }
882 
883     public void setModePreview(String modePreview) {
884         getTypeSettingsProperties().setProperty(MODE_PREVIEW, modePreview);
885     }
886 
887     public void addModePreviewPortletId(String portletId) {
888         removeModesPortletId(portletId);
889         setModePreview(StringUtil.add(getModePreview(), portletId));
890     }
891 
892     public boolean hasModePreviewPortletId(String portletId) {
893         return StringUtil.contains(getModePreview(), portletId);
894     }
895 
896     public void removeModePreviewPortletId(String portletId) {
897         setModePreview(StringUtil.remove(getModePreview(), portletId));
898     }
899 
900     // Print mode
901 
902     public String getModePrint() {
903         return getTypeSettingsProperties().getProperty(MODE_PRINT);
904     }
905 
906     public void setModePrint(String modePrint) {
907         getTypeSettingsProperties().setProperty(MODE_PRINT, modePrint);
908     }
909 
910     public void addModePrintPortletId(String portletId) {
911         removeModesPortletId(portletId);
912         setModePrint(StringUtil.add(getModePrint(), portletId));
913     }
914 
915     public boolean hasModePrintPortletId(String portletId) {
916         return StringUtil.contains(getModePrint(), portletId);
917     }
918 
919     public void removeModePrintPortletId(String portletId) {
920         setModePrint(StringUtil.remove(getModePrint(), portletId));
921     }
922 
923     // View mode
924 
925     public boolean hasModeViewPortletId(String portletId) {
926         if (hasModeAboutPortletId(portletId) ||
927             hasModeConfigPortletId(portletId) ||
928             hasModeEditPortletId(portletId) ||
929             hasModeEditDefaultsPortletId(portletId) ||
930             hasModeEditGuestPortletId(portletId) ||
931             hasModeHelpPortletId(portletId) ||
932             hasModePreviewPortletId(portletId) ||
933             hasModePrintPortletId(portletId)) {
934 
935             return false;
936         }
937         else {
938             return true;
939         }
940     }
941 
942     // All modes
943 
944     public void resetModes() {
945         setModeAbout(StringPool.BLANK);
946         setModeConfig(StringPool.BLANK);
947         setModeEdit(StringPool.BLANK);
948         setModeEditDefaults(StringPool.BLANK);
949         setModeEditGuest(StringPool.BLANK);
950         setModeHelp(StringPool.BLANK);
951         setModePreview(StringPool.BLANK);
952         setModePrint(StringPool.BLANK);
953     }
954 
955     public void removeModesPortletId(String portletId) {
956         removeModeAboutPortletId(portletId);
957         removeModeConfigPortletId(portletId);
958         removeModeEditPortletId(portletId);
959         removeModeEditDefaultsPortletId(portletId);
960         removeModeEditGuestPortletId(portletId);
961         removeModeHelpPortletId(portletId);
962         removeModePreviewPortletId(portletId);
963         removeModePrintPortletId(portletId);
964     }
965 
966     public void removeNestedColumns(String portletId) {
967         UnicodeProperties props = getTypeSettingsProperties();
968 
969         UnicodeProperties newProps = new UnicodeProperties();
970 
971         for (String key : props.keySet()) {
972             if (!key.startsWith(portletId)) {
973                 newProps.setProperty(key, props.getProperty(key));
974             }
975         }
976 
977         getLayout().setTypeSettingsProperties(newProps);
978 
979         String nestedColumnIds = GetterUtil.getString(
980             getTypeSettingsProperties().getProperty(NESTED_COLUMN_IDS));
981 
982         String[] nestedColumnIdsArray = ArrayUtil.removeByPrefix(
983             StringUtil.split(nestedColumnIds), portletId);
984 
985         getTypeSettingsProperties().setProperty(
986             NESTED_COLUMN_IDS, StringUtil.merge(nestedColumnIdsArray));
987     }
988 
989     protected void addNestedColumn(String columnId) {
990         String nestedColumnIds = getTypeSettingsProperties().getProperty(
991             NESTED_COLUMN_IDS, StringPool.BLANK);
992 
993         if (nestedColumnIds.indexOf(columnId) == -1) {
994             nestedColumnIds = StringUtil.add(nestedColumnIds, columnId);
995 
996             getTypeSettingsProperties().setProperty(
997                 NESTED_COLUMN_IDS, nestedColumnIds);
998         }
999     }
1000
1001    protected List<String> getColumns() {
1002        LayoutTemplate layoutTemplate = getLayoutTemplate();
1003
1004        List<String> columns = new ArrayList<String>();
1005
1006        columns.addAll(layoutTemplate.getColumns());
1007        columns.addAll(getNestedColumns());
1008
1009        return columns;
1010    }
1011
1012    protected List<String> getNestedColumns() {
1013        String nestedColumnIds = getTypeSettingsProperties().getProperty(
1014            NESTED_COLUMN_IDS);
1015
1016        return ListUtil.fromArray(StringUtil.split(nestedColumnIds));
1017    }
1018
1019    protected String[] getStaticPortletIds(String position) {
1020        Layout layout = getLayout();
1021
1022        String selector1 = StringPool.BLANK;
1023
1024        Group group = layout.getGroup();
1025
1026        if (group.isUser()) {
1027            selector1 = STATIC_PORTLET_USER_SELECTOR;
1028        }
1029        else if (group.isCommunity()) {
1030            selector1 = STATIC_PORTLET_COMMUNITY_SELECTOR;
1031        }
1032        else if (group.isOrganization()) {
1033            selector1 = STATIC_PORTLET_ORGANIZATION_SELECTOR;
1034        }
1035
1036        String selector2 = layout.getFriendlyURL();
1037
1038        String[] portletIds = PropsUtil.getArray(
1039            position, new Filter(selector1, selector2));
1040
1041        for (int i = 0; i < portletIds.length; i++) {
1042            portletIds[i] = JS.getSafeName(portletIds[i]);
1043        }
1044
1045        return portletIds;
1046    }
1047
1048    protected List<Portlet> getStaticPortlets(String position)
1049        throws SystemException {
1050
1051        String[] portletIds = getStaticPortletIds(position);
1052
1053        List<Portlet> portlets = new ArrayList<Portlet>();
1054
1055        for (int i = 0; i < portletIds.length; i++) {
1056            String portletId = portletIds[i];
1057
1058            if (Validator.isNull(portletId) ||
1059                hasNonstaticPortletId(portletId)) {
1060
1061                continue;
1062            }
1063
1064            Portlet portlet = PortletLocalServiceUtil.getPortletById(
1065                getLayout().getCompanyId(), portletId);
1066
1067            if (portlet != null) {
1068                Portlet staticPortlet = portlet;
1069
1070                if (portlet.isInstanceable()) {
1071
1072                    // Instanceable portlets do not need to be cloned because
1073                    // they are already cloned. See the method getPortletById in
1074                    // the class PortletLocalServiceImpl and how it references
1075                    // the method getClonedInstance in the class PortletImpl.
1076
1077                }
1078                else {
1079                    staticPortlet = (Portlet)staticPortlet.clone();
1080                }
1081
1082                staticPortlet.setStatic(true);
1083
1084                if (position.startsWith("layout.static.portlets.start")) {
1085                    staticPortlet.setStaticStart(true);
1086                }
1087
1088                portlets.add(staticPortlet);
1089            }
1090        }
1091
1092        return portlets;
1093    }
1094
1095    protected boolean hasNonstaticPortletId(String portletId) {
1096        LayoutTemplate layoutTemplate = getLayoutTemplate();
1097
1098        List<String> columns = layoutTemplate.getColumns();
1099
1100        for (int i = 0; i < columns.size(); i++) {
1101            String columnId = columns.get(i);
1102
1103            if (hasNonstaticPortletId(columnId, portletId)) {
1104                return true;
1105            }
1106        }
1107
1108        return false;
1109    }
1110
1111    protected boolean hasNonstaticPortletId(String columnId, String portletId) {
1112        String columnValue = getTypeSettingsProperties().getProperty(columnId);
1113
1114        if (StringUtil.contains(columnValue, portletId)) {
1115            return true;
1116        }
1117        else {
1118            return false;
1119        }
1120    }
1121
1122    /*protected boolean hasStaticPortletId(String portletId) {
1123        LayoutTemplate layoutTemplate = getLayoutTemplate();
1124
1125        List columns = layoutTemplate.getColumns();
1126
1127        for (int i = 0; i < columns.size(); i++) {
1128            String columnId = (String)columns.get(i);
1129
1130            if (hasStaticPortletId(columnId, portletId)) {
1131                return true;
1132            }
1133        }
1134
1135        return false;
1136    }*/
1137
1138    protected boolean hasStaticPortletId(String columnId, String portletId) {
1139        String[] staticPortletIdsStart = getStaticPortletIds(
1140            PropsKeys.LAYOUT_STATIC_PORTLETS_START + columnId);
1141
1142        String[] staticPortletIdsEnd = getStaticPortletIds(
1143            PropsKeys.LAYOUT_STATIC_PORTLETS_END + columnId);
1144
1145        String[] staticPortletIds = ArrayUtil.append(
1146            staticPortletIdsStart, staticPortletIdsEnd);
1147
1148        for (int i = 0; i < staticPortletIds.length; i++) {
1149            String staticPortletId = staticPortletIds[i];
1150
1151            if (staticPortletId.equals(portletId)) {
1152                return true;
1153            }
1154        }
1155
1156        return false;
1157    }
1158
1159    protected void onRemoveFromLayout(String portletId) throws SystemException {
1160        Portlet portlet = PortletLocalServiceUtil.getPortletById(
1161            getLayout().getCompanyId(), portletId);
1162
1163        if (portlet == null) {
1164            return;
1165        }
1166
1167        if (portlet.getRootPortletId().equals(PortletKeys.NESTED_PORTLETS)) {
1168            UnicodeProperties props = getTypeSettingsProperties();
1169
1170            for (String key : props.keySet()) {
1171                if (key.startsWith(portlet.getPortletId())) {
1172                    String portletIds = props.getProperty(key);
1173
1174                    String[] portletIdsArray = StringUtil.split(portletIds);
1175
1176                    for (int i = 0; i < portletIdsArray.length; i++) {
1177                        onRemoveFromLayout(portletIdsArray[i]);
1178                    }
1179                }
1180            }
1181
1182            removeNestedColumns(portletId);
1183        }
1184
1185        if (_enablePortletLayoutListener) {
1186            PortletLayoutListener portletLayoutListener =
1187                portlet.getPortletLayoutListenerInstance();
1188
1189            long plid = getLayout().getPlid();
1190
1191            if ((portletLayoutListener != null)) {
1192                portletLayoutListener.onRemoveFromLayout(portletId, plid);
1193            }
1194        }
1195
1196        deletePortletSetup(portletId);
1197    }
1198
1199    protected void deletePortletSetup(String portletId) {
1200        try {
1201            List<PortletPreferences> list =
1202                PortletPreferencesLocalServiceUtil.getPortletPreferences(
1203                    getLayout().getPlid(), portletId);
1204
1205            for (int i = 0; i < list.size(); i++) {
1206                PortletPreferences portletPreferences = list.get(i);
1207
1208                PortletPreferencesLocalServiceUtil.deletePortletPreferences(
1209                    portletPreferences.getPortletPreferencesId());
1210            }
1211        }
1212        catch (Exception e) {
1213            _log.error(e, e);
1214        }
1215    }
1216
1217    private static final String _NESTED_PORTLETS_NAMESPACE =
1218        PortalUtil.getPortletNamespace(PortletKeys.NESTED_PORTLETS);
1219
1220    private static Log _log =
1221        LogFactoryUtil.getLog(LayoutTypePortletImpl.class);
1222
1223    private boolean _enablePortletLayoutListener = true;
1224
1225}