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