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.service.impl;
16  
17  import com.liferay.portal.LayoutFriendlyURLException;
18  import com.liferay.portal.LayoutHiddenException;
19  import com.liferay.portal.LayoutNameException;
20  import com.liferay.portal.LayoutParentLayoutIdException;
21  import com.liferay.portal.LayoutTypeException;
22  import com.liferay.portal.NoSuchLayoutException;
23  import com.liferay.portal.PortalException;
24  import com.liferay.portal.RequiredLayoutException;
25  import com.liferay.portal.SystemException;
26  import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayInputStream;
27  import com.liferay.portal.kernel.language.LanguageUtil;
28  import com.liferay.portal.kernel.log.Log;
29  import com.liferay.portal.kernel.log.LogFactoryUtil;
30  import com.liferay.portal.kernel.util.FileUtil;
31  import com.liferay.portal.kernel.util.GetterUtil;
32  import com.liferay.portal.kernel.util.ListUtil;
33  import com.liferay.portal.kernel.util.LocaleUtil;
34  import com.liferay.portal.kernel.util.StringBundler;
35  import com.liferay.portal.kernel.util.StringPool;
36  import com.liferay.portal.kernel.util.Validator;
37  import com.liferay.portal.lar.LayoutExporter;
38  import com.liferay.portal.lar.LayoutImporter;
39  import com.liferay.portal.lar.PortletExporter;
40  import com.liferay.portal.lar.PortletImporter;
41  import com.liferay.portal.model.Layout;
42  import com.liferay.portal.model.LayoutConstants;
43  import com.liferay.portal.model.LayoutReference;
44  import com.liferay.portal.model.LayoutTypePortlet;
45  import com.liferay.portal.model.PortletConstants;
46  import com.liferay.portal.model.Resource;
47  import com.liferay.portal.model.ResourceConstants;
48  import com.liferay.portal.model.User;
49  import com.liferay.portal.model.impl.LayoutImpl;
50  import com.liferay.portal.service.base.LayoutLocalServiceBaseImpl;
51  import com.liferay.portal.service.persistence.BatchSessionUtil;
52  import com.liferay.portal.util.FriendlyURLNormalizer;
53  import com.liferay.portal.util.PortalUtil;
54  import com.liferay.portal.util.PortletKeys;
55  import com.liferay.portal.util.PropsValues;
56  import com.liferay.portal.util.comparator.LayoutComparator;
57  import com.liferay.portal.util.comparator.LayoutPriorityComparator;
58  import com.liferay.portlet.documentlibrary.DuplicateFolderNameException;
59  import com.liferay.portlet.documentlibrary.NoSuchFolderException;
60  import com.liferay.portlet.documentlibrary.model.DLFolder;
61  import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
62  
63  import java.io.File;
64  import java.io.IOException;
65  import java.io.InputStream;
66  
67  import java.util.ArrayList;
68  import java.util.Date;
69  import java.util.HashMap;
70  import java.util.HashSet;
71  import java.util.LinkedHashSet;
72  import java.util.List;
73  import java.util.Locale;
74  import java.util.Map;
75  import java.util.Set;
76  
77  /**
78   * <a href="LayoutLocalServiceImpl.java.html"><b><i>View Source</i></b></a>
79   *
80   * @author Brian Wing Shun Chan
81   * @author Joel Kozikowski
82   * @author Charles May
83   * @author Raymond Augé
84   * @author Jorge Ferrer
85   * @author Bruno Farache
86   */
87  public class LayoutLocalServiceImpl extends LayoutLocalServiceBaseImpl {
88  
89      public static String getCounterName(long groupId, boolean privateLayout) {
90          StringBundler sb = new StringBundler();
91  
92          sb.append(Layout.class.getName());
93          sb.append(StringPool.POUND);
94          sb.append(groupId);
95          sb.append(StringPool.POUND);
96          sb.append(privateLayout);
97  
98          return sb.toString();
99      }
100 
101     public Layout addLayout(
102             long userId, long groupId, boolean privateLayout,
103             long parentLayoutId, Map<Locale, String> localeNamesMap,
104             Map<Locale, String> localeTitlesMap, String description,
105             String type, boolean hidden, String friendlyURL)
106         throws PortalException, SystemException {
107 
108         return addLayout(
109             userId, groupId, privateLayout, parentLayoutId, localeNamesMap,
110             localeTitlesMap, description, type, hidden, friendlyURL,
111             DLFolderConstants.DEFAULT_PARENT_FOLDER_ID);
112     }
113 
114     public Layout addLayout(
115             long userId, long groupId, boolean privateLayout,
116             long parentLayoutId, Map<Locale, String> localeNamesMap,
117             Map<Locale, String> localeTitlesMap, String description,
118             String type, boolean hidden, String friendlyURL, long dlFolderId)
119         throws PortalException, SystemException {
120 
121         // Layout
122 
123         User user = userPersistence.findByPrimaryKey(userId);
124         long layoutId = getNextLayoutId(groupId, privateLayout);
125         parentLayoutId = getParentLayoutId(
126             groupId, privateLayout, parentLayoutId);
127         String name = localeNamesMap.get(LocaleUtil.getDefault());
128         friendlyURL = getFriendlyURL(layoutId, friendlyURL);
129         int priority = getNextPriority(groupId, privateLayout, parentLayoutId);
130 
131         validate(
132             groupId, privateLayout, layoutId, parentLayoutId, name, type,
133             hidden, friendlyURL);
134 
135         long plid = counterLocalService.increment();
136 
137         Layout layout = layoutPersistence.create(plid);
138 
139         layout.setGroupId(groupId);
140         layout.setCompanyId(user.getCompanyId());
141         layout.setPrivateLayout(privateLayout);
142         layout.setLayoutId(layoutId);
143         layout.setParentLayoutId(parentLayoutId);
144         layout.setDescription(description);
145         layout.setType(type);
146         layout.setHidden(hidden);
147         layout.setFriendlyURL(friendlyURL);
148         layout.setPriority(priority);
149         layout.setDlFolderId(dlFolderId);
150 
151         setLocalizedAttributes(layout, localeNamesMap, localeTitlesMap);
152 
153         if (type.equals(LayoutConstants.TYPE_PORTLET)) {
154             LayoutTypePortlet layoutTypePortlet =
155                 (LayoutTypePortlet)layout.getLayoutType();
156 
157             layoutTypePortlet.setLayoutTemplateId(
158                 0, PropsValues.LAYOUT_DEFAULT_TEMPLATE_ID, false);
159         }
160 
161         layoutPersistence.update(layout, false);
162 
163         // Resources
164 
165         resourceLocalService.addResources(
166             user.getCompanyId(), groupId, user.getUserId(),
167             Layout.class.getName(), layout.getPlid(), false, true, true);
168 
169         // Layout set
170 
171         layoutSetLocalService.updatePageCount(groupId, privateLayout);
172 
173         // Message boards
174 
175         if (PropsValues.LAYOUT_COMMENTS_ENABLED) {
176             mbMessageLocalService.addDiscussionMessage(
177                 userId, user.getFullName(), Layout.class.getName(), plid);
178         }
179 
180         return layout;
181     }
182 
183     public Layout addLayout(
184             long userId, long groupId, boolean privateLayout,
185             long parentLayoutId, String name, String title, String description,
186             String type, boolean hidden, String friendlyURL)
187         throws PortalException, SystemException {
188 
189         Map<Locale, String> localeNamesMap = new HashMap<Locale, String>();
190 
191         Locale defaultLocale = LocaleUtil.getDefault();
192 
193         localeNamesMap.put(defaultLocale, name);
194 
195         return addLayout(
196             userId, groupId, privateLayout, parentLayoutId, localeNamesMap,
197             new HashMap<Locale, String>(), description, type, hidden,
198             friendlyURL);
199     }
200 
201     public Layout addLayout(
202             long userId, long groupId, boolean privateLayout,
203             long parentLayoutId, String name, String title, String description,
204             String type, boolean hidden, String friendlyURL, long dlFolderId)
205         throws PortalException, SystemException {
206 
207         Map<Locale, String> localeNamesMap = new HashMap<Locale, String>();
208 
209         Locale defaultLocale = LocaleUtil.getDefault();
210 
211         localeNamesMap.put(defaultLocale, name);
212 
213         return addLayout(
214             userId, groupId, privateLayout, parentLayoutId, localeNamesMap,
215             new HashMap<Locale, String>(), description, type, hidden,
216             friendlyURL, dlFolderId);
217     }
218 
219     public void deleteLayout(Layout layout, boolean updateLayoutSet)
220         throws PortalException, SystemException {
221 
222         // Child layouts
223 
224         List<Layout> childLayouts = layoutPersistence.findByG_P_P(
225             layout.getGroupId(), layout.isPrivateLayout(),
226             layout.getLayoutId());
227 
228         for (Layout childLayout : childLayouts) {
229             deleteLayout(childLayout, updateLayoutSet);
230         }
231 
232         // Portlet preferences
233 
234         portletPreferencesLocalService.deletePortletPreferences(
235             PortletKeys.PREFS_OWNER_ID_DEFAULT,
236             PortletKeys.PREFS_OWNER_TYPE_LAYOUT, layout.getPlid());
237 
238         // Tasks
239 
240         tasksProposalLocalService.deleteProposal(
241             Layout.class.getName(), String.valueOf(layout.getPlid()));
242 
243         // Ratings
244 
245         ratingsStatsLocalService.deleteStats(
246             Layout.class.getName(), layout.getPlid());
247 
248         // Message boards
249 
250         mbMessageLocalService.deleteDiscussionMessages(
251             Layout.class.getName(), layout.getPlid());
252 
253         // Journal content searches
254 
255         journalContentSearchLocalService.deleteLayoutContentSearches(
256             layout.getGroupId(), layout.isPrivateLayout(),
257             layout.getLayoutId());
258 
259         // Icon
260 
261         imageLocalService.deleteImage(layout.getIconImageId());
262 
263         // Resources
264 
265         String primKey =
266             layout.getPlid() + PortletConstants.LAYOUT_SEPARATOR + "%";
267 
268         List<Resource> resources = resourceFinder.findByC_P(
269             layout.getCompanyId(), primKey);
270 
271         for (Resource resource : resources) {
272             resourceLocalService.deleteResource(resource);
273         }
274 
275         resourceLocalService.deleteResource(
276             layout.getCompanyId(), Layout.class.getName(),
277             ResourceConstants.SCOPE_INDIVIDUAL, layout.getPlid());
278 
279         // Layout
280 
281         layoutPersistence.remove(layout);
282 
283         // Layout set
284 
285         if (updateLayoutSet) {
286             layoutSetLocalService.updatePageCount(
287                 layout.getGroupId(), layout.isPrivateLayout());
288         }
289     }
290 
291     public void deleteLayout(long plid)
292         throws PortalException, SystemException {
293 
294         Layout layout = layoutPersistence.findByPrimaryKey(plid);
295 
296         deleteLayout(layout, true);
297     }
298 
299     public void deleteLayout(long groupId, boolean privateLayout, long layoutId)
300         throws PortalException, SystemException {
301 
302         Layout layout = layoutPersistence.findByG_P_L(
303             groupId, privateLayout, layoutId);
304 
305         deleteLayout(layout, true);
306     }
307 
308     public void deleteLayouts(long groupId, boolean privateLayout)
309         throws PortalException, SystemException {
310 
311         // Layouts
312 
313         List<Layout> layouts = layoutPersistence.findByG_P_P(
314             groupId, privateLayout, LayoutConstants.DEFAULT_PARENT_LAYOUT_ID);
315 
316         for (Layout layout : layouts) {
317             try {
318                 deleteLayout(layout, false);
319             }
320             catch (NoSuchLayoutException nsle) {
321             }
322         }
323 
324         // Layout set
325 
326         layoutSetLocalService.updatePageCount(groupId, privateLayout);
327 
328         // Counter
329 
330         counterLocalService.reset(getCounterName(groupId, privateLayout));
331     }
332 
333     public byte[] exportLayouts(
334             long groupId, boolean privateLayout, long[] layoutIds,
335             Map<String, String[]> parameterMap, Date startDate, Date endDate)
336         throws PortalException, SystemException {
337 
338         File file = exportLayoutsAsFile(
339             groupId, privateLayout, layoutIds, parameterMap, startDate,
340             endDate);
341 
342         try {
343             return FileUtil.getBytes(file);
344         }
345         catch (IOException ioe) {
346             throw new SystemException(ioe);
347         }
348         finally {
349             file.delete();
350         }
351     }
352 
353     public byte[] exportLayouts(
354             long groupId, boolean privateLayout,
355             Map<String, String[]> parameterMap, Date startDate, Date endDate)
356         throws PortalException, SystemException {
357 
358         return exportLayouts(
359             groupId, privateLayout, null, parameterMap, startDate, endDate);
360     }
361 
362     public File exportLayoutsAsFile(
363             long groupId, boolean privateLayout, long[] layoutIds,
364             Map<String, String[]> parameterMap, Date startDate, Date endDate)
365         throws PortalException, SystemException {
366 
367         LayoutExporter layoutExporter = new LayoutExporter();
368 
369         return layoutExporter.exportLayoutsAsFile(
370             groupId, privateLayout, layoutIds, parameterMap, startDate,
371             endDate);
372     }
373 
374     public byte[] exportPortletInfo(
375             long plid, long groupId, String portletId,
376             Map<String, String[]> parameterMap, Date startDate, Date endDate)
377         throws PortalException, SystemException {
378 
379         File file = exportPortletInfoAsFile(
380             plid, groupId, portletId, parameterMap, startDate, endDate);
381 
382         try {
383             return FileUtil.getBytes(file);
384         }
385         catch (IOException ioe) {
386             throw new SystemException(ioe);
387         }
388         finally {
389             file.delete();
390         }
391     }
392 
393     public File exportPortletInfoAsFile(
394             long plid, long groupId, String portletId,
395             Map<String, String[]> parameterMap, Date startDate, Date endDate)
396         throws PortalException, SystemException {
397 
398         PortletExporter portletExporter = new PortletExporter();
399 
400         return portletExporter.exportPortletInfoAsFile(
401             plid, groupId, portletId, parameterMap, startDate, endDate);
402     }
403 
404     public long getDefaultPlid(long groupId) throws SystemException {
405         if (groupId > 0) {
406             List<Layout> layouts = layoutPersistence.findByGroupId(
407                 groupId, 0, 1);
408 
409             if (layouts.size() > 0) {
410                 Layout layout = layouts.get(0);
411 
412                 return layout.getPlid();
413             }
414         }
415 
416         return LayoutConstants.DEFAULT_PLID;
417     }
418 
419     public long getDefaultPlid(long groupId, boolean privateLayout)
420         throws SystemException {
421 
422         if (groupId > 0) {
423             List<Layout> layouts = layoutPersistence.findByG_P(
424                 groupId, privateLayout, 0, 1);
425 
426             if (layouts.size() > 0) {
427                 Layout layout = layouts.get(0);
428 
429                 return layout.getPlid();
430             }
431         }
432 
433         return LayoutConstants.DEFAULT_PLID;
434     }
435 
436     public long getDefaultPlid(
437             long groupId, boolean privateLayout, String portletId)
438         throws SystemException {
439 
440         if (groupId > 0) {
441             List<Layout> layouts = layoutPersistence.findByG_P(
442                 groupId, privateLayout);
443 
444             for (Layout layout : layouts) {
445                 if (layout.getType().equals(LayoutConstants.TYPE_PORTLET)) {
446                     LayoutTypePortlet layoutTypePortlet =
447                         (LayoutTypePortlet)layout.getLayoutType();
448 
449                     if (layoutTypePortlet.hasPortletId(portletId)) {
450                         return layout.getPlid();
451                     }
452                 }
453             }
454         }
455 
456         return LayoutConstants.DEFAULT_PLID;
457     }
458 
459     public Layout getDLFolderLayout(long dlFolderId)
460         throws PortalException, SystemException {
461 
462         return layoutPersistence.findByDLFolderId(dlFolderId);
463     }
464 
465     public Layout getFriendlyURLLayout(
466             long groupId, boolean privateLayout, String friendlyURL)
467         throws PortalException, SystemException {
468 
469         if (Validator.isNull(friendlyURL)) {
470             throw new NoSuchLayoutException();
471         }
472 
473         friendlyURL = getFriendlyURL(friendlyURL);
474 
475         Layout layout = layoutPersistence.fetchByG_P_F(
476             groupId, privateLayout, friendlyURL);
477 
478         if ((layout == null) &&
479             (friendlyURL.startsWith(StringPool.SLASH))) {
480 
481             long layoutId = GetterUtil.getLong(friendlyURL.substring(1));
482 
483             layout = layoutPersistence.fetchByG_P_L(
484                 groupId, privateLayout, layoutId);
485         }
486 
487         if (layout == null) {
488             throw new NoSuchLayoutException();
489         }
490 
491         return layout;
492     }
493 
494     public Layout getLayout(long plid)
495         throws PortalException, SystemException {
496 
497         return layoutPersistence.findByPrimaryKey(plid);
498     }
499 
500     public Layout getLayout(long groupId, boolean privateLayout, long layoutId)
501         throws PortalException, SystemException {
502 
503         return layoutPersistence.findByG_P_L(groupId, privateLayout, layoutId);
504     }
505 
506     public Layout getLayoutByIconImageId(long iconImageId)
507         throws PortalException, SystemException {
508 
509         return layoutPersistence.findByIconImageId(iconImageId);
510     }
511 
512     public List<Layout> getLayouts(long groupId, boolean privateLayout)
513         throws SystemException {
514 
515         return layoutPersistence.findByG_P(groupId, privateLayout);
516     }
517 
518     public List<Layout> getLayouts(
519             long groupId, boolean privateLayout, long parentLayoutId)
520         throws SystemException {
521 
522         return layoutPersistence.findByG_P_P(
523             groupId, privateLayout, parentLayoutId);
524     }
525 
526     public List<Layout> getLayouts(
527             long groupId, boolean privateLayout, long parentLayoutId, int start,
528             int end)
529         throws SystemException {
530 
531         return layoutPersistence.findByG_P_P(
532             groupId, privateLayout, parentLayoutId, start, end);
533     }
534 
535     public List<Layout> getLayouts(
536             long groupId, boolean privateLayout, long[] layoutIds)
537         throws PortalException, SystemException {
538 
539         List<Layout> layouts = new ArrayList<Layout>();
540 
541         for (long layoutId : layoutIds) {
542             Layout layout = getLayout(groupId, privateLayout, layoutId);
543 
544             layouts.add(layout);
545         }
546 
547         return layouts;
548     }
549 
550     public List<Layout> getLayouts(
551             long groupId, boolean privateLayout, String type)
552         throws SystemException {
553 
554         return layoutPersistence.findByG_P_T(groupId, privateLayout, type);
555     }
556 
557     public LayoutReference[] getLayouts(
558             long companyId, String portletId, String prefsKey,
559             String prefsValue)
560         throws SystemException {
561 
562         List<LayoutReference> layoutReferences = layoutFinder.findByC_P_P(
563             companyId, portletId, prefsKey, prefsValue);
564 
565         return layoutReferences.toArray(
566             new LayoutReference[layoutReferences.size()]);
567     }
568 
569     public long getNextLayoutId(long groupId, boolean privateLayout)
570         throws SystemException {
571 
572         long nextLayoutId = counterLocalService.increment(
573             getCounterName(groupId, privateLayout));
574 
575         if (nextLayoutId == 1) {
576             List<Layout> layouts = layoutPersistence.findByG_P(
577                 groupId, privateLayout, 0, 1, new LayoutComparator());
578 
579             if (!layouts.isEmpty()) {
580                 Layout layout = layouts.get(0);
581 
582                 nextLayoutId = layout.getLayoutId() + 1;
583 
584                 counterLocalService.reset(
585                     getCounterName(groupId, privateLayout),
586                     layout.getLayoutId());
587             }
588         }
589 
590         return nextLayoutId;
591     }
592 
593     public List<Layout> getNullFriendlyURLLayouts() throws SystemException {
594         return layoutFinder.findByNullFriendlyURL();
595     }
596 
597     public void importLayouts(
598             long userId, long groupId, boolean privateLayout,
599             Map<String, String[]> parameterMap, byte[] bytes)
600         throws PortalException, SystemException {
601 
602         importLayouts(
603             userId, groupId, privateLayout, parameterMap,
604             new UnsyncByteArrayInputStream(bytes));
605     }
606 
607     public void importLayouts(
608             long userId, long groupId, boolean privateLayout,
609             Map<String, String[]> parameterMap, File file)
610         throws PortalException, SystemException {
611 
612         BatchSessionUtil.setEnabled(true);
613 
614         try {
615             LayoutImporter layoutImporter = new LayoutImporter();
616 
617             layoutImporter.importLayouts(
618                 userId, groupId, privateLayout, parameterMap, file);
619         }
620         finally {
621             BatchSessionUtil.setEnabled(false);
622         }
623     }
624 
625     public void importLayouts(
626             long userId, long groupId, boolean privateLayout,
627             Map<String, String[]> parameterMap, InputStream is)
628         throws PortalException, SystemException {
629 
630         try {
631             File file = FileUtil.createTempFile("lar");
632 
633             FileUtil.write(file, is);
634 
635             importLayouts(userId, groupId, privateLayout, parameterMap, file);
636         }
637         catch (IOException e) {
638             throw new SystemException(e);
639         }
640     }
641 
642     public void importPortletInfo(
643             long userId, long plid, long groupId, String portletId,
644             Map<String, String[]> parameterMap, File file)
645         throws PortalException, SystemException {
646 
647         BatchSessionUtil.setEnabled(true);
648 
649         try {
650             PortletImporter portletImporter = new PortletImporter();
651 
652             portletImporter.importPortletInfo(
653                 userId, plid, groupId, portletId, parameterMap, file);
654         }
655         finally {
656             BatchSessionUtil.setEnabled(false);
657         }
658     }
659 
660     public void importPortletInfo(
661             long userId, long plid, long groupId, String portletId,
662             Map<String, String[]> parameterMap, InputStream is)
663         throws PortalException, SystemException {
664 
665         try {
666             File file = FileUtil.createTempFile("lar");
667 
668             FileUtil.write(file, is);
669 
670             importPortletInfo(
671                 userId, plid, groupId, portletId, parameterMap, file);
672         }
673         catch (IOException e) {
674             throw new SystemException(e);
675         }
676     }
677 
678     public void setLayouts(
679             long groupId, boolean privateLayout, long parentLayoutId,
680             long[] layoutIds)
681         throws PortalException, SystemException {
682 
683         if (layoutIds == null) {
684             return;
685         }
686 
687         if (parentLayoutId == LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
688             if (layoutIds.length < 1) {
689                 throw new RequiredLayoutException(
690                     RequiredLayoutException.AT_LEAST_ONE);
691             }
692 
693             Layout layout = layoutPersistence.findByG_P_L(
694                 groupId, privateLayout, layoutIds[0]);
695 
696             if (!layout.getType().equals(LayoutConstants.TYPE_PORTLET)) {
697                 throw new RequiredLayoutException(
698                     RequiredLayoutException.FIRST_LAYOUT_TYPE);
699             }
700 
701             if (layout.isHidden()) {
702                 throw new RequiredLayoutException(
703                     RequiredLayoutException.FIRST_LAYOUT_HIDDEN);
704             }
705         }
706 
707         Set<Long> layoutIdsSet = new LinkedHashSet<Long>();
708 
709         for (int i = 0; i < layoutIds.length; i++) {
710             layoutIdsSet.add(layoutIds[i]);
711         }
712 
713         Set<Long> newLayoutIdsSet = new HashSet<Long>();
714 
715         List<Layout> layouts = layoutPersistence.findByG_P_P(
716             groupId, privateLayout, parentLayoutId);
717 
718         for (Layout layout : layouts) {
719             if (!layoutIdsSet.contains(layout.getLayoutId())) {
720                 deleteLayout(layout, true);
721             }
722             else {
723                 newLayoutIdsSet.add(layout.getLayoutId());
724             }
725         }
726 
727         int priority = 0;
728 
729         for (long layoutId : layoutIdsSet) {
730             Layout layout = layoutPersistence.findByG_P_L(
731                 groupId, privateLayout, layoutId);
732 
733             layout.setPriority(priority++);
734 
735             layoutPersistence.update(layout, false);
736         }
737 
738         layoutSetLocalService.updatePageCount(groupId, privateLayout);
739     }
740 
741     public Layout updateFriendlyURL(long plid, String friendlyURL)
742         throws PortalException, SystemException {
743 
744         Layout layout = layoutPersistence.findByPrimaryKey(plid);
745 
746         friendlyURL = getFriendlyURL(layout.getLayoutId(), friendlyURL);
747 
748         validateFriendlyURL(
749             layout.getGroupId(), layout.isPrivateLayout(), layout.getLayoutId(),
750             friendlyURL);
751 
752         layout.setFriendlyURL(friendlyURL);
753 
754         layoutPersistence.update(layout, false);
755 
756         return layout;
757     }
758 
759     public Layout updateLayout(
760             long groupId, boolean privateLayout, long layoutId,
761             long parentLayoutId, Map<Locale, String> localeNamesMap,
762             Map<Locale, String> localeTitlesMap, String description,
763             String type, boolean hidden, String friendlyURL)
764         throws PortalException, SystemException {
765 
766         return updateLayout(
767             groupId, privateLayout, layoutId, parentLayoutId, localeNamesMap,
768             localeTitlesMap, description, type, hidden, friendlyURL, null,
769             null);
770     }
771 
772     public Layout updateLayout(
773             long groupId, boolean privateLayout, long layoutId,
774             long parentLayoutId, Map<Locale, String> localeNamesMap,
775             Map<Locale, String> localeTitlesMap, String description,
776             String type, boolean hidden, String friendlyURL, Boolean iconImage,
777             byte[] iconBytes)
778         throws PortalException, SystemException {
779 
780         // Layout
781 
782         parentLayoutId = getParentLayoutId(
783             groupId, privateLayout, parentLayoutId);
784         String name = localeNamesMap.get(LocaleUtil.getDefault());
785         friendlyURL = getFriendlyURL(layoutId, friendlyURL);
786 
787         validate(
788             groupId, privateLayout, layoutId, parentLayoutId, name, type,
789             hidden, friendlyURL);
790 
791         validateParentLayoutId(
792             groupId, privateLayout, layoutId, parentLayoutId);
793 
794         Layout layout = layoutPersistence.findByG_P_L(
795             groupId, privateLayout, layoutId);
796 
797         if (parentLayoutId != layout.getParentLayoutId()) {
798             layout.setPriority(
799                 getNextPriority(groupId, privateLayout, parentLayoutId));
800         }
801 
802         layout.setParentLayoutId(parentLayoutId);
803         layout.setDescription(description);
804         layout.setType(type);
805         layout.setHidden(hidden);
806         layout.setFriendlyURL(friendlyURL);
807 
808         setLocalizedAttributes(layout, localeNamesMap, localeTitlesMap);
809 
810         if (iconImage != null) {
811             layout.setIconImage(iconImage.booleanValue());
812 
813             if (iconImage.booleanValue()) {
814                 long iconImageId = layout.getIconImageId();
815 
816                 if (iconImageId <= 0) {
817                     iconImageId = counterLocalService.increment();
818 
819                     layout.setIconImageId(iconImageId);
820                 }
821             }
822         }
823 
824         layoutPersistence.update(layout, false);
825 
826         // Icon
827 
828         if (iconImage != null) {
829             if (!iconImage.booleanValue()) {
830                 imageLocalService.deleteImage(layout.getIconImageId());
831             }
832             else if ((iconBytes != null) && (iconBytes.length > 0)) {
833                 imageLocalService.updateImage(
834                     layout.getIconImageId(), iconBytes);
835             }
836         }
837 
838         try {
839             if (layout.getDlFolderId() > 0) {
840                 DLFolder folder = dlFolderLocalService.getFolder(
841                     layout.getDlFolderId());
842 
843                 if (!name.equals(folder.getName())) {
844                     dlFolderLocalService.updateFolder(
845                         folder.getFolderId(), folder.getParentFolderId(), name,
846                         folder.getDescription());
847                 }
848             }
849         }
850         catch (DuplicateFolderNameException dfne) {
851             if (_log.isDebugEnabled()) {
852                 _log.debug(dfne);
853             }
854         }
855         catch (NoSuchFolderException nsfe) {
856         }
857 
858         return layout;
859     }
860 
861     public Layout updateLayout(
862             long groupId, boolean privateLayout, long layoutId,
863             String typeSettings)
864         throws PortalException, SystemException {
865 
866         Layout layout = layoutPersistence.findByG_P_L(
867             groupId, privateLayout, layoutId);
868 
869         layout.setTypeSettings(typeSettings);
870 
871         layoutPersistence.update(layout, false);
872 
873         return layout;
874     }
875 
876     public Layout updateLookAndFeel(
877             long groupId, boolean privateLayout, long layoutId, String themeId,
878             String colorSchemeId, String css, boolean wapTheme)
879         throws PortalException, SystemException {
880 
881         Layout layout = layoutPersistence.findByG_P_L(
882             groupId, privateLayout, layoutId);
883 
884         if (wapTheme) {
885             layout.setWapThemeId(themeId);
886             layout.setWapColorSchemeId(colorSchemeId);
887         }
888         else {
889             layout.setThemeId(themeId);
890             layout.setColorSchemeId(colorSchemeId);
891             layout.setCss(css);
892         }
893 
894         layoutPersistence.update(layout, false);
895 
896         return layout;
897     }
898 
899     public Layout updateName(Layout layout, String name, String languageId)
900         throws PortalException, SystemException {
901 
902         validateName(name, languageId);
903 
904         layout.setName(name, LocaleUtil.fromLanguageId(languageId));
905 
906         layoutPersistence.update(layout, false);
907 
908         try {
909             if (layout.getDlFolderId() > 0) {
910                 DLFolder folder = dlFolderLocalService.getFolder(
911                     layout.getDlFolderId());
912 
913                 dlFolderLocalService.updateFolder(
914                     folder.getFolderId(), folder.getParentFolderId(),
915                     layout.getName(LocaleUtil.getDefault()),
916                     folder.getDescription());
917             }
918         }
919         catch (NoSuchFolderException nsfe) {
920         }
921 
922         return layout;
923     }
924 
925     public Layout updateName(
926             long groupId, boolean privateLayout, long layoutId, String name,
927             String languageId)
928         throws PortalException, SystemException {
929 
930         Layout layout = layoutPersistence.findByG_P_L(
931             groupId, privateLayout, layoutId);
932 
933         return updateName(layout, name, languageId);
934     }
935 
936     public Layout updateName(long plid, String name, String languageId)
937         throws PortalException, SystemException {
938 
939         Layout layout = layoutPersistence.findByPrimaryKey(plid);
940 
941         return updateName(layout, name, languageId);
942     }
943 
944     public Layout updateParentLayoutId(
945             long groupId, boolean privateLayout, long layoutId,
946             long parentLayoutId)
947         throws PortalException, SystemException {
948 
949         parentLayoutId = getParentLayoutId(
950             groupId, privateLayout, parentLayoutId);
951 
952         validateParentLayoutId(
953             groupId, privateLayout, layoutId, parentLayoutId);
954 
955         Layout layout = layoutPersistence.findByG_P_L(
956             groupId, privateLayout, layoutId);
957 
958         if (parentLayoutId != layout.getParentLayoutId()) {
959             layout.setPriority(
960                 getNextPriority(groupId, privateLayout, parentLayoutId));
961         }
962 
963         layout.setParentLayoutId(parentLayoutId);
964 
965         layoutPersistence.update(layout, false);
966 
967         return layout;
968     }
969 
970     public Layout updateParentLayoutId(long plid, long parentPlid)
971         throws PortalException, SystemException {
972 
973         Layout layout = layoutPersistence.findByPrimaryKey(plid);
974 
975         long parentLayoutId = LayoutConstants.DEFAULT_PARENT_LAYOUT_ID;
976 
977         if (parentPlid > 0) {
978             Layout parentLayout = layoutPersistence.fetchByPrimaryKey(
979                 parentPlid);
980 
981             if (parentLayout != null) {
982                 parentLayoutId = parentLayout.getLayoutId();
983             }
984         }
985 
986         parentLayoutId = getParentLayoutId(
987             layout.getGroupId(), layout.isPrivateLayout(), parentLayoutId);
988 
989         validateParentLayoutId(
990             layout.getGroupId(), layout.isPrivateLayout(), layout.getLayoutId(),
991             parentLayoutId);
992 
993         if (parentLayoutId != layout.getParentLayoutId()) {
994             int priority = getNextPriority(
995                 layout.getGroupId(), layout.isPrivateLayout(), parentLayoutId);
996 
997             layout.setPriority(priority);
998         }
999 
1000        layout.setParentLayoutId(parentLayoutId);
1001
1002        layoutPersistence.update(layout, false);
1003
1004        return layout;
1005    }
1006
1007    public Layout updatePriority(Layout layout, int priority)
1008        throws SystemException {
1009
1010        if (layout.getPriority() == priority) {
1011            return layout;
1012        }
1013
1014        boolean lessThan = false;
1015
1016        if (layout.getPriority() < priority) {
1017            lessThan = true;
1018        }
1019
1020        layout.setPriority(priority);
1021
1022        layoutPersistence.update(layout, false);
1023
1024        priority = 0;
1025
1026        List<Layout> layouts = layoutPersistence.findByG_P_P(
1027            layout.getGroupId(), layout.isPrivateLayout(),
1028            layout.getParentLayoutId());
1029
1030        layouts = ListUtil.sort(
1031            layouts, new LayoutPriorityComparator(layout, lessThan));
1032
1033        for (Layout curLayout : layouts) {
1034            curLayout.setPriority(priority++);
1035
1036            layoutPersistence.update(curLayout, false);
1037
1038            if (curLayout.equals(layout)) {
1039                layout = curLayout;
1040            }
1041        }
1042
1043        return layout;
1044    }
1045
1046    public Layout updatePriority(
1047            long groupId, boolean privateLayout, long layoutId, int priority)
1048        throws PortalException, SystemException {
1049
1050        Layout layout = layoutPersistence.findByG_P_L(
1051            groupId, privateLayout, layoutId);
1052
1053        return updatePriority(layout, priority);
1054    }
1055
1056    public Layout updatePriority(long plid, int priority)
1057        throws PortalException, SystemException {
1058
1059        Layout layout = layoutPersistence.findByPrimaryKey(plid);
1060
1061        return updatePriority(layout, priority);
1062    }
1063
1064    protected String getFriendlyURL(long layoutId, String friendlyURL) {
1065        friendlyURL = getFriendlyURL(friendlyURL);
1066
1067        if (Validator.isNull(friendlyURL)) {
1068            friendlyURL = StringPool.SLASH + layoutId;
1069        }
1070
1071        return friendlyURL;
1072    }
1073
1074    protected String getFriendlyURL(String friendlyURL) {
1075        return FriendlyURLNormalizer.normalize(friendlyURL);
1076    }
1077
1078    protected int getNextPriority(
1079            long groupId, boolean privateLayout, long parentLayoutId)
1080        throws SystemException {
1081
1082        List<Layout> layouts = layoutPersistence.findByG_P_P(
1083            groupId, privateLayout, parentLayoutId);
1084
1085        if (layouts.size() == 0) {
1086            return 0;
1087        }
1088
1089        Layout layout = layouts.get(layouts.size() - 1);
1090
1091        return layout.getPriority() + 1;
1092    }
1093
1094    protected long getParentLayoutId(
1095            long groupId, boolean privateLayout, long parentLayoutId)
1096        throws SystemException {
1097
1098        if (parentLayoutId != LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
1099
1100            // Ensure parent layout exists
1101
1102            Layout parentLayout = layoutPersistence.fetchByG_P_L(
1103                groupId, privateLayout, parentLayoutId);
1104
1105            if (parentLayout == null) {
1106                parentLayoutId = LayoutConstants.DEFAULT_PARENT_LAYOUT_ID;
1107            }
1108        }
1109
1110        return parentLayoutId;
1111    }
1112
1113    protected boolean isDescendant(Layout layout, long layoutId)
1114        throws PortalException, SystemException {
1115
1116        if (layout.getLayoutId() == layoutId) {
1117            return true;
1118        }
1119        else {
1120            for (Layout childLayout : layout.getChildren()) {
1121                if (isDescendant(childLayout, layoutId)) {
1122                    return true;
1123                }
1124            }
1125
1126            return false;
1127        }
1128    }
1129
1130    protected void setLocalizedAttributes(
1131        Layout layout, Map<Locale, String> localeNamesMap,
1132        Map<Locale, String> localeTitlesMap) {
1133
1134        Locale[] locales = LanguageUtil.getAvailableLocales();
1135
1136        for (Locale locale : locales) {
1137            String name = localeNamesMap.get(locale);
1138            String title = localeTitlesMap.get(locale);
1139
1140            layout.setName(name, locale);
1141            layout.setTitle(title, locale);
1142        }
1143    }
1144
1145    protected void validate(
1146            long groupId, boolean privateLayout, long layoutId,
1147            long parentLayoutId, String name, String type, boolean hidden,
1148            String friendlyURL)
1149        throws PortalException, SystemException {
1150
1151        validateName(name);
1152
1153        boolean firstLayout = false;
1154
1155        if (parentLayoutId == LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
1156            List<Layout> layouts = layoutPersistence.findByG_P_P(
1157                groupId, privateLayout, parentLayoutId, 0, 1);
1158
1159            if (layouts.size() == 0) {
1160                firstLayout = true;
1161            }
1162            else {
1163                long firstLayoutId = layouts.get(0).getLayoutId();
1164
1165                if (firstLayoutId == layoutId) {
1166                    firstLayout = true;
1167                }
1168            }
1169        }
1170
1171        if (firstLayout) {
1172            validateFirstLayout(type, hidden);
1173        }
1174
1175        if (!PortalUtil.isLayoutParentable(type)) {
1176            if (layoutPersistence.countByG_P_P(
1177                    groupId, privateLayout, layoutId) > 0) {
1178
1179                throw new LayoutTypeException(
1180                    LayoutTypeException.NOT_PARENTABLE);
1181            }
1182        }
1183
1184        validateFriendlyURL(groupId, privateLayout, layoutId, friendlyURL);
1185    }
1186
1187    protected void validateFirstLayout(String type, boolean hidden)
1188        throws PortalException {
1189
1190        if (!type.equals(LayoutConstants.TYPE_PORTLET)) {
1191            throw new LayoutTypeException(LayoutTypeException.FIRST_LAYOUT);
1192        }
1193
1194        if (hidden) {
1195            throw new LayoutHiddenException();
1196        }
1197    }
1198
1199    protected void validateFriendlyURL(
1200            long groupId, boolean privateLayout, long layoutId,
1201            String friendlyURL)
1202        throws PortalException, SystemException {
1203
1204        if (Validator.isNull(friendlyURL)) {
1205            return;
1206        }
1207
1208        int exceptionType = LayoutImpl.validateFriendlyURL(friendlyURL);
1209
1210        if (exceptionType != -1) {
1211            throw new LayoutFriendlyURLException(exceptionType);
1212        }
1213
1214        Layout layout = layoutPersistence.fetchByG_P_F(
1215            groupId, privateLayout, friendlyURL);
1216
1217        if ((layout != null) && (layout.getLayoutId() != layoutId)) {
1218            throw new LayoutFriendlyURLException(
1219                LayoutFriendlyURLException.DUPLICATE);
1220        }
1221
1222        LayoutImpl.validateFriendlyURLKeyword(friendlyURL);
1223
1224        /*List<FriendlyURLMapper> friendlyURLMappers =
1225            portletLocalService.getFriendlyURLMappers();
1226
1227        for (FriendlyURLMapper friendlyURLMapper : friendlyURLMappers) {
1228            if (friendlyURL.indexOf(friendlyURLMapper.getMapping()) != -1) {
1229                LayoutFriendlyURLException lfurle =
1230                    new LayoutFriendlyURLException(
1231                        LayoutFriendlyURLException.KEYWORD_CONFLICT);
1232
1233                lfurle.setKeywordConflict(friendlyURLMapper.getMapping());
1234
1235                throw lfurle;
1236            }
1237        }*/
1238
1239        String layoutIdFriendlyURL = friendlyURL.substring(1);
1240
1241        if (Validator.isNumber(layoutIdFriendlyURL) &&
1242            !layoutIdFriendlyURL.equals(String.valueOf(layoutId))) {
1243
1244            LayoutFriendlyURLException lfurle = new LayoutFriendlyURLException(
1245                LayoutFriendlyURLException.POSSIBLE_DUPLICATE);
1246
1247            lfurle.setKeywordConflict(layoutIdFriendlyURL);
1248
1249            throw lfurle;
1250        }
1251    }
1252
1253    protected void validateName(String name) throws PortalException {
1254        if (Validator.isNull(name)) {
1255            throw new LayoutNameException();
1256        }
1257    }
1258
1259    protected void validateName(String name, String languageId)
1260        throws PortalException {
1261
1262        String defaultLanguageId = LocaleUtil.toLanguageId(
1263            LocaleUtil.getDefault());
1264
1265        if (defaultLanguageId.equals(languageId)) {
1266            validateName(name);
1267        }
1268    }
1269
1270    protected void validateParentLayoutId(
1271            long groupId, boolean privateLayout, long layoutId,
1272            long parentLayoutId)
1273        throws PortalException, SystemException {
1274
1275        Layout layout = layoutPersistence.findByG_P_L(
1276            groupId, privateLayout, layoutId);
1277
1278        if (parentLayoutId != layout.getParentLayoutId()) {
1279
1280            // Layouts can always be moved to the root level
1281
1282            if (parentLayoutId == LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
1283                return;
1284            }
1285
1286            // Layout cannot become a child of a layout that is not parentable
1287
1288            Layout parentLayout = layoutPersistence.findByG_P_L(
1289                groupId, privateLayout, parentLayoutId);
1290
1291            if (!PortalUtil.isLayoutParentable(parentLayout)) {
1292                throw new LayoutParentLayoutIdException(
1293                    LayoutParentLayoutIdException.NOT_PARENTABLE);
1294            }
1295
1296            // Layout cannot become descendant of itself
1297
1298            if (isDescendant(layout, parentLayoutId)) {
1299                throw new LayoutParentLayoutIdException(
1300                    LayoutParentLayoutIdException.SELF_DESCENDANT);
1301            }
1302
1303            // If layout is moved, the new first layout must be valid
1304
1305            if (layout.getParentLayoutId() ==
1306                    LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
1307
1308                List<Layout> layouts = layoutPersistence.findByG_P_P(
1309                    groupId, privateLayout,
1310                    LayoutConstants.DEFAULT_PARENT_LAYOUT_ID, 0, 2);
1311
1312                // You can only reach this point if there are more than two
1313                // layouts at the root level because of the descendant check
1314
1315                long firstLayoutId = layouts.get(0).getLayoutId();
1316
1317                if (firstLayoutId == layoutId) {
1318                    Layout secondLayout = layouts.get(1);
1319
1320                    try {
1321                        validateFirstLayout(
1322                            secondLayout.getType(), secondLayout.getHidden());
1323                    }
1324                    catch (LayoutHiddenException lhe) {
1325                        throw new LayoutParentLayoutIdException(
1326                            LayoutParentLayoutIdException.FIRST_LAYOUT_HIDDEN);
1327                    }
1328                    catch (LayoutTypeException lte) {
1329                        throw new LayoutParentLayoutIdException(
1330                            LayoutParentLayoutIdException.FIRST_LAYOUT_TYPE);
1331                    }
1332                }
1333            }
1334        }
1335    }
1336
1337    private static Log _log = LogFactoryUtil.getLog(
1338        LayoutLocalServiceImpl.class);
1339
1340}