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.StringPool;
34  import com.liferay.portal.kernel.util.StringUtil;
35  import com.liferay.portal.kernel.util.UnicodeProperties;
36  import com.liferay.portal.kernel.util.Validator;
37  import com.liferay.portal.model.Group;
38  import com.liferay.portal.model.Layout;
39  import com.liferay.portal.model.LayoutTemplate;
40  import com.liferay.portal.model.LayoutTypePortlet;
41  import com.liferay.portal.model.Plugin;
42  import com.liferay.portal.model.Portlet;
43  import com.liferay.portal.model.PortletConstants;
44  import com.liferay.portal.model.PortletPreferences;
45  import com.liferay.portal.model.Theme;
46  import com.liferay.portal.service.LayoutTemplateLocalServiceUtil;
47  import com.liferay.portal.service.PluginSettingLocalServiceUtil;
48  import com.liferay.portal.service.PortletLocalServiceUtil;
49  import com.liferay.portal.service.PortletPreferencesLocalServiceUtil;
50  import com.liferay.portal.util.PortletKeys;
51  import com.liferay.portal.util.PropsKeys;
52  import com.liferay.portal.util.PropsUtil;
53  import com.liferay.portal.util.PropsValues;
54  import com.liferay.util.JS;
55  import com.liferay.util.PwdGenerator;
56  
57  import java.util.ArrayList;
58  import java.util.Iterator;
59  import java.util.List;
60  
61  /**
62   * <a href="LayoutTypePortletImpl.java.html"><b><i>View Source</i></b></a>
63   *
64   * @author Brian Wing Shun Chan
65   * @author Berentey Zsolt
66   * @author Jorge Ferrer
67   *
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 
337             if (checkPermission && !portlet.hasAddPortletPermission(userId)) {
338                 return null;
339             }
340         }
341         catch (Exception e) {
342             _log.error(e, e);
343         }
344 
345         if (portlet != null) {
346             if (portlet.isSystem()) {
347                 return null;
348             }
349 
350             if ((portlet.isInstanceable()) &&
351                 (PortletConstants.getInstanceId(
352                     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 =
373                     getTypeSettingsProperties().getProperty(columnId);
374 
375                 if ((columnValue == null) &&
376                     (columnId.startsWith(PortletKeys.NESTED_PORTLETS))) {
377 
378                     addNestedColumn(columnId);
379                 }
380 
381                 if (columnPos >= 0) {
382                     List<String> portletIds =
383                         ListUtil.fromArray(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.getPortletLayoutListener();
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         else {
419             return null;
420         }
421     }
422 
423     public void addPortletIds(
424         long userId, String[] portletIds, boolean checkPermission) {
425 
426         for (int i = 0; i < portletIds.length; i++) {
427             String portletId = portletIds[i];
428 
429             addPortletId(userId, portletId, checkPermission);
430         }
431     }
432 
433     public void addPortletIds(
434         long userId, String[] portletIds, String columnId,
435         boolean checkPermission) {
436 
437         for (int i = 0; i < portletIds.length; i++) {
438             String portletId = portletIds[i];
439 
440             addPortletId(userId, portletId, columnId, -1, checkPermission);
441         }
442     }
443 
444     public List<Portlet> getPortlets() throws SystemException {
445         List<String> portletIds = getPortletIds();
446 
447         List<Portlet> portlets = new ArrayList<Portlet>(portletIds.size());
448 
449         for (int i = 0; i < portletIds.size(); i++) {
450             String portletId = portletIds.get(i);
451 
452             Portlet portlet = PortletLocalServiceUtil.getPortletById(
453                 getLayout().getCompanyId(), portletId);
454 
455             if (portlet != null) {
456                 portlets.add(portlet);
457             }
458         }
459 
460         return portlets;
461     }
462 
463     public List<String> getPortletIds() {
464         List<String> portletIds = new ArrayList<String>();
465 
466         List<String> columns = getColumns();
467 
468         for (int i = 0; i < columns.size(); i++) {
469             String columnId = columns.get(i);
470 
471             String columnValue =
472                 getTypeSettingsProperties().getProperty(columnId);
473 
474             portletIds.addAll(
475                 ListUtil.fromArray(StringUtil.split(columnValue)));
476 
477         }
478 
479         return portletIds;
480     }
481 
482     public boolean hasPortletId(String portletId) {
483         List<String> columns = getColumns();
484 
485         for (int i = 0; i < columns.size(); i++) {
486             String columnId = columns.get(i);
487 
488             if (hasNonstaticPortletId(columnId, portletId)) {
489                 return true;
490             }
491 
492             if (hasStaticPortletId(columnId, portletId)) {
493                 return true;
494             }
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.getPortletLayoutListener();
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 
553             if (!portlet.hasAddPortletPermission(userId)) {
554                 return;
555             }
556         }
557         catch (Exception e) {
558             _log.error(e, e);
559         }
560 
561         List<String> columns = getColumns();
562 
563         for (int i = 0; i < columns.size(); i++) {
564             String columnId = columns.get(i);
565 
566             String columnValue =
567                 getTypeSettingsProperties().getProperty(columnId);
568 
569             columnValue = StringUtil.remove(columnValue, portletId);
570 
571             getTypeSettingsProperties().setProperty(columnId, columnValue);
572         }
573 
574         if (cleanUp) {
575             removeStatesPortletId(portletId);
576             removeModesPortletId(portletId);
577 
578             try {
579                 onRemoveFromLayout(portletId);
580             }
581             catch (Exception e) {
582                 _log.error("Unable to fire portlet layout listener event", e);
583             }
584         }
585     }
586 
587     public void setPortletIds(String columnId, String portletIds) {
588         getTypeSettingsProperties().setProperty(columnId, portletIds);
589     }
590 
591     public void reorganizePortlets(
592         List<String> newColumns, List<String> oldColumns) {
593 
594         String lastNewColumnId = newColumns.get(newColumns.size() - 1);
595         String lastNewColumnValue =
596             getTypeSettingsProperties().getProperty(lastNewColumnId);
597 
598         Iterator<String> itr = oldColumns.iterator();
599 
600         while (itr.hasNext()) {
601             String oldColumnId = itr.next();
602 
603             if (!newColumns.contains(oldColumnId)) {
604                 String oldColumnValue = getTypeSettingsProperties().remove(
605                     oldColumnId);
606 
607                 String[] portletIds = StringUtil.split(oldColumnValue);
608 
609                 for (int i = 0; i < portletIds.length; i++) {
610                     lastNewColumnValue =
611                         StringUtil.add(lastNewColumnValue, portletIds[i]);
612                 }
613             }
614         }
615 
616         getTypeSettingsProperties().setProperty(
617             lastNewColumnId, lastNewColumnValue);
618     }
619 
620     // Maximized state
621 
622     public String getStateMax() {
623         return getTypeSettingsProperties().getProperty(STATE_MAX);
624     }
625 
626     public void setStateMax(String stateMax) {
627         getTypeSettingsProperties().setProperty(STATE_MAX, stateMax);
628     }
629 
630     public boolean hasStateMax() {
631         String[] stateMax = StringUtil.split(getStateMax());
632 
633         if (stateMax.length > 0) {
634             return true;
635         }
636         else {
637             return false;
638         }
639     }
640 
641     public void addStateMaxPortletId(String portletId) {
642         removeStatesPortletId(portletId);
643         //setStateMax(StringUtil.add(getStateMax(), portletId));
644         setStateMax(StringUtil.add(StringPool.BLANK, portletId));
645     }
646 
647     public String getStateMaxPortletId() {
648         String[] stateMax = StringUtil.split(getStateMax());
649 
650         if (stateMax.length > 0) {
651             return stateMax[0];
652         }
653         else {
654             return StringPool.BLANK;
655         }
656     }
657 
658     public boolean hasStateMaxPortletId(String portletId) {
659         if (StringUtil.contains(getStateMax(), portletId)) {
660             return true;
661         }
662         else {
663             return false;
664         }
665     }
666 
667     public void removeStateMaxPortletId(String portletId) {
668         setStateMax(StringUtil.remove(getStateMax(), portletId));
669     }
670 
671     // Minimized state
672 
673     public String getStateMin() {
674         return getTypeSettingsProperties().getProperty(STATE_MIN);
675     }
676 
677     public void setStateMin(String stateMin) {
678         getTypeSettingsProperties().setProperty(STATE_MIN, stateMin);
679     }
680 
681     public boolean hasStateMin() {
682         String[] stateMin = StringUtil.split(getStateMin());
683 
684         if (stateMin.length > 0) {
685             return true;
686         }
687         else {
688             return false;
689         }
690     }
691 
692     public void addStateMinPortletId(String portletId) {
693         removeStateMaxPortletId(portletId);
694         setStateMin(StringUtil.add(getStateMin(), portletId));
695     }
696 
697     public boolean hasStateMinPortletId(String portletId) {
698         if (StringUtil.contains(getStateMin(), portletId)) {
699             return true;
700         }
701         else {
702             return false;
703         }
704     }
705 
706     public void removeStateMinPortletId(String portletId) {
707         setStateMin(StringUtil.remove(getStateMin(), portletId));
708     }
709 
710     // Normal state
711 
712     public boolean hasStateNormalPortletId(String portletId) {
713         if (hasStateMaxPortletId(portletId) ||
714             hasStateMinPortletId(portletId)) {
715 
716             return false;
717         }
718         else {
719             return true;
720         }
721     }
722 
723     // All states
724 
725     public void resetStates() {
726         setStateMax(StringPool.BLANK);
727         setStateMin(StringPool.BLANK);
728     }
729 
730     public void removeStatesPortletId(String portletId) {
731         removeStateMaxPortletId(portletId);
732         removeStateMinPortletId(portletId);
733     }
734 
735     // About mode
736 
737     public String getModeAbout() {
738         return getTypeSettingsProperties().getProperty(MODE_ABOUT);
739     }
740 
741     public void setModeAbout(String modeAbout) {
742         getTypeSettingsProperties().setProperty(MODE_ABOUT, modeAbout);
743     }
744 
745     public void addModeAboutPortletId(String portletId) {
746         removeModesPortletId(portletId);
747         setModeAbout(StringUtil.add(getModeAbout(), portletId));
748     }
749 
750     public boolean hasModeAboutPortletId(String portletId) {
751         return StringUtil.contains(getModeAbout(), portletId);
752     }
753 
754     public void removeModeAboutPortletId(String portletId) {
755         setModeAbout(StringUtil.remove(getModeAbout(), portletId));
756     }
757 
758     // Config mode
759 
760     public String getModeConfig() {
761         return getTypeSettingsProperties().getProperty(MODE_CONFIG);
762     }
763 
764     public void setModeConfig(String modeConfig) {
765         getTypeSettingsProperties().setProperty(MODE_CONFIG, modeConfig);
766     }
767 
768     public void addModeConfigPortletId(String portletId) {
769         removeModesPortletId(portletId);
770         setModeConfig(StringUtil.add(getModeConfig(), portletId));
771     }
772 
773     public boolean hasModeConfigPortletId(String portletId) {
774         return StringUtil.contains(getModeConfig(), portletId);
775     }
776 
777     public void removeModeConfigPortletId(String portletId) {
778         setModeConfig(StringUtil.remove(getModeConfig(), portletId));
779     }
780 
781     // Edit mode
782 
783     public String getModeEdit() {
784         return getTypeSettingsProperties().getProperty(MODE_EDIT);
785     }
786 
787     public void setModeEdit(String modeEdit) {
788         getTypeSettingsProperties().setProperty(MODE_EDIT, modeEdit);
789     }
790 
791     public void addModeEditPortletId(String portletId) {
792         removeModesPortletId(portletId);
793         setModeEdit(StringUtil.add(getModeEdit(), portletId));
794     }
795 
796     public boolean hasModeEditPortletId(String portletId) {
797         return StringUtil.contains(getModeEdit(), portletId);
798     }
799 
800     public void removeModeEditPortletId(String portletId) {
801         setModeEdit(StringUtil.remove(getModeEdit(), portletId));
802     }
803 
804     // Edit defaults mode
805 
806     public String getModeEditDefaults() {
807         return getTypeSettingsProperties().getProperty(MODE_EDIT_DEFAULTS);
808     }
809 
810     public void setModeEditDefaults(String modeEditDefaults) {
811         getTypeSettingsProperties().setProperty(
812             MODE_EDIT_DEFAULTS, modeEditDefaults);
813     }
814 
815     public void addModeEditDefaultsPortletId(String portletId) {
816         removeModesPortletId(portletId);
817         setModeEditDefaults(StringUtil.add(getModeEditDefaults(), portletId));
818     }
819 
820     public boolean hasModeEditDefaultsPortletId(String portletId) {
821         return StringUtil.contains(getModeEditDefaults(), portletId);
822     }
823 
824     public void removeModeEditDefaultsPortletId(String portletId) {
825         setModeEditDefaults(
826             StringUtil.remove(getModeEditDefaults(), portletId));
827     }
828 
829     // Edit guest mode
830 
831     public String getModeEditGuest() {
832         return getTypeSettingsProperties().getProperty(MODE_EDIT_GUEST);
833     }
834 
835     public void setModeEditGuest(String modeEditGuest) {
836         getTypeSettingsProperties().setProperty(MODE_EDIT_GUEST, modeEditGuest);
837     }
838 
839     public void addModeEditGuestPortletId(String portletId) {
840         removeModesPortletId(portletId);
841         setModeEditGuest(StringUtil.add(getModeEditGuest(), portletId));
842     }
843 
844     public boolean hasModeEditGuestPortletId(String portletId) {
845         return StringUtil.contains(getModeEditGuest(), portletId);
846     }
847 
848     public void removeModeEditGuestPortletId(String portletId) {
849         setModeEditGuest(StringUtil.remove(getModeEditGuest(), portletId));
850     }
851 
852     // Help mode
853 
854     public String getModeHelp() {
855         return getTypeSettingsProperties().getProperty(MODE_HELP);
856     }
857 
858     public void setModeHelp(String modeHelp) {
859         getTypeSettingsProperties().setProperty(MODE_HELP, modeHelp);
860     }
861 
862     public void addModeHelpPortletId(String portletId) {
863         removeModesPortletId(portletId);
864         setModeHelp(StringUtil.add(getModeHelp(), portletId));
865     }
866 
867     public boolean hasModeHelpPortletId(String portletId) {
868         return StringUtil.contains(getModeHelp(), portletId);
869     }
870 
871     public void removeModeHelpPortletId(String portletId) {
872         setModeHelp(StringUtil.remove(getModeHelp(), portletId));
873     }
874 
875     // Preview mode
876 
877     public String getModePreview() {
878         return getTypeSettingsProperties().getProperty(MODE_PREVIEW);
879     }
880 
881     public void setModePreview(String modePreview) {
882         getTypeSettingsProperties().setProperty(MODE_PREVIEW, modePreview);
883     }
884 
885     public void addModePreviewPortletId(String portletId) {
886         removeModesPortletId(portletId);
887         setModePreview(StringUtil.add(getModePreview(), portletId));
888     }
889 
890     public boolean hasModePreviewPortletId(String portletId) {
891         return StringUtil.contains(getModePreview(), portletId);
892     }
893 
894     public void removeModePreviewPortletId(String portletId) {
895         setModePreview(StringUtil.remove(getModePreview(), portletId));
896     }
897 
898     // Print mode
899 
900     public String getModePrint() {
901         return getTypeSettingsProperties().getProperty(MODE_PRINT);
902     }
903 
904     public void setModePrint(String modePrint) {
905         getTypeSettingsProperties().setProperty(MODE_PRINT, modePrint);
906     }
907 
908     public void addModePrintPortletId(String portletId) {
909         removeModesPortletId(portletId);
910         setModePrint(StringUtil.add(getModePrint(), portletId));
911     }
912 
913     public boolean hasModePrintPortletId(String portletId) {
914         return StringUtil.contains(getModePrint(), portletId);
915     }
916 
917     public void removeModePrintPortletId(String portletId) {
918         setModePrint(StringUtil.remove(getModePrint(), portletId));
919     }
920 
921     // View mode
922 
923     public boolean hasModeViewPortletId(String portletId) {
924         if (hasModeAboutPortletId(portletId) ||
925             hasModeConfigPortletId(portletId) ||
926             hasModeEditPortletId(portletId) ||
927             hasModeEditDefaultsPortletId(portletId) ||
928             hasModeEditGuestPortletId(portletId) ||
929             hasModeHelpPortletId(portletId) ||
930             hasModePreviewPortletId(portletId) ||
931             hasModePrintPortletId(portletId)) {
932 
933             return false;
934         }
935         else {
936             return true;
937         }
938     }
939 
940     // All modes
941 
942     public void resetModes() {
943         setModeAbout(StringPool.BLANK);
944         setModeConfig(StringPool.BLANK);
945         setModeEdit(StringPool.BLANK);
946         setModeEditDefaults(StringPool.BLANK);
947         setModeEditGuest(StringPool.BLANK);
948         setModeHelp(StringPool.BLANK);
949         setModePreview(StringPool.BLANK);
950         setModePrint(StringPool.BLANK);
951     }
952 
953     public void removeModesPortletId(String portletId) {
954         removeModeAboutPortletId(portletId);
955         removeModeConfigPortletId(portletId);
956         removeModeEditPortletId(portletId);
957         removeModeEditDefaultsPortletId(portletId);
958         removeModeEditGuestPortletId(portletId);
959         removeModeHelpPortletId(portletId);
960         removeModePreviewPortletId(portletId);
961         removeModePrintPortletId(portletId);
962     }
963 
964     public void removeNestedColumns(String portletId) {
965         UnicodeProperties props = getTypeSettingsProperties();
966 
967         UnicodeProperties newProps = new UnicodeProperties();
968 
969         for (String key : props.keySet()) {
970             if (!key.startsWith(portletId)) {
971                 newProps.setProperty(key, props.getProperty(key));
972             }
973         }
974 
975         getLayout().setTypeSettingsProperties(newProps);
976 
977         String nestedColumnIds = GetterUtil.getString(
978             getTypeSettingsProperties().getProperty(NESTED_COLUMN_IDS));
979 
980         String[] nestedColumnIdsArray = ArrayUtil.removeByPrefix(
981             StringUtil.split(nestedColumnIds), portletId);
982 
983         getTypeSettingsProperties().setProperty(
984             NESTED_COLUMN_IDS, StringUtil.merge(nestedColumnIdsArray));
985     }
986 
987     protected void addNestedColumn(String columnId) {
988         String nestedColumnIds = getTypeSettingsProperties().getProperty(
989             NESTED_COLUMN_IDS, StringPool.BLANK);
990 
991         if (nestedColumnIds.indexOf(columnId) == -1) {
992             nestedColumnIds = StringUtil.add(nestedColumnIds, columnId);
993 
994             getTypeSettingsProperties().setProperty(
995                 NESTED_COLUMN_IDS, nestedColumnIds);
996         }
997     }
998 
999     protected List<String> getColumns() {
1000        LayoutTemplate layoutTemplate = getLayoutTemplate();
1001
1002        List<String> columns = new ArrayList<String>();
1003
1004        columns.addAll(layoutTemplate.getColumns());
1005        columns.addAll(getNestedColumns());
1006
1007        return columns;
1008    }
1009
1010    protected List<String> getNestedColumns() {
1011        String nestedColumnIds = getTypeSettingsProperties().getProperty(
1012            NESTED_COLUMN_IDS);
1013
1014        return ListUtil.fromArray(StringUtil.split(nestedColumnIds));
1015    }
1016
1017    protected String[] getStaticPortletIds(String position) {
1018        Layout layout = getLayout();
1019
1020        String selector1 = StringPool.BLANK;
1021
1022        Group group = layout.getGroup();
1023
1024        if (group.isUser()) {
1025            selector1 = STATIC_PORTLET_USER_SELECTOR;
1026        }
1027        else if (group.isCommunity()) {
1028            selector1 = STATIC_PORTLET_COMMUNITY_SELECTOR;
1029        }
1030        else if (group.isOrganization()) {
1031            selector1 = STATIC_PORTLET_ORGANIZATION_SELECTOR;
1032        }
1033
1034        String selector2 = layout.getFriendlyURL();
1035
1036        String[] portletIds = PropsUtil.getArray(
1037            position, new Filter(selector1, selector2));
1038
1039        for (int i = 0; i < portletIds.length; i++) {
1040            portletIds[i] = JS.getSafeName(portletIds[i]);
1041        }
1042
1043        return portletIds;
1044    }
1045
1046    protected List<Portlet> getStaticPortlets(String position)
1047        throws SystemException {
1048
1049        String[] portletIds = getStaticPortletIds(position);
1050
1051        List<Portlet> portlets = new ArrayList<Portlet>();
1052
1053        for (int i = 0; i < portletIds.length; i++) {
1054            String portletId = portletIds[i];
1055
1056            if (hasNonstaticPortletId(portletId)) {
1057                continue;
1058            }
1059
1060            Portlet portlet = PortletLocalServiceUtil.getPortletById(
1061                getLayout().getCompanyId(), portletId);
1062
1063            if (portlet != null) {
1064                Portlet staticPortlet = portlet;
1065
1066                if (portlet.isInstanceable()) {
1067
1068                    // Instanceable portlets do not need to be cloned because
1069                    // they are already cloned. See the method getPortletById in
1070                    // the class PortletLocalServiceImpl and how it references
1071                    // the method getClonedInstance in the class PortletImpl.
1072
1073                }
1074                else {
1075                    staticPortlet = (Portlet)staticPortlet.clone();
1076                }
1077
1078                staticPortlet.setStatic(true);
1079
1080                if (position.startsWith("layout.static.portlets.start")) {
1081                    staticPortlet.setStaticStart(true);
1082                }
1083
1084                portlets.add(staticPortlet);
1085            }
1086        }
1087
1088        return portlets;
1089    }
1090
1091    protected boolean hasNonstaticPortletId(String portletId) {
1092        LayoutTemplate layoutTemplate = getLayoutTemplate();
1093
1094        List<String> columns = layoutTemplate.getColumns();
1095
1096        for (int i = 0; i < columns.size(); i++) {
1097            String columnId = columns.get(i);
1098
1099            if (hasNonstaticPortletId(columnId, portletId)) {
1100                return true;
1101            }
1102        }
1103
1104        return false;
1105    }
1106
1107    protected boolean hasNonstaticPortletId(String columnId, String portletId) {
1108        String columnValue = getTypeSettingsProperties().getProperty(columnId);
1109
1110        if (StringUtil.contains(columnValue, portletId)) {
1111            return true;
1112        }
1113        else {
1114            return false;
1115        }
1116    }
1117
1118    /*protected boolean hasStaticPortletId(String portletId) {
1119        LayoutTemplate layoutTemplate = getLayoutTemplate();
1120
1121        List columns = layoutTemplate.getColumns();
1122
1123        for (int i = 0; i < columns.size(); i++) {
1124            String columnId = (String)columns.get(i);
1125
1126            if (hasStaticPortletId(columnId, portletId)) {
1127                return true;
1128            }
1129        }
1130
1131        return false;
1132    }*/
1133
1134    protected boolean hasStaticPortletId(String columnId, String portletId) {
1135        String[] staticPortletIdsStart = getStaticPortletIds(
1136            PropsKeys.LAYOUT_STATIC_PORTLETS_START + columnId);
1137
1138        String[] staticPortletIdsEnd = getStaticPortletIds(
1139            PropsKeys.LAYOUT_STATIC_PORTLETS_END + columnId);
1140
1141        String[] staticPortletIds = ArrayUtil.append(
1142            staticPortletIdsStart, staticPortletIdsEnd);
1143
1144        for (int i = 0; i < staticPortletIds.length; i++) {
1145            String staticPortletId = staticPortletIds[i];
1146
1147            if (staticPortletId.equals(portletId)) {
1148                return true;
1149            }
1150        }
1151
1152        return false;
1153    }
1154
1155    protected void onRemoveFromLayout(String portletId) throws SystemException {
1156        Portlet portlet = PortletLocalServiceUtil.getPortletById(
1157            getLayout().getCompanyId(), portletId);
1158
1159        if (portlet == null) {
1160            return;
1161        }
1162
1163        if (portlet.getRootPortletId().equals(PortletKeys.NESTED_PORTLETS)) {
1164            UnicodeProperties props = getTypeSettingsProperties();
1165
1166            for (String key : props.keySet()) {
1167                if (key.startsWith(portlet.getPortletId())) {
1168                    String portletIds = props.getProperty(key);
1169
1170                    String[] portletIdsArray = StringUtil.split(portletIds);
1171
1172                    for (int i = 0; i < portletIdsArray.length; i++) {
1173                        onRemoveFromLayout(portletIdsArray[i]);
1174                    }
1175                }
1176            }
1177
1178            removeNestedColumns(portletId);
1179        }
1180
1181        if (_enablePortletLayoutListener) {
1182            PortletLayoutListener portletLayoutListener =
1183                portlet.getPortletLayoutListener();
1184
1185            long plid = getLayout().getPlid();
1186
1187            if ((portletLayoutListener != null)) {
1188                portletLayoutListener.onRemoveFromLayout(portletId, plid);
1189            }
1190        }
1191
1192        deletePortletSetup(portletId);
1193    }
1194
1195    protected void deletePortletSetup(String portletId) {
1196        try {
1197            List<PortletPreferences> list =
1198                PortletPreferencesLocalServiceUtil.getPortletPreferences(
1199                    getLayout().getPlid(), portletId);
1200
1201            for (int i = 0; i < list.size(); i++) {
1202                PortletPreferences portletPreferences = list.get(i);
1203
1204                PortletPreferencesLocalServiceUtil.deletePortletPreferences(
1205                    portletPreferences.getPortletPreferencesId());
1206            }
1207        }
1208        catch (Exception e) {
1209            _log.error(e, e);
1210        }
1211    }
1212
1213    private static Log _log =
1214         LogFactoryUtil.getLog(LayoutTypePortletImpl.class);
1215
1216    private boolean _enablePortletLayoutListener = true;
1217
1218}