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