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