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