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