001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portal.service.impl;
016    
017    import com.liferay.portal.LayoutFriendlyURLException;
018    import com.liferay.portal.LayoutHiddenException;
019    import com.liferay.portal.LayoutNameException;
020    import com.liferay.portal.LayoutParentLayoutIdException;
021    import com.liferay.portal.LayoutTypeException;
022    import com.liferay.portal.LocaleException;
023    import com.liferay.portal.NoSuchLayoutException;
024    import com.liferay.portal.RequiredLayoutException;
025    import com.liferay.portal.kernel.dao.orm.Criterion;
026    import com.liferay.portal.kernel.dao.orm.DynamicQuery;
027    import com.liferay.portal.kernel.dao.orm.DynamicQueryFactoryUtil;
028    import com.liferay.portal.kernel.dao.orm.Junction;
029    import com.liferay.portal.kernel.dao.orm.Projection;
030    import com.liferay.portal.kernel.dao.orm.ProjectionFactoryUtil;
031    import com.liferay.portal.kernel.dao.orm.Property;
032    import com.liferay.portal.kernel.dao.orm.PropertyFactoryUtil;
033    import com.liferay.portal.kernel.dao.orm.RestrictionsFactoryUtil;
034    import com.liferay.portal.kernel.exception.PortalException;
035    import com.liferay.portal.kernel.exception.SystemException;
036    import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayInputStream;
037    import com.liferay.portal.kernel.language.LanguageUtil;
038    import com.liferay.portal.kernel.util.FileUtil;
039    import com.liferay.portal.kernel.util.FriendlyURLNormalizerUtil;
040    import com.liferay.portal.kernel.util.GetterUtil;
041    import com.liferay.portal.kernel.util.ListUtil;
042    import com.liferay.portal.kernel.util.LocaleUtil;
043    import com.liferay.portal.kernel.util.LocalizationUtil;
044    import com.liferay.portal.kernel.util.ParamUtil;
045    import com.liferay.portal.kernel.util.StringBundler;
046    import com.liferay.portal.kernel.util.StringPool;
047    import com.liferay.portal.kernel.util.UnicodeProperties;
048    import com.liferay.portal.kernel.util.Validator;
049    import com.liferay.portal.kernel.workflow.WorkflowConstants;
050    import com.liferay.portal.lar.LayoutExporter;
051    import com.liferay.portal.lar.LayoutImporter;
052    import com.liferay.portal.lar.PortletExporter;
053    import com.liferay.portal.lar.PortletImporter;
054    import com.liferay.portal.model.Group;
055    import com.liferay.portal.model.Layout;
056    import com.liferay.portal.model.LayoutConstants;
057    import com.liferay.portal.model.LayoutPrototype;
058    import com.liferay.portal.model.LayoutReference;
059    import com.liferay.portal.model.LayoutSet;
060    import com.liferay.portal.model.LayoutSetPrototype;
061    import com.liferay.portal.model.LayoutTypePortlet;
062    import com.liferay.portal.model.Portlet;
063    import com.liferay.portal.model.PortletConstants;
064    import com.liferay.portal.model.PortletPreferences;
065    import com.liferay.portal.model.Resource;
066    import com.liferay.portal.model.ResourceConstants;
067    import com.liferay.portal.model.ResourcePermission;
068    import com.liferay.portal.model.User;
069    import com.liferay.portal.model.UserGroup;
070    import com.liferay.portal.model.impl.LayoutImpl;
071    import com.liferay.portal.model.impl.PortletPreferencesImpl;
072    import com.liferay.portal.security.pacl.PACLClassLoaderUtil;
073    import com.liferay.portal.service.ServiceContext;
074    import com.liferay.portal.service.base.LayoutLocalServiceBaseImpl;
075    import com.liferay.portal.util.PortalUtil;
076    import com.liferay.portal.util.PortletKeys;
077    import com.liferay.portal.util.PropsValues;
078    import com.liferay.portal.util.comparator.LayoutComparator;
079    import com.liferay.portal.util.comparator.LayoutPriorityComparator;
080    import com.liferay.portlet.PortletPreferencesFactoryUtil;
081    import com.liferay.portlet.expando.model.ExpandoBridge;
082    import com.liferay.portlet.sites.util.SitesUtil;
083    
084    import java.io.File;
085    import java.io.IOException;
086    import java.io.InputStream;
087    
088    import java.util.ArrayList;
089    import java.util.Date;
090    import java.util.HashMap;
091    import java.util.HashSet;
092    import java.util.LinkedHashSet;
093    import java.util.List;
094    import java.util.Locale;
095    import java.util.Map;
096    import java.util.Set;
097    
098    import javax.portlet.PortletException;
099    
100    /**
101     * The implementation of the layout local service.
102     *
103     * @author Brian Wing Shun Chan
104     * @author Jorge Ferrer
105     * @author Joel Kozikowski
106     * @author Charles May
107     * @author Raymond Augé
108     * @author Jorge Ferrer
109     * @author Bruno Farache
110     * @author Vilmos Papp
111     */
112    public class LayoutLocalServiceImpl extends LayoutLocalServiceBaseImpl {
113    
114            /**
115             * Returns the object counter's name.
116             *
117             * @param  groupId the primary key of the group
118             * @param  privateLayout whether layout is private to the group
119             * @return the object counter's name
120             */
121            public static String getCounterName(long groupId, boolean privateLayout) {
122                    StringBundler sb = new StringBundler();
123    
124                    sb.append(Layout.class.getName());
125                    sb.append(StringPool.POUND);
126                    sb.append(groupId);
127                    sb.append(StringPool.POUND);
128                    sb.append(privateLayout);
129    
130                    return sb.toString();
131            }
132    
133            /**
134             * Adds a layout with additional parameters.
135             *
136             * <p>
137             * This method handles the creation of the layout including its resources,
138             * metadata, and internal data structures. It is not necessary to make
139             * subsequent calls to any methods to setup default groups, resources, ...
140             * etc.
141             * </p>
142             *
143             * @param  userId the primary key of the user
144             * @param  groupId the primary key of the group
145             * @param  privateLayout whether the layout is private to the group
146             * @param  parentLayoutId the primary key of the parent layout (optionally
147             *         {@link
148             *         com.liferay.portal.model.LayoutConstants#DEFAULT_PARENT_LAYOUT_ID})
149             * @param  nameMap the layout's locales and localized names
150             * @param  titleMap the layout's locales and localized titles
151             * @param  descriptionMap the layout's locales and localized descriptions
152             * @param  keywordsMap the layout's locales and localized keywords
153             * @param  robotsMap the layout's locales and localized robots
154             * @param  type the layout's type (optionally {@link
155             *         com.liferay.portal.model.LayoutConstants#TYPE_PORTLET}). The
156             *         possible types can be found in {@link
157             *         com.liferay.portal.model.LayoutConstants}.
158             * @param  hidden whether the layout is hidden
159             * @param  friendlyURL the layout's friendly URL (optionally {@link
160             *         com.liferay.portal.util.PropsValues#DEFAULT_USER_PRIVATE_LAYOUT_FRIENDLY_URL}
161             *         or {@link
162             *         com.liferay.portal.util.PropsValues#DEFAULT_USER_PUBLIC_LAYOUT_FRIENDLY_URL}).
163             *         The default values can be overridden in
164             *         <code>portal-ext.properties</code> by specifying new values for
165             *         the corresponding properties defined in {@link
166             *         com.liferay.portal.util.PropsValues}. To see how the URL is
167             *         normalized when accessed see {@link
168             *         com.liferay.portal.kernel.util.FriendlyURLNormalizerUtil#normalize(
169             *         String)}.
170             * @param  serviceContext the service context. Must set the universally
171             *         unique identifier (UUID) for the layout. Can set the creation
172             *         date, modification date and the expando bridge attributes for the
173             *         layout. For layouts that belong to a layout set prototype, an
174             *         attribute named 'layoutUpdateable' can be set to specify whether
175             *         site administrators can modify this page within their site. For
176             *         layouts that are created from a layout prototype, attributes
177             *         named 'layoutPrototypeUuid' and 'layoutPrototypeLinkedEnabled'
178             *         can be specified to provide the unique identifier of the source
179             *         prototype and a boolean to determined whether a link to it should
180             *         be enabled to activate propagation of changes made to the linked
181             *         page in the prototype.
182             * @return the layout
183             * @throws PortalException if a group or user with the primary key could not
184             *         be found, or if layout values were invalid
185             * @throws SystemException if a system exception occurred
186             */
187            public Layout addLayout(
188                            long userId, long groupId, boolean privateLayout,
189                            long parentLayoutId, Map<Locale, String> nameMap,
190                            Map<Locale, String> titleMap, Map<Locale, String> descriptionMap,
191                            Map<Locale, String> keywordsMap, Map<Locale, String> robotsMap,
192                            String type, boolean hidden, String friendlyURL,
193                            ServiceContext serviceContext)
194                    throws PortalException, SystemException {
195    
196                    // Layout
197    
198                    User user = userPersistence.findByPrimaryKey(userId);
199                    long layoutId = getNextLayoutId(groupId, privateLayout);
200                    parentLayoutId = getParentLayoutId(
201                            groupId, privateLayout, parentLayoutId);
202                    String name = nameMap.get(LocaleUtil.getDefault());
203                    friendlyURL = getFriendlyURL(
204                            groupId, privateLayout, layoutId, name, friendlyURL);
205                    int priority = getNextPriority(
206                            groupId, privateLayout, parentLayoutId, null, -1);
207    
208                    validate(
209                            groupId, privateLayout, layoutId, parentLayoutId, name, type,
210                            hidden, friendlyURL);
211    
212                    Date now = new Date();
213    
214                    long plid = counterLocalService.increment();
215    
216                    Layout layout = layoutPersistence.create(plid);
217    
218                    layout.setUuid(serviceContext.getUuid());
219                    layout.setGroupId(groupId);
220                    layout.setCompanyId(user.getCompanyId());
221                    layout.setCreateDate(serviceContext.getCreateDate(now));
222                    layout.setModifiedDate(serviceContext.getModifiedDate(now));
223                    layout.setPrivateLayout(privateLayout);
224                    layout.setLayoutId(layoutId);
225                    layout.setParentLayoutId(parentLayoutId);
226                    layout.setNameMap(nameMap);
227                    layout.setTitleMap(titleMap);
228                    layout.setDescriptionMap(descriptionMap);
229                    layout.setKeywordsMap(keywordsMap);
230                    layout.setRobotsMap(robotsMap);
231                    layout.setType(type);
232                    layout.setHidden(hidden);
233                    layout.setFriendlyURL(friendlyURL);
234                    layout.setPriority(priority);
235    
236                    boolean layoutUpdateable = ParamUtil.getBoolean(
237                            serviceContext, "layoutUpdateable", true);
238    
239                    if (!layoutUpdateable) {
240                            UnicodeProperties typeSettingsProperties =
241                                    layout.getTypeSettingsProperties();
242    
243                            typeSettingsProperties.put(
244                                    "layoutUpdateable", String.valueOf(layoutUpdateable));
245    
246                            layout.setTypeSettingsProperties(typeSettingsProperties);
247                    }
248    
249                    String layoutPrototypeUuid = ParamUtil.getString(
250                            serviceContext, "layoutPrototypeUuid");
251                    boolean layoutPrototypeLinkEnabled = ParamUtil.getBoolean(
252                            serviceContext, "layoutPrototypeLinkEnabled",
253                            PropsValues.LAYOUT_PROTOTYPE_LINK_ENABLED_DEFAULT);
254    
255                    if (Validator.isNotNull(layoutPrototypeUuid)) {
256                            layout.setLayoutPrototypeUuid(layoutPrototypeUuid);
257                            layout.setLayoutPrototypeLinkEnabled(layoutPrototypeLinkEnabled);
258                    }
259    
260                    if (type.equals(LayoutConstants.TYPE_PORTLET)) {
261                            LayoutTypePortlet layoutTypePortlet =
262                                    (LayoutTypePortlet)layout.getLayoutType();
263    
264                            layoutTypePortlet.setLayoutTemplateId(
265                                    0, PropsValues.LAYOUT_DEFAULT_TEMPLATE_ID, false);
266                    }
267    
268                    layoutPersistence.update(layout, false);
269    
270                    if (Validator.isNotNull(layoutPrototypeUuid) &&
271                            !layoutPrototypeLinkEnabled) {
272    
273                            LayoutPrototype layoutPrototype =
274                                    layoutPrototypeLocalService.getLayoutPrototypeByUuid(
275                                            layoutPrototypeUuid);
276    
277                            try {
278                                    SitesUtil.applyLayoutPrototype(
279                                            layoutPrototype, layout, layoutPrototypeLinkEnabled);
280                            }
281                            catch (PortalException pe) {
282                                    throw pe;
283                            }
284                            catch (SystemException se) {
285                                    throw se;
286                            }
287                            catch (Exception e) {
288                                    throw new SystemException(e);
289                            }
290                    }
291    
292                    // Resources
293    
294                    boolean addGroupPermissions = true;
295    
296                    Group group = groupLocalService.getGroup(groupId);
297    
298                    if (privateLayout && group.isUser()) {
299                            addGroupPermissions = false;
300                    }
301    
302                    boolean addGuestPermissions = false;
303    
304                    if (!privateLayout ||
305                            type.equals(LayoutConstants.TYPE_CONTROL_PANEL) ||
306                            group.isLayoutSetPrototype()) {
307    
308                            addGuestPermissions = true;
309                    }
310    
311                    resourceLocalService.addResources(
312                            user.getCompanyId(), groupId, user.getUserId(),
313                            Layout.class.getName(), layout.getPlid(), false,
314                            addGroupPermissions, addGuestPermissions);
315    
316                    // Group
317    
318                    groupLocalService.updateSite(groupId, true);
319    
320                    // Layout set
321    
322                    layoutSetLocalService.updatePageCount(groupId, privateLayout);
323    
324                    LayoutSet layoutSet = layoutSetPersistence.findByG_P(
325                            groupId, privateLayout);
326    
327                    layout.setLayoutSet(layoutSet);
328    
329                    // Expando
330    
331                    ExpandoBridge expandoBridge = layout.getExpandoBridge();
332    
333                    expandoBridge.setAttributes(serviceContext);
334    
335                    // Message boards
336    
337                    if (PropsValues.LAYOUT_COMMENTS_ENABLED) {
338                            mbMessageLocalService.addDiscussionMessage(
339                                    userId, user.getFullName(), groupId, Layout.class.getName(),
340                                    plid, WorkflowConstants.ACTION_PUBLISH);
341                    }
342    
343                    return layout;
344            }
345    
346            /**
347             * Adds a layout.
348             *
349             * <p>
350             * This method handles the creation of the layout including its resources,
351             * metadata, and internal data structures. It is not necessary to make
352             * subsequent calls to any methods to setup default groups, resources, ...
353             * etc.
354             * </p>
355             *
356             * @param  userId the primary key of the user
357             * @param  groupId the primary key of the group
358             * @param  privateLayout whether the layout is private to the group
359             * @param  parentLayoutId the primary key of the parent layout (optionally
360             *         {@link
361             *         com.liferay.portal.model.LayoutConstants#DEFAULT_PARENT_LAYOUT_ID}).
362             *         The possible values can be found in {@link
363             *         com.liferay.portal.model.LayoutConstants}.
364             * @param  name the layout's name (optionally {@link
365             *         com.liferay.portal.util.PropsValues#DEFAULT_USER_PRIVATE_LAYOUT_NAME}
366             *         or {@link
367             *         com.liferay.portal.util.PropsValues#DEFAULT_USER_PUBLIC_LAYOUT_NAME}).
368             *         The default values can be overridden in
369             *         <code>portal-ext.properties</code> by specifying new values for
370             *         the corresponding properties defined in {@link
371             *         com.liferay.portal.util.PropsValues}
372             * @param  title the layout's title
373             * @param  description the layout's description
374             * @param  type the layout's type (optionally {@link
375             *         com.liferay.portal.model.LayoutConstants#TYPE_PORTLET}). The
376             *         possible types can be found in {@link
377             *         com.liferay.portal.model.LayoutConstants}.
378             * @param  hidden whether the layout is hidden
379             * @param  friendlyURL the friendly URL of the layout (optionally {@link
380             *         com.liferay.portal.util.PropsValues#DEFAULT_USER_PRIVATE_LAYOUT_FRIENDLY_URL}
381             *         or {@link
382             *         com.liferay.portal.util.PropsValues#DEFAULT_USER_PUBLIC_LAYOUT_FRIENDLY_URL}).
383             *         The default values can be overridden in
384             *         <code>portal-ext.properties</code> by specifying new values for
385             *         the corresponding properties defined in {@link
386             *         com.liferay.portal.util.PropsValues}. To see how the URL is
387             *         normalized when accessed see {@link
388             *         com.liferay.portal.kernel.util.FriendlyURLNormalizerUtil#normalize(
389             *         String)}.
390             * @param  serviceContext the service context. Must set the universally
391             *         unique identifier (UUID) for the layout. Can set the creation
392             *         date and modification date for the layout. For layouts that
393             *         belong to a layout set prototype, an attribute named
394             *         'layoutUpdateable' can be set to specify whether site
395             *         administrators can modify this page within their site.
396             * @return the layout
397             * @throws PortalException if a group or user with the primary key could not
398             *         be found
399             * @throws SystemException if a system exception occurred
400             */
401            public Layout addLayout(
402                            long userId, long groupId, boolean privateLayout,
403                            long parentLayoutId, String name, String title, String description,
404                            String type, boolean hidden, String friendlyURL,
405                            ServiceContext serviceContext)
406                    throws PortalException, SystemException {
407    
408                    Map<Locale, String> localeNamesMap = new HashMap<Locale, String>();
409    
410                    Locale defaultLocale = LocaleUtil.getDefault();
411    
412                    localeNamesMap.put(defaultLocale, name);
413    
414                    return addLayout(
415                            userId, groupId, privateLayout, parentLayoutId, localeNamesMap,
416                            new HashMap<Locale, String>(), new HashMap<Locale, String>(),
417                            new HashMap<Locale, String>(), new HashMap<Locale, String>(), type,
418                            hidden, friendlyURL, serviceContext);
419            }
420    
421            /**
422             * Deletes the layout, its child layouts, and its associated resources.
423             *
424             * @param  layout the layout
425             * @param  updateLayoutSet whether the layout set's page counter needs to be
426             *         updated
427             * @param  serviceContext the service context
428             * @throws PortalException if a portal exception occurred
429             * @throws SystemException if a system exception occurred
430             */
431            public void deleteLayout(
432                            Layout layout, boolean updateLayoutSet,
433                            ServiceContext serviceContext)
434                    throws PortalException, SystemException {
435    
436                    // First layout validation
437    
438                    if (layout.getParentLayoutId() ==
439                                    LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
440    
441                            List<Layout> rootLayouts = layoutPersistence.findByG_P_P(
442                                    layout.getGroupId(), layout.isPrivateLayout(),
443                                    LayoutConstants.DEFAULT_PARENT_LAYOUT_ID, 0, 2);
444    
445                            if (rootLayouts.size() > 1) {
446                                    Layout firstLayout = rootLayouts.get(0);
447    
448                                    if (firstLayout.getLayoutId() == layout.getLayoutId()) {
449                                            Layout secondLayout = rootLayouts.get(1);
450    
451                                            validateFirstLayout(secondLayout.getType());
452                                    }
453                            }
454                    }
455    
456                    // Child layouts
457    
458                    List<Layout> childLayouts = layoutPersistence.findByG_P_P(
459                            layout.getGroupId(), layout.isPrivateLayout(),
460                            layout.getLayoutId());
461    
462                    for (Layout childLayout : childLayouts) {
463                            deleteLayout(childLayout, updateLayoutSet, serviceContext);
464                    }
465    
466                    // Portlet preferences
467    
468                    portletPreferencesLocalService.deletePortletPreferences(
469                            PortletKeys.PREFS_OWNER_ID_DEFAULT,
470                            PortletKeys.PREFS_OWNER_TYPE_LAYOUT, layout.getPlid());
471    
472                    // Subscriptions
473    
474                    subscriptionLocalService.deleteSubscriptions(
475                            layout.getCompanyId(), Layout.class.getName(), layout.getPlid());
476    
477                    // Ratings
478    
479                    ratingsStatsLocalService.deleteStats(
480                            Layout.class.getName(), layout.getPlid());
481    
482                    // Message boards
483    
484                    mbMessageLocalService.deleteDiscussionMessages(
485                            Layout.class.getName(), layout.getPlid());
486    
487                    // Journal articles
488    
489                    journalArticleLocalService.deleteLayoutArticleReferences(
490                            layout.getGroupId(), layout.getUuid());
491    
492                    // Journal content searches
493    
494                    journalContentSearchLocalService.deleteLayoutContentSearches(
495                            layout.getGroupId(), layout.isPrivateLayout(),
496                            layout.getLayoutId());
497    
498                    // Expando
499    
500                    expandoValueLocalService.deleteValues(
501                            Layout.class.getName(), layout.getPlid());
502    
503                    // Icon
504    
505                    imageLocalService.deleteImage(layout.getIconImageId());
506    
507                    // Scope group
508    
509                    Group scopeGroup = layout.getScopeGroup();
510    
511                    if (scopeGroup != null) {
512                            groupLocalService.deleteGroup(scopeGroup.getGroupId());
513                    }
514    
515                    // Resources
516    
517                    String primKey =
518                            layout.getPlid() + PortletConstants.LAYOUT_SEPARATOR + "%";
519    
520                    if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) {
521                            List<ResourcePermission> resourcePermissions =
522                                    resourcePermissionPersistence.findByC_P(
523                                            layout.getCompanyId(), primKey);
524    
525                            for (ResourcePermission resourcePermission : resourcePermissions) {
526                                    resourcePermissionLocalService.deleteResourcePermission(
527                                            resourcePermission);
528                            }
529                    }
530                    else {
531                            List<Resource> resources = resourceFinder.findByC_P(
532                                    layout.getCompanyId(), primKey);
533    
534                            for (Resource resource : resources) {
535                                    resourceLocalService.deleteResource(resource);
536                            }
537                    }
538    
539                    resourceLocalService.deleteResource(
540                            layout.getCompanyId(), Layout.class.getName(),
541                            ResourceConstants.SCOPE_INDIVIDUAL, layout.getPlid());
542    
543                    // Layout
544    
545                    layoutPersistence.remove(layout);
546    
547                    // Layout set
548    
549                    if (updateLayoutSet) {
550                            layoutSetLocalService.updatePageCount(
551                                    layout.getGroupId(), layout.isPrivateLayout());
552                    }
553            }
554    
555            /**
556             * Deletes the layout with the primary key, also deleting the layout's child
557             * layouts, and associated resources.
558             *
559             * @param  groupId the primary key of the group
560             * @param  privateLayout whether the layout is private to the group
561             * @param  layoutId the primary key of the layout
562             * @param  serviceContext the service context
563             * @throws PortalException if a matching layout could not be found , or if
564             *         some other portal exception occurred
565             * @throws SystemException if a system exception occurred
566             */
567            public void deleteLayout(
568                            long groupId, boolean privateLayout, long layoutId,
569                            ServiceContext serviceContext)
570                    throws PortalException, SystemException {
571    
572                    Layout layout = layoutPersistence.findByG_P_L(
573                            groupId, privateLayout, layoutId);
574    
575                    deleteLayout(layout, true, serviceContext);
576            }
577    
578            /**
579             * Deletes the layout with the plid, also deleting the layout's child
580             * layouts, and associated resources.
581             *
582             * @param  plid the primary key of the layout
583             * @param  serviceContext the service context
584             * @throws PortalException if a layout with the primary key could not be
585             *         found , or if some other portal exception occurred
586             * @throws SystemException if a system exception occurred
587             */
588            public void deleteLayout(long plid, ServiceContext serviceContext)
589                    throws PortalException, SystemException {
590    
591                    Layout layout = layoutPersistence.findByPrimaryKey(plid);
592    
593                    deleteLayout(layout, true, serviceContext);
594            }
595    
596            /**
597             * Deletes the group's private or non-private layouts, also deleting the
598             * layouts' child layouts, and associated resources.
599             *
600             * @param  groupId the primary key of the group
601             * @param  privateLayout whether the layout is private to the group
602             * @param  serviceContext the service context
603             * @throws PortalException if a group with the primary key could not be
604             *         found or if a layout set for the group and privacy could not be
605             *         found
606             * @throws SystemException if a system exception occurred
607             */
608            public void deleteLayouts(
609                            long groupId, boolean privateLayout, ServiceContext serviceContext)
610                    throws PortalException, SystemException {
611    
612                    // Layouts
613    
614                    List<Layout> layouts = layoutPersistence.findByG_P_P(
615                            groupId, privateLayout, LayoutConstants.DEFAULT_PARENT_LAYOUT_ID);
616    
617                    for (Layout layout : layouts) {
618                            try {
619                                    deleteLayout(layout, false, serviceContext);
620                            }
621                            catch (NoSuchLayoutException nsle) {
622                            }
623                    }
624    
625                    // Layout set
626    
627                    layoutSetLocalService.updatePageCount(groupId, privateLayout);
628    
629                    // Counter
630    
631                    counterLocalService.reset(getCounterName(groupId, privateLayout));
632            }
633    
634            /**
635             * Exports layouts with the primary keys and criteria as a byte array.
636             *
637             * @param  groupId the primary key of the group
638             * @param  privateLayout whether the layout is private to the group
639             * @param  layoutIds the primary keys of the layouts to be exported
640             * @param  parameterMap the mapping of parameters indicating which
641             *         information to export. For information on the keys used in the
642             *         map see {@link
643             *         com.liferay.portal.kernel.lar.PortletDataHandlerKeys}.
644             * @param  startDate the export's start date
645             * @param  endDate the export's end date
646             * @return the layouts as a byte array
647             * @throws PortalException if a group or any layout with the primary key
648             *         could not be found, or if some other portal exception occurred
649             * @throws SystemException if a system exception occurred
650             */
651            public byte[] exportLayouts(
652                            long groupId, boolean privateLayout, long[] layoutIds,
653                            Map<String, String[]> parameterMap, Date startDate, Date endDate)
654                    throws PortalException, SystemException {
655    
656                    File file = exportLayoutsAsFile(
657                            groupId, privateLayout, layoutIds, parameterMap, startDate,
658                            endDate);
659    
660                    try {
661                            return FileUtil.getBytes(file);
662                    }
663                    catch (IOException ioe) {
664                            throw new SystemException(ioe);
665                    }
666                    finally {
667                            file.delete();
668                    }
669            }
670    
671            /**
672             * Exports all layouts that match the criteria as a byte array.
673             *
674             * @param  groupId the primary key of the group
675             * @param  privateLayout whether the layout is private to the group
676             * @param  parameterMap the mapping of parameters indicating which
677             *         information to export. For information on the keys used in the
678             *         map see {@link
679             *         com.liferay.portal.kernel.lar.PortletDataHandlerKeys}.
680             * @param  startDate the export's start date
681             * @param  endDate the export's end date
682             * @return the layout as a byte array
683             * @throws PortalException if a group with the primary key could not be
684             *         found or if some other portal exception occurred
685             * @throws SystemException if a system exception occurred
686             */
687            public byte[] exportLayouts(
688                            long groupId, boolean privateLayout,
689                            Map<String, String[]> parameterMap, Date startDate, Date endDate)
690                    throws PortalException, SystemException {
691    
692                    return exportLayouts(
693                            groupId, privateLayout, null, parameterMap, startDate, endDate);
694            }
695    
696            /**
697             * Exports the layouts that match the primary keys and criteria as a file.
698             *
699             * @param  groupId the primary key of the group
700             * @param  privateLayout whether the layout is private to the group
701             * @param  layoutIds the primary keys of the layouts to be exported
702             *         (optionally <code>null</code>)
703             * @param  parameterMap the mapping of parameters indicating which
704             *         information to export. For information on the keys used in the
705             *         map see {@link
706             *         com.liferay.portal.kernel.lar.PortletDataHandlerKeys}.
707             * @param  startDate the export's start date
708             * @param  endDate the export's end date
709             * @return the layouts as a File
710             * @throws PortalException if a group or any layout with the primary key
711             *         could not be found, or if some other portal exception occurred
712             * @throws SystemException if a system exception occurred
713             */
714            public File exportLayoutsAsFile(
715                            long groupId, boolean privateLayout, long[] layoutIds,
716                            Map<String, String[]> parameterMap, Date startDate, Date endDate)
717                    throws PortalException, SystemException {
718    
719                    try {
720                            LayoutExporter layoutExporter = new LayoutExporter();
721    
722                            return layoutExporter.exportLayoutsAsFile(
723                                    groupId, privateLayout, layoutIds, parameterMap, startDate,
724                                    endDate);
725                    }
726                    catch (PortalException pe) {
727                            throw pe;
728                    }
729                    catch (SystemException se) {
730                            throw se;
731                    }
732                    catch (Exception e) {
733                            throw new SystemException(e);
734                    }
735            }
736    
737            /**
738             * Exports the portlet information (categories, permissions, ... etc.) as a
739             * byte array.
740             *
741             * @param  plid the primary key of the layout
742             * @param  groupId the primary key of the group
743             * @param  portletId the primary key of the portlet
744             * @param  parameterMap the mapping of parameters indicating which
745             *         information to export. For information on the keys used in the
746             *         map see {@link
747             *         com.liferay.portal.kernel.lar.PortletDataHandlerKeys}.
748             * @param  startDate the export's start date
749             * @param  endDate the export's end date
750             * @return the portlet information as a byte array
751             * @throws PortalException if a group or portlet with the primary key could
752             *         not be found, or if some other portal exception occurred
753             * @throws SystemException if a system exception occurred
754             */
755            public byte[] exportPortletInfo(
756                            long plid, long groupId, String portletId,
757                            Map<String, String[]> parameterMap, Date startDate, Date endDate)
758                    throws PortalException, SystemException {
759    
760                    File file = exportPortletInfoAsFile(
761                            plid, groupId, portletId, parameterMap, startDate, endDate);
762    
763                    try {
764                            return FileUtil.getBytes(file);
765                    }
766                    catch (IOException ioe) {
767                            throw new SystemException(ioe);
768                    }
769                    finally {
770                            file.delete();
771                    }
772            }
773    
774            /**
775             * Exports the portlet information (categories, permissions, ... etc.) as a
776             * file.
777             *
778             * @param  plid the primary key of the layout
779             * @param  groupId the primary key of the group
780             * @param  portletId the primary key of the portlet
781             * @param  parameterMap the mapping of parameters indicating which
782             *         information to export. For information on the keys used in the
783             *         map see {@link
784             *         com.liferay.portal.kernel.lar.PortletDataHandlerKeys}.
785             * @param  startDate the export's start date
786             * @param  endDate the export's end date
787             * @return the portlet information as a file
788             * @throws PortalException if a group or portlet with the primary key could
789             *         not be found, or if some other portal exception occurred
790             * @throws SystemException if a system exception occurred
791             */
792            public File exportPortletInfoAsFile(
793                            long plid, long groupId, String portletId,
794                            Map<String, String[]> parameterMap, Date startDate, Date endDate)
795                    throws PortalException, SystemException {
796    
797                    try {
798                            PortletExporter portletExporter = new PortletExporter();
799    
800                            return portletExporter.exportPortletInfoAsFile(
801                                    plid, groupId, portletId, parameterMap, startDate, endDate);
802                    }
803                    catch (PortalException pe) {
804                            throw pe;
805                    }
806                    catch (SystemException se) {
807                            throw se;
808                    }
809                    catch (Exception e) {
810                            throw new SystemException(e);
811                    }
812            }
813    
814            public Layout fetchFirstLayout(
815                            long groupId, boolean privateLayout, long parentLayoutId)
816                    throws SystemException {
817    
818                    return layoutPersistence.fetchByG_P_P_First(
819                            groupId, privateLayout, parentLayoutId,
820                            new LayoutPriorityComparator());
821            }
822    
823            /**
824             * Returns the layout matching the universally unique identifier and group
825             * ID
826             *
827             * @param  uuid the universally unique identifier of the scope layout
828             * @param  groupId the primary key of the group
829             * @return the layout, or <code>null</code> if a matching layout could not
830             *         be found
831             * @throws SystemException if a system exception occurred
832             */
833            public Layout fetchLayoutByUuidAndGroupId(String uuid, long groupId)
834                    throws SystemException {
835    
836                    return layoutPersistence.fetchByUUID_G(uuid, groupId);
837            }
838    
839            /**
840             * Returns the primary key of the default layout for the group
841             *
842             * @param  groupId the primary key of the group
843             * @return the primary key of the default layout for the group (optionally
844             *         {@link com.liferay.portal.model.LayoutConstants#DEFAULT_PLID})
845             * @throws SystemException if a system exception occurred
846             */
847            public long getDefaultPlid(long groupId) throws SystemException {
848                    if (groupId > 0) {
849                            List<Layout> layouts = layoutPersistence.findByGroupId(
850                                    groupId, 0, 1);
851    
852                            if (layouts.size() > 0) {
853                                    Layout layout = layouts.get(0);
854    
855                                    return layout.getPlid();
856                            }
857                    }
858    
859                    return LayoutConstants.DEFAULT_PLID;
860            }
861    
862            /**
863             * Returns primary key of the matching default layout for the group
864             *
865             * @param  groupId the primary key of the group
866             * @param  privateLayout whether the layout is private to the group
867             * @return the primary key of the default layout for the group; {@link
868             *         com.liferay.portal.model.LayoutConstants#DEFAULT_PLID}) otherwise
869             * @throws SystemException if a system exception occurred
870             */
871            public long getDefaultPlid(long groupId, boolean privateLayout)
872                    throws SystemException {
873    
874                    if (groupId > 0) {
875                            List<Layout> layouts = layoutPersistence.findByG_P(
876                                    groupId, privateLayout, 0, 1);
877    
878                            if (layouts.size() > 0) {
879                                    Layout layout = layouts.get(0);
880    
881                                    return layout.getPlid();
882                            }
883                    }
884    
885                    return LayoutConstants.DEFAULT_PLID;
886            }
887    
888            /**
889             * Returns primary key of the default portlet layout for the group
890             *
891             * @param  groupId the primary key of the group
892             * @param  privateLayout whether the layout is private to the group
893             * @param  portletId the primary key of the portlet
894             * @return the primary key of the default portlet layout for the group;
895             *         {@link com.liferay.portal.model.LayoutConstants#DEFAULT_PLID}
896             *         otherwise
897             * @throws PortalException if a portlet with the primary key could not be
898             *         found
899             * @throws SystemException if a system exception occurred
900             */
901            public long getDefaultPlid(
902                            long groupId, boolean privateLayout, String portletId)
903                    throws PortalException, SystemException {
904    
905                    if (groupId > 0) {
906                            List<Layout> layouts = layoutPersistence.findByG_P(
907                                    groupId, privateLayout);
908    
909                            for (Layout layout : layouts) {
910                                    if (layout.isTypePortlet()) {
911                                            LayoutTypePortlet layoutTypePortlet =
912                                                    (LayoutTypePortlet)layout.getLayoutType();
913    
914                                            if (layoutTypePortlet.hasPortletId(portletId)) {
915                                                    return layout.getPlid();
916                                            }
917                                    }
918                            }
919                    }
920    
921                    return LayoutConstants.DEFAULT_PLID;
922            }
923    
924            /**
925             * Returns the layout for the friendly URL
926             *
927             * @param  groupId the primary key of the group
928             * @param  privateLayout whether the layout is private to the group
929             * @param  friendlyURL the friendly URL of the layout
930             * @return the layout for the friendly URL
931             * @throws PortalException if the friendly URL is <code>null</code> or a
932             *         matching layout could not be found
933             * @throws SystemException if a system exception occurred
934             */
935            public Layout getFriendlyURLLayout(
936                            long groupId, boolean privateLayout, String friendlyURL)
937                    throws PortalException, SystemException {
938    
939                    if (Validator.isNull(friendlyURL)) {
940                            throw new NoSuchLayoutException();
941                    }
942    
943                    friendlyURL = getFriendlyURL(friendlyURL);
944    
945                    Layout layout = layoutPersistence.fetchByG_P_F(
946                            groupId, privateLayout, friendlyURL);
947    
948                    if ((layout == null) &&
949                            friendlyURL.startsWith(StringPool.SLASH) &&
950                            Validator.isNumber(friendlyURL.substring(1))) {
951    
952                            long layoutId = GetterUtil.getLong(friendlyURL.substring(1));
953    
954                            layout = layoutPersistence.fetchByG_P_L(
955                                    groupId, privateLayout, layoutId);
956                    }
957    
958                    if (layout == null) {
959                            throw new NoSuchLayoutException();
960                    }
961    
962                    return layout;
963            }
964    
965            /**
966             * Returns the layout matching the primary key, group, and privacy; throws a
967             * {@link com.liferay.portal.NoSuchLayoutException} otherwise.
968             *
969             * @param  groupId the primary key of the group
970             * @param  privateLayout whether the layout is private to the group
971             * @param  layoutId the primary key of the layout
972             * @return the matching layout
973             * @throws PortalException if a matching layout could not be found
974             * @throws SystemException if a system exception occurred
975             */
976            public Layout getLayout(long groupId, boolean privateLayout, long layoutId)
977                    throws PortalException, SystemException {
978    
979                    return layoutPersistence.findByG_P_L(groupId, privateLayout, layoutId);
980            }
981    
982            /**
983             * Returns the layout for the icon image; throws a {@link
984             * com.liferay.portal.NoSuchLayoutException} otherwise.
985             *
986             * @param  iconImageId the primary key of the icon image
987             * @return Returns the layout for the icon image
988             * @throws PortalException if an icon image with the primary key could not
989             *         be found
990             * @throws SystemException if a system exception occurred
991             */
992            public Layout getLayoutByIconImageId(long iconImageId)
993                    throws PortalException, SystemException {
994    
995                    return layoutPersistence.findByIconImageId(iconImageId);
996            }
997    
998            /**
999             * Returns all the layouts belonging to the group.
1000             *
1001             * @param  groupId the primary key of the group
1002             * @param  privateLayout whether the layout is private to the group
1003             * @return the matching layouts, or <code>null</code> if no matches were
1004             *         found
1005             * @throws SystemException if a system exception occurred
1006             */
1007            public List<Layout> getLayouts(long groupId, boolean privateLayout)
1008                    throws SystemException {
1009    
1010                    return layoutPersistence.findByG_P(groupId, privateLayout);
1011            }
1012    
1013            /**
1014             * Returns all the layouts belonging to the group that are children of the
1015             * parent layout.
1016             *
1017             * @param  groupId the primary key of the group
1018             * @param  privateLayout whether the layout is private to the group
1019             * @param  parentLayoutId the primary key of the parent layout
1020             * @return the matching layouts, or <code>null</code> if no matches were
1021             *         found
1022             * @throws SystemException if a system exception occurred
1023             */
1024            public List<Layout> getLayouts(
1025                            long groupId, boolean privateLayout, long parentLayoutId)
1026                    throws SystemException {
1027    
1028                    return layoutPersistence.findByG_P_P(
1029                            groupId, privateLayout, parentLayoutId);
1030            }
1031    
1032            /**
1033             * Returns a range of all the layouts belonging to the group that are
1034             * children of the parent layout.
1035             *
1036             * <p>
1037             * Useful when paginating results. Returns a maximum of <code>end -
1038             * start</code> instances. <code>start</code> and <code>end</code> are not
1039             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1040             * refers to the first result in the set. Setting both <code>start</code>
1041             * and <code>end</code> to {@link
1042             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1043             * result set.
1044             * </p>
1045             *
1046             * @param  groupId the primary key of the group
1047             * @param  privateLayout whether the layout is private to the group
1048             * @param  parentLayoutId the primary key of the parent layout
1049             * @param  incomplete whether the layout is incomplete
1050             * @param  start the lower bound of the range of layouts
1051             * @param  end the upper bound of the range of layouts (not inclusive)
1052             * @return the matching layouts, or <code>null</code> if no matches were
1053             *         found
1054             * @throws SystemException if a system exception occurred
1055             */
1056            public List<Layout> getLayouts(
1057                            long groupId, boolean privateLayout, long parentLayoutId,
1058                            boolean incomplete, int start, int end)
1059                    throws SystemException {
1060    
1061                    return layoutPersistence.findByG_P_P(
1062                            groupId, privateLayout, parentLayoutId, start, end);
1063            }
1064    
1065            /**
1066             * Returns all the layouts that match the layout IDs and belong to the
1067             * group.
1068             *
1069             * @param  groupId the primary key of the group
1070             * @param  privateLayout whether the layout is private to the group
1071             * @param  layoutIds the primary keys of the layouts
1072             * @return the matching layouts, or <code>null</code> if no matches were
1073             *         found
1074             * @throws PortalException if a group or layout with the primary key could
1075             *         not be found
1076             * @throws SystemException if a system exception occurred
1077             */
1078            public List<Layout> getLayouts(
1079                            long groupId, boolean privateLayout, long[] layoutIds)
1080                    throws PortalException, SystemException {
1081    
1082                    List<Layout> layouts = new ArrayList<Layout>();
1083    
1084                    for (long layoutId : layoutIds) {
1085                            Layout layout = getLayout(groupId, privateLayout, layoutId);
1086    
1087                            layouts.add(layout);
1088                    }
1089    
1090                    return layouts;
1091            }
1092    
1093            /**
1094             * Returns all the layouts that match the type and belong to the group.
1095             *
1096             * @param  groupId the primary key of the group
1097             * @param  privateLayout whether the layout is private to the group
1098             * @param  type the type of the layouts (optionally {@link
1099             *         com.liferay.portal.model.LayoutConstants#TYPE_PORTLET})
1100             * @return the matching layouts, or <code>null</code> if no matches were
1101             *         found
1102             * @throws SystemException if a system exception occurred
1103             */
1104            public List<Layout> getLayouts(
1105                            long groupId, boolean privateLayout, String type)
1106                    throws SystemException {
1107    
1108                    return layoutPersistence.findByG_P_T(groupId, privateLayout, type);
1109            }
1110    
1111            /**
1112             * Returns the layout references for all the layouts that belong to the
1113             * company and belong to the portlet that matches the preferences.
1114             *
1115             * @param  companyId the primary key of the company
1116             * @param  portletId the primary key of the portlet
1117             * @param  preferencesKey the portlet's preference key
1118             * @param  preferencesValue the portlet's preference value
1119             * @return the layout references of the matching layouts
1120             * @throws SystemException if a system exception occurred
1121             */
1122            public LayoutReference[] getLayouts(
1123                            long companyId, String portletId, String preferencesKey,
1124                            String preferencesValue)
1125                    throws SystemException {
1126    
1127                    List<LayoutReference> layoutReferences = layoutFinder.findByC_P_P(
1128                            companyId, portletId, preferencesKey, preferencesValue);
1129    
1130                    return layoutReferences.toArray(
1131                            new LayoutReference[layoutReferences.size()]);
1132            }
1133    
1134            public int getLayoutsByLayoutPrototypeUuidCount(String layoutPrototypeUuid)
1135                    throws SystemException {
1136    
1137                    return layoutPersistence.countByLayoutPrototypeUuid(
1138                            layoutPrototypeUuid);
1139            }
1140    
1141            public int getLayoutsCount(Group group, boolean privateLayout)
1142                    throws PortalException, SystemException {
1143    
1144                    LayoutSet layoutSet = layoutSetPersistence.findByG_P(
1145                            group.getGroupId(), privateLayout);
1146    
1147                    int count = layoutSet.getPageCount();
1148    
1149                    if (PropsValues.USER_GROUPS_COPY_LAYOUTS_TO_USER_PERSONAL_SITE &&
1150                            group.isUser()) {
1151    
1152                            List<UserGroup> userGroups = userPersistence.getUserGroups(
1153                                    group.getClassPK());
1154    
1155                            if (!userGroups.isEmpty()) {
1156                                    long userGroupClassNameId =
1157                                            classNameLocalService.getClassNameId(UserGroup.class);
1158    
1159                                    for (UserGroup userGroup : userGroups) {
1160                                            Group userGroupGroup = groupPersistence.findByC_C_C(
1161                                                    group.getCompanyId(), userGroupClassNameId,
1162                                                    userGroup.getUserGroupId());
1163    
1164                                            layoutSet = layoutSetPersistence.findByG_P(
1165                                                    userGroupGroup.getGroupId(), privateLayout);
1166    
1167                                            count += layoutSet.getPageCount();
1168                                    }
1169                            }
1170                    }
1171    
1172                    return count;
1173            }
1174    
1175            public int getLayoutsCount(User user, boolean privateLayout)
1176                    throws PortalException, SystemException {
1177    
1178                    long classNameId = classNameLocalService.getClassNameId(User.class);
1179    
1180                    Group group = groupPersistence.findByC_C_C(
1181                            user.getCompanyId(), classNameId, user.getUserId());
1182    
1183                    return getLayoutsCount(group, privateLayout);
1184            }
1185    
1186            /**
1187             * Returns the primary key to use for the next layout.
1188             *
1189             * @param  groupId the primary key of the group
1190             * @param  privateLayout whether the layout is private to the group
1191             * @return the primary key to use for the next layout
1192             * @throws SystemException if a system exception occurred
1193             */
1194            public long getNextLayoutId(long groupId, boolean privateLayout)
1195                    throws SystemException {
1196    
1197                    long nextLayoutId = counterLocalService.increment(
1198                            getCounterName(groupId, privateLayout));
1199    
1200                    if (nextLayoutId == 1) {
1201                            List<Layout> layouts = layoutPersistence.findByG_P(
1202                                    groupId, privateLayout, 0, 1, new LayoutComparator());
1203    
1204                            if (!layouts.isEmpty()) {
1205                                    Layout layout = layouts.get(0);
1206    
1207                                    nextLayoutId = layout.getLayoutId() + 1;
1208    
1209                                    counterLocalService.reset(
1210                                            getCounterName(groupId, privateLayout), nextLayoutId);
1211                            }
1212                    }
1213    
1214                    return nextLayoutId;
1215            }
1216    
1217            /**
1218             * Returns all the layouts whose friendly URLs are <code>null</code>
1219             *
1220             * @return all the layouts whose friendly URLs are <code>null</code>
1221             * @throws SystemException if a system exception occurred
1222             */
1223            public List<Layout> getNullFriendlyURLLayouts() throws SystemException {
1224                    return layoutFinder.findByNullFriendlyURL();
1225            }
1226    
1227            /**
1228             * Returns all the layouts within scope of the group
1229             *
1230             * @param  groupId the primary key of the group
1231             * @param  privateLayout whether the layout is private to the group
1232             * @return the layouts within scope of the group
1233             * @throws SystemException if a system exception occurred
1234             */
1235            public List<Layout> getScopeGroupLayouts(
1236                            long groupId, boolean privateLayout)
1237                    throws SystemException {
1238    
1239                    return layoutFinder.findByScopeGroup(groupId, privateLayout);
1240            }
1241    
1242            public boolean hasLayouts(Group group, boolean privateLayout)
1243                    throws PortalException, SystemException {
1244    
1245                    LayoutSet layoutSet = layoutSetPersistence.findByG_P(
1246                            group.getGroupId(), privateLayout);
1247    
1248                    if (layoutSet.getPageCount() > 0) {
1249                            return true;
1250                    }
1251    
1252                    if (PropsValues.USER_GROUPS_COPY_LAYOUTS_TO_USER_PERSONAL_SITE &&
1253                            group.isUser()) {
1254    
1255                            List<UserGroup> userGroups = userPersistence.getUserGroups(
1256                                    group.getClassPK());
1257    
1258                            if (!userGroups.isEmpty()) {
1259                                    long userGroupClassNameId =
1260                                            classNameLocalService.getClassNameId(UserGroup.class);
1261    
1262                                    for (UserGroup userGroup : userGroups) {
1263                                            Group userGroupGroup = groupPersistence.findByC_C_C(
1264                                                    group.getCompanyId(), userGroupClassNameId,
1265                                                    userGroup.getUserGroupId());
1266    
1267                                            layoutSet = layoutSetPersistence.findByG_P(
1268                                                    userGroupGroup.getGroupId(), privateLayout);
1269    
1270                                            if (layoutSet.getPageCount() > 0) {
1271                                                    return true;
1272                                            }
1273                                    }
1274                            }
1275                    }
1276    
1277                    return false;
1278            }
1279    
1280            /**
1281             * Returns <code>true</code> if the group has any layouts;
1282             * <code>false</code> otherwise.
1283             *
1284             * @param  groupId the primary key of the group
1285             * @param  privateLayout whether the layout is private to the group
1286             * @param  parentLayoutId the primary key of the parent layout
1287             * @return <code>true</code> if the group has any layouts;
1288             *         <code>false</code> otherwise
1289             * @throws SystemException if a system exception occurred
1290             */
1291            public boolean hasLayouts(
1292                            long groupId, boolean privateLayout, long parentLayoutId)
1293                    throws SystemException {
1294    
1295                    return layoutPersistence.countByG_P_P(
1296                            groupId, privateLayout, parentLayoutId) > 0;
1297            }
1298    
1299            public boolean hasLayouts(User user, boolean privateLayout)
1300                    throws PortalException, SystemException {
1301    
1302                    long classNameId = classNameLocalService.getClassNameId(User.class);
1303    
1304                    Group group = groupPersistence.findByC_C_C(
1305                            user.getCompanyId(), classNameId, user.getUserId());
1306    
1307                    return hasLayouts(group, privateLayout);
1308            }
1309    
1310            public boolean hasLayoutSetPrototypeLayout(
1311                            long layoutSetPrototypeId, String layoutUuid)
1312                    throws PortalException, SystemException {
1313    
1314                    LayoutSetPrototype layoutSetPrototype =
1315                            layoutSetPrototypeLocalService.getLayoutSetPrototype(
1316                                    layoutSetPrototypeId);
1317    
1318                    return hasLayoutSetPrototypeLayout(layoutSetPrototype, layoutUuid);
1319            }
1320    
1321            public boolean hasLayoutSetPrototypeLayout(
1322                            String layoutSetPrototypeUuid, String layoutUuid)
1323                    throws PortalException, SystemException {
1324    
1325                    LayoutSetPrototype layoutSetPrototype =
1326                            layoutSetPrototypeLocalService.getLayoutSetPrototypeByUuid(
1327                                    layoutSetPrototypeUuid);
1328    
1329                    return hasLayoutSetPrototypeLayout(layoutSetPrototype, layoutUuid);
1330            }
1331    
1332            /**
1333             * Imports the layouts from the byte array.
1334             *
1335             * @param  userId the primary key of the user
1336             * @param  groupId the primary key of the group
1337             * @param  privateLayout whether the layout is private to the group
1338             * @param  parameterMap the mapping of parameters indicating which
1339             *         information will be imported. For information on the keys used in
1340             *         the map see {@link
1341             *         com.liferay.portal.kernel.lar.PortletDataHandlerKeys}.
1342             * @param  bytes the byte array with the data
1343             * @throws PortalException if a group or user with the primary key could not
1344             *         be found, or if some other portal exception occurred
1345             * @throws SystemException if a system exception occurred
1346             * @see    com.liferay.portal.lar.LayoutImporter
1347             */
1348            public void importLayouts(
1349                            long userId, long groupId, boolean privateLayout,
1350                            Map<String, String[]> parameterMap, byte[] bytes)
1351                    throws PortalException, SystemException {
1352    
1353                    importLayouts(
1354                            userId, groupId, privateLayout, parameterMap,
1355                            new UnsyncByteArrayInputStream(bytes));
1356            }
1357    
1358            /**
1359             * Imports the layouts from the file.
1360             *
1361             * @param  userId the primary key of the user
1362             * @param  groupId the primary key of the group
1363             * @param  privateLayout whether the layout is private to the group
1364             * @param  parameterMap the mapping of parameters indicating which
1365             *         information will be imported. For information on the keys used in
1366             *         the map see {@link
1367             *         com.liferay.portal.kernel.lar.PortletDataHandlerKeys}.
1368             * @param  file the LAR file with the data
1369             * @throws PortalException if a group or user with the primary key could not
1370             *         be found, or if some other portal exception occurred
1371             * @throws SystemException if a system exception occurred
1372             * @see    com.liferay.portal.lar.LayoutImporter
1373             */
1374            public void importLayouts(
1375                            long userId, long groupId, boolean privateLayout,
1376                            Map<String, String[]> parameterMap, File file)
1377                    throws PortalException, SystemException {
1378    
1379                    try {
1380                            LayoutImporter layoutImporter = new LayoutImporter();
1381    
1382                            layoutImporter.importLayouts(
1383                                    userId, groupId, privateLayout, parameterMap, file);
1384                    }
1385                    catch (PortalException pe) {
1386                            Throwable cause = pe.getCause();
1387    
1388                            if (cause instanceof LocaleException) {
1389                                    throw (PortalException)cause;
1390                            }
1391    
1392                            throw pe;
1393                    }
1394                    catch (SystemException se) {
1395                            throw se;
1396                    }
1397                    catch (Exception e) {
1398                            throw new SystemException(e);
1399                    }
1400            }
1401    
1402            /**
1403             * Imports the layouts from the input stream.
1404             *
1405             * @param  userId the primary key of the user
1406             * @param  groupId the primary key of the group
1407             * @param  privateLayout whether the layout is private to the group
1408             * @param  parameterMap the mapping of parameters indicating which
1409             *         information will be imported. For information on the keys used in
1410             *         the map see {@link
1411             *         com.liferay.portal.kernel.lar.PortletDataHandlerKeys}.
1412             * @param  is the input stream
1413             * @throws PortalException if a group or user with the primary key could not
1414             *         be found, or if some other portal exception occurred
1415             * @throws SystemException if a system exception occurred
1416             * @see    com.liferay.portal.lar.LayoutImporter
1417             */
1418            public void importLayouts(
1419                            long userId, long groupId, boolean privateLayout,
1420                            Map<String, String[]> parameterMap, InputStream is)
1421                    throws PortalException, SystemException {
1422    
1423                    try {
1424                            File file = FileUtil.createTempFile("lar");
1425    
1426                            FileUtil.write(file, is);
1427    
1428                            importLayouts(userId, groupId, privateLayout, parameterMap, file);
1429                    }
1430                    catch (IOException ioe) {
1431                            throw new SystemException(ioe);
1432                    }
1433            }
1434    
1435            /**
1436             * Imports the portlet information (categories, permissions, ... etc.) from
1437             * the file.
1438             *
1439             * @param  userId the primary key of the user
1440             * @param  plid the primary key of the target layout
1441             * @param  groupId the primary key of the target group
1442             * @param  portletId the primary key of the portlet
1443             * @param  parameterMap the mapping of parameters indicating which
1444             *         information will be imported. For information on the keys used in
1445             *         the map see {@link
1446             *         com.liferay.portal.kernel.lar.PortletDataHandlerKeys}.
1447             * @param  file the LAR file with the data
1448             * @throws PortalException if a group, layout, portlet or user with the
1449             *         primary key could not be found
1450             * @throws SystemException if a system exception occurred
1451             */
1452            public void importPortletInfo(
1453                            long userId, long plid, long groupId, String portletId,
1454                            Map<String, String[]> parameterMap, File file)
1455                    throws PortalException, SystemException {
1456    
1457                    try {
1458                            PortletImporter portletImporter = new PortletImporter();
1459    
1460                            portletImporter.importPortletInfo(
1461                                    userId, plid, groupId, portletId, parameterMap, file);
1462                    }
1463                    catch (PortalException pe) {
1464                            Throwable cause = pe.getCause();
1465    
1466                            if (cause instanceof LocaleException) {
1467                                    throw (PortalException)cause;
1468                            }
1469    
1470                            throw pe;
1471                    }
1472                    catch (SystemException se) {
1473                            throw se;
1474                    }
1475                    catch (Exception e) {
1476                            throw new SystemException(e);
1477                    }
1478            }
1479    
1480            /**
1481             * Imports the portlet information (categories, permissions, ... etc.) from
1482             * the input stream.
1483             *
1484             * @param  userId the primary key of the user
1485             * @param  plid the primary key of the layout
1486             * @param  groupId the primary key of the group
1487             * @param  portletId the primary key of the portlet
1488             * @param  parameterMap the mapping of parameters indicating which
1489             *         information will be imported. For information on the keys used in
1490             *         the map see {@link
1491             *         com.liferay.portal.kernel.lar.PortletDataHandlerKeys}.
1492             * @param  is the input stream
1493             * @throws PortalException if a group, portlet, layout or user with the
1494             *         primary key could not be found
1495             * @throws SystemException if a system exception occurred
1496             */
1497            public void importPortletInfo(
1498                            long userId, long plid, long groupId, String portletId,
1499                            Map<String, String[]> parameterMap, InputStream is)
1500                    throws PortalException, SystemException {
1501    
1502                    try {
1503                            File file = FileUtil.createTempFile("lar");
1504    
1505                            FileUtil.write(file, is);
1506    
1507                            importPortletInfo(
1508                                    userId, plid, groupId, portletId, parameterMap, file);
1509                    }
1510                    catch (IOException ioe) {
1511                            throw new SystemException(ioe);
1512                    }
1513            }
1514    
1515            /**
1516             * Sets the layouts for the group, replacing and prioritizing all layouts of
1517             * the parent layout.
1518             *
1519             * @param  groupId the primary key of the group
1520             * @param  privateLayout whether the layout is private to the group
1521             * @param  parentLayoutId the primary key of the parent layout
1522             * @param  layoutIds the primary keys of the layouts
1523             * @param  serviceContext the service context
1524             * @throws PortalException if a group or layout with the primary key could
1525             *         not be found, if no layouts were specified, if the first layout
1526             *         was not page-able, if the first layout was hidden, or if some
1527             *         other portal exception occurred
1528             * @throws SystemException if a system exception occurred
1529             */
1530            public void setLayouts(
1531                            long groupId, boolean privateLayout, long parentLayoutId,
1532                            long[] layoutIds, ServiceContext serviceContext)
1533                    throws PortalException, SystemException {
1534    
1535                    if (layoutIds == null) {
1536                            return;
1537                    }
1538    
1539                    if (parentLayoutId == LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
1540                            if (layoutIds.length < 1) {
1541                                    throw new RequiredLayoutException(
1542                                            RequiredLayoutException.AT_LEAST_ONE);
1543                            }
1544    
1545                            Layout layout = layoutPersistence.findByG_P_L(
1546                                    groupId, privateLayout, layoutIds[0]);
1547    
1548                            if (!PortalUtil.isLayoutFirstPageable(layout.getType())) {
1549                                    throw new RequiredLayoutException(
1550                                            RequiredLayoutException.FIRST_LAYOUT_TYPE);
1551                            }
1552    
1553                            if (layout.isHidden()) {
1554                                    throw new RequiredLayoutException(
1555                                            RequiredLayoutException.FIRST_LAYOUT_HIDDEN);
1556                            }
1557                    }
1558    
1559                    Set<Long> layoutIdsSet = new LinkedHashSet<Long>();
1560    
1561                    for (long layoutId : layoutIds) {
1562                            layoutIdsSet.add(layoutId);
1563                    }
1564    
1565                    Set<Long> newLayoutIdsSet = new HashSet<Long>();
1566    
1567                    List<Layout> layouts = layoutPersistence.findByG_P_P(
1568                            groupId, privateLayout, parentLayoutId);
1569    
1570                    for (Layout layout : layouts) {
1571                            if (!layoutIdsSet.contains(layout.getLayoutId())) {
1572                                    deleteLayout(layout, true, serviceContext);
1573                            }
1574                            else {
1575                                    newLayoutIdsSet.add(layout.getLayoutId());
1576                            }
1577                    }
1578    
1579                    int priority = 0;
1580    
1581                    for (long layoutId : layoutIdsSet) {
1582                            Layout layout = layoutPersistence.findByG_P_L(
1583                                    groupId, privateLayout, layoutId);
1584    
1585                            layout.setPriority(priority++);
1586    
1587                            layoutPersistence.update(layout, false);
1588                    }
1589    
1590                    layoutSetLocalService.updatePageCount(groupId, privateLayout);
1591            }
1592    
1593            /**
1594             * Updates the friendly URL of the layout.
1595             *
1596             * @param  plid the primary key of the layout
1597             * @param  friendlyURL the friendly URL to be assigned
1598             * @return the updated layout
1599             * @throws PortalException if a group or layout with the primary key could
1600             *         not be found
1601             * @throws SystemException if a system exception occurred
1602             */
1603            public Layout updateFriendlyURL(long plid, String friendlyURL)
1604                    throws PortalException, SystemException {
1605    
1606                    Date now = new Date();
1607    
1608                    Layout layout = layoutPersistence.findByPrimaryKey(plid);
1609    
1610                    friendlyURL = getFriendlyURL(
1611                            layout.getGroupId(), layout.isPrivateLayout(), layout.getLayoutId(),
1612                            StringPool.BLANK, friendlyURL);
1613    
1614                    validateFriendlyURL(
1615                            layout.getGroupId(), layout.isPrivateLayout(), layout.getLayoutId(),
1616                            friendlyURL);
1617    
1618                    layout.setModifiedDate(now);
1619                    layout.setFriendlyURL(friendlyURL);
1620    
1621                    layoutPersistence.update(layout, false);
1622    
1623                    return layout;
1624            }
1625    
1626            /**
1627             * Updates the layout.
1628             *
1629             * @param  groupId the primary key of the group
1630             * @param  privateLayout whether the layout is private to the group
1631             * @param  layoutId the primary key of the layout
1632             * @param  parentLayoutId the primary key of the layout's new parent layout
1633             * @param  nameMap the locales and localized names to merge (optionally
1634             *         <code>null</code>)
1635             * @param  titleMap the locales and localized titles to merge (optionally
1636             *         <code>null</code>)
1637             * @param  descriptionMap the locales and localized descriptions to merge
1638             *         (optionally <code>null</code>)
1639             * @param  keywordsMap the locales and localized keywords to merge
1640             *         (optionally <code>null</code>)
1641             * @param  robotsMap the locales and localized robots to merge (optionally
1642             *         <code>null</code>)
1643             * @param  type the layout's new type (optionally {@link
1644             *         com.liferay.portal.model.LayoutConstants#TYPE_PORTLET})
1645             * @param  hidden whether the layout is hidden
1646             * @param  friendlyURL the layout's new friendly URL (optionally {@link
1647             *         com.liferay.portal.util.PropsValues#DEFAULT_USER_PRIVATE_LAYOUT_FRIENDLY_URL}
1648             *         or {@link
1649             *         com.liferay.portal.util.PropsValues#DEFAULT_USER_PRIVATE_LAYOUT_FRIENDLY_URL}).
1650             *         The default values can be overridden in
1651             *         <code>portal-ext.properties</code> by specifying new values for
1652             *         the corresponding properties defined in {@link
1653             *         com.liferay.portal.util.PropsValues}. To see how the URL is
1654             *         normalized when accessed see {@link
1655             *         com.liferay.portal.kernel.util.FriendlyURLNormalizerUtil#normalize(
1656             *         String)}.
1657             * @param  iconImage whether the icon image will be updated
1658             * @param  iconBytes the byte array of the layout's new icon image
1659             * @param  serviceContext the service context. Can set the modification date
1660             *         and expando bridge attributes for the layout. For layouts that
1661             *         are linked to a layout prototype, attributes named
1662             *         'layoutPrototypeUuid' and 'layoutPrototypeLinkedEnabled' can be
1663             *         specified to provide the unique identifier of the source
1664             *         prototype and a boolean to determined whether a link to it should
1665             *         be enabled to activate propagation of changes made to the linked
1666             *         page in the prototype.
1667             * @return the updated layout
1668             * @throws PortalException if a group or layout with the primary key could
1669             *         not be found, if a unique friendly URL could not be generated, if
1670             *         a valid parent layout ID to use could not be found, or if the
1671             *         layout parameters were invalid
1672             * @throws SystemException if a system exception occurred
1673             */
1674            public Layout updateLayout(
1675                            long groupId, boolean privateLayout, long layoutId,
1676                            long parentLayoutId, Map<Locale, String> nameMap,
1677                            Map<Locale, String> titleMap, Map<Locale, String> descriptionMap,
1678                            Map<Locale, String> keywordsMap, Map<Locale, String> robotsMap,
1679                            String type, boolean hidden, String friendlyURL, Boolean iconImage,
1680                            byte[] iconBytes, ServiceContext serviceContext)
1681                    throws PortalException, SystemException {
1682    
1683                    // Layout
1684    
1685                    parentLayoutId = getParentLayoutId(
1686                            groupId, privateLayout, parentLayoutId);
1687                    String name = nameMap.get(LocaleUtil.getDefault());
1688                    friendlyURL = getFriendlyURL(
1689                            groupId, privateLayout, layoutId, StringPool.BLANK, friendlyURL);
1690    
1691                    validate(
1692                            groupId, privateLayout, layoutId, parentLayoutId, name, type,
1693                            hidden, friendlyURL);
1694    
1695                    validateParentLayoutId(
1696                            groupId, privateLayout, layoutId, parentLayoutId);
1697    
1698                    Date now = new Date();
1699    
1700                    Layout layout = layoutPersistence.findByG_P_L(
1701                            groupId, privateLayout, layoutId);
1702    
1703                    List<Locale> modifiedLocales = LocalizationUtil.getModifiedLocales(
1704                            layout.getNameMap(), nameMap);
1705    
1706                    if (parentLayoutId != layout.getParentLayoutId()) {
1707                            int priority = getNextPriority(
1708                                    groupId, privateLayout, parentLayoutId,
1709                                    layout.getSourcePrototypeLayoutUuid(), -1);
1710    
1711                            layout.setPriority(priority);
1712                    }
1713    
1714                    layout.setModifiedDate(serviceContext.getModifiedDate(now));
1715                    layout.setParentLayoutId(parentLayoutId);
1716                    layout.setNameMap(nameMap);
1717                    layout.setTitleMap(titleMap);
1718                    layout.setDescriptionMap(descriptionMap);
1719                    layout.setKeywordsMap(keywordsMap);
1720                    layout.setRobotsMap(robotsMap);
1721                    layout.setType(type);
1722                    layout.setHidden(hidden);
1723                    layout.setFriendlyURL(friendlyURL);
1724    
1725                    if (iconImage != null) {
1726                            layout.setIconImage(iconImage.booleanValue());
1727    
1728                            if (iconImage.booleanValue()) {
1729                                    long iconImageId = layout.getIconImageId();
1730    
1731                                    if (iconImageId <= 0) {
1732                                            iconImageId = counterLocalService.increment();
1733    
1734                                            layout.setIconImageId(iconImageId);
1735                                    }
1736                            }
1737                    }
1738    
1739                    boolean layoutUpdateable = ParamUtil.getBoolean(
1740                            serviceContext, "layoutUpdateable", true);
1741    
1742                    UnicodeProperties typeSettingsProperties =
1743                            layout.getTypeSettingsProperties();
1744    
1745                    typeSettingsProperties.put(
1746                            "layoutUpdateable", String.valueOf(layoutUpdateable));
1747    
1748                    layout.setTypeSettingsProperties(typeSettingsProperties);
1749    
1750                    String layoutPrototypeUuid = ParamUtil.getString(
1751                            serviceContext, "layoutPrototypeUuid");
1752                    boolean layoutPrototypeLinkEnabled = ParamUtil.getBoolean(
1753                            serviceContext, "layoutPrototypeLinkEnabled");
1754    
1755                    if (Validator.isNotNull(layoutPrototypeUuid)) {
1756                            layout.setLayoutPrototypeUuid(layoutPrototypeUuid);
1757                            layout.setLayoutPrototypeLinkEnabled(layoutPrototypeLinkEnabled);
1758                    }
1759    
1760                    layoutPersistence.update(layout, false);
1761    
1762                    // Icon
1763    
1764                    if (iconImage != null) {
1765                            if (!iconImage.booleanValue()) {
1766                                    imageLocalService.deleteImage(layout.getIconImageId());
1767                            }
1768                            else if ((iconBytes != null) && (iconBytes.length > 0)) {
1769                                    imageLocalService.updateImage(
1770                                            layout.getIconImageId(), iconBytes);
1771                            }
1772                    }
1773    
1774                    // Portlet preferences
1775    
1776                    if (!modifiedLocales.isEmpty()) {
1777                            updateScopedPortletNames(
1778                                    groupId, privateLayout, layoutId, nameMap, modifiedLocales);
1779                    }
1780    
1781                    // Expando
1782    
1783                    ExpandoBridge expandoBridge = layout.getExpandoBridge();
1784    
1785                    expandoBridge.setAttributes(serviceContext);
1786    
1787                    return layout;
1788            }
1789    
1790            /**
1791             * Updates the layout replacing its type settings.
1792             *
1793             * @param  groupId the primary key of the group
1794             * @param  privateLayout whether the layout is private to the group
1795             * @param  layoutId the primary key of the layout
1796             * @param  typeSettings the settings to load the unicode properties object.
1797             *         See {@link com.liferay.portal.kernel.util.UnicodeProperties
1798             *         #fastLoad(String)}.
1799             * @return the updated layout
1800             * @throws PortalException if a matching layout could not be found
1801             * @throws SystemException if a system exception occurred
1802             */
1803            public Layout updateLayout(
1804                            long groupId, boolean privateLayout, long layoutId,
1805                            String typeSettings)
1806                    throws PortalException, SystemException {
1807    
1808                    Date now = new Date();
1809    
1810                    UnicodeProperties typeSettingsProperties = new UnicodeProperties();
1811    
1812                    typeSettingsProperties.fastLoad(typeSettings);
1813    
1814                    Layout layout = layoutPersistence.findByG_P_L(
1815                            groupId, privateLayout, layoutId);
1816    
1817                    layout.setModifiedDate(now);
1818                    layout.setTypeSettings(typeSettingsProperties.toString());
1819    
1820                    layoutPersistence.update(layout, false);
1821    
1822                    return layout;
1823            }
1824    
1825            /**
1826             * Updates the look and feel of the layout.
1827             *
1828             * @param  groupId the primary key of the group
1829             * @param  privateLayout whether the layout is private to the group
1830             * @param  layoutId the primary key of the layout
1831             * @param  themeId the primary key of the layout's new theme
1832             * @param  colorSchemeId the primary key of the layout's new color scheme
1833             * @param  css the layout's new CSS
1834             * @param  wapTheme whether the theme is for WAP browsers
1835             * @return the updated layout
1836             * @throws PortalException if a matching layout could not be found
1837             * @throws SystemException if a system exception occurred
1838             */
1839            public Layout updateLookAndFeel(
1840                            long groupId, boolean privateLayout, long layoutId, String themeId,
1841                            String colorSchemeId, String css, boolean wapTheme)
1842                    throws PortalException, SystemException {
1843    
1844                    Date now = new Date();
1845    
1846                    Layout layout = layoutPersistence.findByG_P_L(
1847                            groupId, privateLayout, layoutId);
1848    
1849                    layout.setModifiedDate(now);
1850    
1851                    if (wapTheme) {
1852                            layout.setWapThemeId(themeId);
1853                            layout.setWapColorSchemeId(colorSchemeId);
1854                    }
1855                    else {
1856                            layout.setThemeId(themeId);
1857                            layout.setColorSchemeId(colorSchemeId);
1858                            layout.setCss(css);
1859                    }
1860    
1861                    layoutPersistence.update(layout, false);
1862    
1863                    return layout;
1864            }
1865    
1866            /**
1867             * Updates the name of the layout.
1868             *
1869             * @param  layout the layout to be updated
1870             * @param  name the layout's new name
1871             * @param  languageId the primary key of the language. For more information
1872             *         see {@link java.util.Locale}.
1873             * @return the updated layout
1874             * @throws PortalException if the new name was <code>null</code>
1875             * @throws SystemException if a system exception occurred
1876             */
1877            public Layout updateName(Layout layout, String name, String languageId)
1878                    throws PortalException, SystemException {
1879    
1880                    Date now = new Date();
1881    
1882                    validateName(name, languageId);
1883    
1884                    layout.setModifiedDate(now);
1885                    layout.setName(name, LocaleUtil.fromLanguageId(languageId));
1886    
1887                    layoutPersistence.update(layout, false);
1888    
1889                    return layout;
1890            }
1891    
1892            /**
1893             * Updates the name of the layout matching the group, layout ID, and
1894             * privacy.
1895             *
1896             * @param  groupId the primary key of the group
1897             * @param  privateLayout whether the layout is private to the group
1898             * @param  layoutId the primary key of the layout
1899             * @param  name the layout's new name
1900             * @param  languageId the primary key of the language. For more information
1901             *         see {@link java.util.Locale}.
1902             * @return the updated layout
1903             * @throws PortalException if a matching layout could not be found or if the
1904             *         new name was <code>null</code>
1905             * @throws SystemException if a system exception occurred
1906             */
1907            public Layout updateName(
1908                            long groupId, boolean privateLayout, long layoutId, String name,
1909                            String languageId)
1910                    throws PortalException, SystemException {
1911    
1912                    Layout layout = layoutPersistence.findByG_P_L(
1913                            groupId, privateLayout, layoutId);
1914    
1915                    return layoutLocalService.updateName(layout, name, languageId);
1916            }
1917    
1918            /**
1919             * Updates the name of the layout matching the primary key.
1920             *
1921             * @param  plid the primary key of the layout
1922             * @param  name the name to be assigned
1923             * @param  languageId the primary key of the language. For more information
1924             *         see {@link java.util.Locale}.
1925             * @return the updated layout
1926             * @throws PortalException if a layout with the primary key could not be
1927             *         found or if the name was <code>null</code>
1928             * @throws SystemException if a system exception occurred
1929             */
1930            public Layout updateName(long plid, String name, String languageId)
1931                    throws PortalException, SystemException {
1932    
1933                    Layout layout = layoutPersistence.findByPrimaryKey(plid);
1934    
1935                    return layoutLocalService.updateName(layout, name, languageId);
1936            }
1937    
1938            /**
1939             * Updates the parent layout ID of the layout matching the group, layout ID,
1940             * and privacy.
1941             *
1942             * @param  groupId the primary key of the group
1943             * @param  privateLayout whether the layout is private to the group
1944             * @param  layoutId the primary key of the layout
1945             * @param  parentLayoutId the primary key to be assigned to the parent
1946             *         layout
1947             * @return the matching layout
1948             * @throws PortalException if a valid parent layout ID to use could not be
1949             *         found or if a matching layout could not be found
1950             * @throws SystemException if a system exception occurred
1951             */
1952            public Layout updateParentLayoutId(
1953                            long groupId, boolean privateLayout, long layoutId,
1954                            long parentLayoutId)
1955                    throws PortalException, SystemException {
1956    
1957                    parentLayoutId = getParentLayoutId(
1958                            groupId, privateLayout, parentLayoutId);
1959    
1960                    validateParentLayoutId(
1961                            groupId, privateLayout, layoutId, parentLayoutId);
1962    
1963                    Date now = new Date();
1964    
1965                    Layout layout = layoutPersistence.findByG_P_L(
1966                            groupId, privateLayout, layoutId);
1967    
1968                    if (parentLayoutId != layout.getParentLayoutId()) {
1969                            int priority = getNextPriority(
1970                                    groupId, privateLayout, parentLayoutId,
1971                                    layout.getSourcePrototypeLayoutUuid(), -1);
1972    
1973                            layout.setPriority(priority);
1974                    }
1975    
1976                    layout.setModifiedDate(now);
1977                    layout.setParentLayoutId(parentLayoutId);
1978    
1979                    layoutPersistence.update(layout, false);
1980    
1981                    return layout;
1982            }
1983    
1984            /**
1985             * Updates the parent layout ID of the layout matching the primary key. If a
1986             * layout matching the parent primary key is found, the layout ID of that
1987             * layout is assigned, otherwise {@link
1988             * com.liferay.portal.model.LayoutConstants#DEFAULT_PARENT_LAYOUT_ID} is
1989             * assigned.
1990             *
1991             * @param  plid the primary key of the layout
1992             * @param  parentPlid the primary key of the parent layout
1993             * @return the layout matching the primary key
1994             * @throws PortalException if a layout with the primary key could not be
1995             *         found or if a valid parent layout ID to use could not be found
1996             * @throws SystemException if a system exception occurred
1997             */
1998            public Layout updateParentLayoutId(long plid, long parentPlid)
1999                    throws PortalException, SystemException {
2000    
2001                    Date now = new Date();
2002    
2003                    Layout layout = layoutPersistence.findByPrimaryKey(plid);
2004    
2005                    long parentLayoutId = LayoutConstants.DEFAULT_PARENT_LAYOUT_ID;
2006    
2007                    if (parentPlid > 0) {
2008                            Layout parentLayout = layoutPersistence.fetchByPrimaryKey(
2009                                    parentPlid);
2010    
2011                            if (parentLayout != null) {
2012                                    parentLayoutId = parentLayout.getLayoutId();
2013                            }
2014                    }
2015    
2016                    parentLayoutId = getParentLayoutId(
2017                            layout.getGroupId(), layout.isPrivateLayout(), parentLayoutId);
2018    
2019                    validateParentLayoutId(
2020                            layout.getGroupId(), layout.isPrivateLayout(), layout.getLayoutId(),
2021                            parentLayoutId);
2022    
2023                    if (parentLayoutId != layout.getParentLayoutId()) {
2024                            int priority = getNextPriority(
2025                                    layout.getGroupId(), layout.isPrivateLayout(), parentLayoutId,
2026                                    layout.getSourcePrototypeLayoutUuid(), -1);
2027    
2028                            layout.setPriority(priority);
2029                    }
2030    
2031                    layout.setModifiedDate(now);
2032                    layout.setParentLayoutId(parentLayoutId);
2033    
2034                    layoutPersistence.update(layout, false);
2035    
2036                    return layout;
2037            }
2038    
2039            /**
2040             * Updates the priorities of the layouts.
2041             *
2042             * @param  groupId the primary key of the group
2043             * @param  privateLayout whether the layout is private to the group
2044             * @throws PortalException if a matching layout could not be found
2045             * @throws SystemException if a system exception occurred
2046             */
2047            public void updatePriorities(long groupId, boolean privateLayout)
2048                    throws PortalException, SystemException {
2049    
2050                    List<Layout> layouts = layoutPersistence.findByG_P(
2051                            groupId, privateLayout);
2052    
2053                    for (Layout layout : layouts) {
2054                            int nextPriority = getNextPriority(
2055                                    layout.getGroupId(), layout.isPrivateLayout(),
2056                                    layout.getParentLayoutId(),
2057                                    layout.getSourcePrototypeLayoutUuid(), layout.getPriority());
2058    
2059                            layout.setPriority(nextPriority);
2060    
2061                            layoutPersistence.update(layout, false);
2062                    }
2063            }
2064    
2065            /**
2066             * Updates the priority of the layout.
2067             *
2068             * @param  layout the layout to be updated
2069             * @param  priority the layout's new priority
2070             * @return the updated layout
2071             * @throws SystemException if a system exception occurred
2072             */
2073            public Layout updatePriority(Layout layout, int priority)
2074                    throws SystemException {
2075    
2076                    if (layout.getPriority() == priority) {
2077                            return layout;
2078                    }
2079    
2080                    Date now = new Date();
2081    
2082                    layout.setModifiedDate(now);
2083    
2084                    int oldPriority = layout.getPriority();
2085    
2086                    int nextPriority = getNextPriority(
2087                            layout.getGroupId(), layout.isPrivateLayout(),
2088                            layout.getParentLayoutId(), layout.getSourcePrototypeLayoutUuid(),
2089                            priority);
2090    
2091                    layout.setPriority(nextPriority);
2092    
2093                    layoutPersistence.update(layout, false);
2094    
2095                    List<Layout> layouts = layoutPersistence.findByG_P_P(
2096                            layout.getGroupId(), layout.isPrivateLayout(),
2097                            layout.getParentLayoutId());
2098    
2099                    boolean lessThan = false;
2100    
2101                    if (oldPriority < priority) {
2102                            lessThan = true;
2103                    }
2104    
2105                    layouts = ListUtil.sort(
2106                            layouts, new LayoutPriorityComparator(layout, lessThan));
2107    
2108                    priority = 0;
2109    
2110                    for (Layout curLayout : layouts) {
2111                            curLayout.setModifiedDate(now);
2112    
2113                            int curNextPriority = getNextPriority(
2114                                    layout.getGroupId(), layout.isPrivateLayout(),
2115                                    layout.getParentLayoutId(),
2116                                    curLayout.getSourcePrototypeLayoutUuid(), priority++);
2117    
2118                            curLayout.setPriority(curNextPriority);
2119    
2120                            layoutPersistence.update(curLayout, false);
2121    
2122                            if (curLayout.equals(layout)) {
2123                                    layout = curLayout;
2124                            }
2125                    }
2126    
2127                    return layout;
2128            }
2129    
2130            /**
2131             * Updates the priority of the layout matching the group, layout ID, and
2132             * privacy.
2133             *
2134             * @param  groupId the primary key of the group
2135             * @param  privateLayout whether the layout is private to the group
2136             * @param  layoutId the primary key of the layout
2137             * @param  priority the layout's new priority
2138             * @return the updated layout
2139             * @throws PortalException if a matching layout could not be found
2140             * @throws SystemException if a system exception occurred
2141             */
2142            public Layout updatePriority(
2143                            long groupId, boolean privateLayout, long layoutId, int priority)
2144                    throws PortalException, SystemException {
2145    
2146                    Layout layout = layoutPersistence.findByG_P_L(
2147                            groupId, privateLayout, layoutId);
2148    
2149                    return updatePriority(layout, priority);
2150            }
2151    
2152            /**
2153             * Updates the priority of the layout matching the primary key.
2154             *
2155             * @param  plid the primary key of the layout
2156             * @param  priority the layout's new priority
2157             * @return the updated layout
2158             * @throws PortalException if a layout with the primary key could not be
2159             *         found
2160             * @throws SystemException if a system exception occurred
2161             */
2162            public Layout updatePriority(long plid, int priority)
2163                    throws PortalException, SystemException {
2164    
2165                    Layout layout = layoutPersistence.findByPrimaryKey(plid);
2166    
2167                    return updatePriority(layout, priority);
2168            }
2169    
2170            public void updateScopedPortletNames(
2171                            long groupId, boolean privateLayout, long layoutId,
2172                            Map<Locale, String> nameMap, List<Locale> nameMapModifiedLocales)
2173                    throws PortalException, SystemException {
2174    
2175                    Layout layout = layoutPersistence.findByG_P_L(
2176                            groupId, privateLayout, layoutId);
2177    
2178                    DynamicQuery portletPreferencesDynamicQuery =
2179                            DynamicQueryFactoryUtil.forClass(
2180                                    PortletPreferences.class, PortletPreferencesImpl.TABLE_NAME,
2181                                    PACLClassLoaderUtil.getPortalClassLoader());
2182    
2183                    Property plidProperty = PropertyFactoryUtil.forName("plid");
2184    
2185                    DynamicQuery layoutDynamicQuery = DynamicQueryFactoryUtil.forClass(
2186                            Layout.class, LayoutImpl.TABLE_NAME,
2187                            PACLClassLoaderUtil.getPortalClassLoader());
2188    
2189                    Projection plidProjection = ProjectionFactoryUtil.property("plid");
2190    
2191                    layoutDynamicQuery.setProjection(plidProjection);
2192    
2193                    Property groupIdProperty = PropertyFactoryUtil.forName("groupId");
2194    
2195                    layoutDynamicQuery.add(groupIdProperty.eq(groupId));
2196    
2197                    Property privateLayoutProperty = PropertyFactoryUtil.forName(
2198                            "privateLayout");
2199    
2200                    layoutDynamicQuery.add(privateLayoutProperty.eq(privateLayout));
2201    
2202                    portletPreferencesDynamicQuery.add(plidProperty.in(layoutDynamicQuery));
2203    
2204                    Junction junction = RestrictionsFactoryUtil.disjunction();
2205    
2206                    List<Portlet> scopablePortlets =
2207                            portletLocalService.getScopablePortlets();
2208    
2209                    for (Portlet scopablePortlet :scopablePortlets) {
2210                            if (scopablePortlet.isInstanceable()) {
2211                                    Criterion criterion = RestrictionsFactoryUtil.like(
2212                                            "portletId",
2213                                            scopablePortlet.getPortletId() +
2214                                                    PortletConstants.INSTANCE_SEPARATOR +
2215                                                            StringPool.PERCENT);
2216    
2217                                    junction.add(criterion);
2218                            }
2219                            else {
2220                                    Criterion criterion = RestrictionsFactoryUtil.eq(
2221                                            "portletId", scopablePortlet.getPortletId());
2222    
2223                                    junction.add(criterion);
2224                            }
2225                    }
2226    
2227                    portletPreferencesDynamicQuery.add(junction);
2228    
2229                    List<PortletPreferences> portletPreferencesList =
2230                            portletPreferencesLocalService.dynamicQuery(
2231                                    portletPreferencesDynamicQuery);
2232    
2233                    for (PortletPreferences portletPreferences : portletPreferencesList) {
2234                            if (portletPreferences.getPortletId() == null) {
2235                                    continue;
2236                            }
2237    
2238                            Layout curLayout = layoutPersistence.findByPrimaryKey(
2239                                    portletPreferences.getPlid());
2240    
2241                            javax.portlet.PortletPreferences jxPreferences =
2242                                    PortletPreferencesFactoryUtil.getLayoutPortletSetup(
2243                                            curLayout, portletPreferences.getPortletId());
2244    
2245                            String scopeLayoutUuid = GetterUtil.getString(
2246                                    jxPreferences.getValue("lfrScopeLayoutUuid", null));
2247    
2248                            if (!scopeLayoutUuid.equals(layout.getUuid())) {
2249                                    continue;
2250                            }
2251    
2252                            for (Locale locale : nameMapModifiedLocales) {
2253                                    String languageId = LanguageUtil.getLanguageId(locale);
2254    
2255                                    String portletTitle = PortalUtil.getPortletTitle(
2256                                            PortletConstants.getRootPortletId(
2257                                                    portletPreferences.getPortletId()), languageId);
2258    
2259                                    String newPortletTitle = PortalUtil.getNewPortletTitle(
2260                                            portletTitle, curLayout.getName(languageId),
2261                                            nameMap.get(locale));
2262    
2263                                    if (newPortletTitle.equals(portletTitle)) {
2264                                            continue;
2265                                    }
2266    
2267                                    try {
2268                                            jxPreferences.setValue(
2269                                                    "portletSetupTitle_" + languageId, newPortletTitle);
2270                                            jxPreferences.setValue(
2271                                                    "portletSetupUseCustomTitle", Boolean.TRUE.toString());
2272    
2273                                            jxPreferences.store();
2274                                    }
2275                                    catch (IOException ioe) {
2276                                            throw new SystemException(ioe);
2277                                    }
2278                                    catch (PortletException pe) {
2279                                            throw new SystemException(pe);
2280                                    }
2281                            }
2282                    }
2283            }
2284    
2285            /**
2286             * Updates the names of the portlets within scope of the group, the scope of
2287             * the layout's universally unique identifier, and the privacy.
2288             *
2289             * @param  groupId the primary key of the group
2290             * @param  privateLayout whether the layout is private to the group
2291             * @param  layoutId the primary key of the layout whose universally unique
2292             *         identifier to match
2293             * @param  name the new name for the portlets
2294             * @param  languageId the primary key of the language
2295             * @throws PortalException if a matching layout could not be found
2296             * @throws SystemException if a system exception occurred
2297             * @see    com.liferay.portlet.portletconfiguration.action.EditScopeAction
2298             */
2299            public void updateScopedPortletNames(
2300                            long groupId, boolean privateLayout, long layoutId, String name,
2301                            String languageId)
2302                    throws PortalException, SystemException {
2303    
2304                    Map<Locale, String> map = new HashMap<Locale, String>();
2305    
2306                    Locale locale = LocaleUtil.fromLanguageId(languageId);
2307    
2308                    map.put(locale, name);
2309    
2310                    List<Locale> locales = new ArrayList<Locale>();
2311    
2312                    locales.add(locale);
2313    
2314                    updateScopedPortletNames(
2315                            groupId, privateLayout, layoutId, map, locales);
2316            }
2317    
2318            protected String getFriendlyURL(
2319                            long groupId, boolean privateLayout, long layoutId, String name,
2320                            String friendlyURL)
2321                    throws PortalException, SystemException {
2322    
2323                    friendlyURL = getFriendlyURL(friendlyURL);
2324    
2325                    if (Validator.isNull(friendlyURL)) {
2326                            friendlyURL = StringPool.SLASH + getFriendlyURL(name);
2327    
2328                            String originalFriendlyURL = friendlyURL;
2329    
2330                            for (int i = 1;; i++) {
2331                                    try {
2332                                            validateFriendlyURL(
2333                                                    groupId, privateLayout, layoutId, friendlyURL);
2334    
2335                                            break;
2336                                    }
2337                                    catch (LayoutFriendlyURLException lfurle) {
2338                                            int type = lfurle.getType();
2339    
2340                                            if (type == LayoutFriendlyURLException.DUPLICATE) {
2341                                                    friendlyURL = originalFriendlyURL + i;
2342                                            }
2343                                            else {
2344                                                    friendlyURL = StringPool.SLASH + layoutId;
2345    
2346                                                    break;
2347                                            }
2348                                    }
2349                            }
2350                    }
2351    
2352                    return friendlyURL;
2353            }
2354    
2355            protected String getFriendlyURL(String friendlyURL) {
2356                    return FriendlyURLNormalizerUtil.normalize(friendlyURL);
2357            }
2358    
2359            protected int getNextPriority(
2360                            long groupId, boolean privateLayout, long parentLayoutId,
2361                            String sourcePrototypeLayoutUuid, int defaultPriority)
2362                    throws SystemException {
2363    
2364                    try {
2365                            int priority = defaultPriority;
2366    
2367                            if (priority < 0) {
2368                                    Layout layout = layoutPersistence.findByG_P_P_First(
2369                                            groupId, privateLayout, parentLayoutId,
2370                                            new LayoutPriorityComparator(false));
2371    
2372                                    priority = layout.getPriority() + 1;
2373                            }
2374    
2375                            if ((priority < _PRIORITY_BUFFER) &&
2376                                    Validator.isNull(sourcePrototypeLayoutUuid)) {
2377    
2378                                    LayoutSet layoutSet = layoutSetPersistence.fetchByG_P(
2379                                            groupId, privateLayout);
2380    
2381                                    if (Validator.isNotNull(
2382                                                    layoutSet.getLayoutSetPrototypeUuid())) {
2383    
2384                                            priority = priority + _PRIORITY_BUFFER;
2385                                    }
2386                            }
2387    
2388                            return priority;
2389                    }
2390                    catch (NoSuchLayoutException nsle) {
2391                            return 0;
2392                    }
2393            }
2394    
2395            protected long getParentLayoutId(
2396                            long groupId, boolean privateLayout, long parentLayoutId)
2397                    throws SystemException {
2398    
2399                    if (parentLayoutId != LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
2400    
2401                            // Ensure parent layout exists
2402    
2403                            Layout parentLayout = layoutPersistence.fetchByG_P_L(
2404                                    groupId, privateLayout, parentLayoutId);
2405    
2406                            if (parentLayout == null) {
2407                                    parentLayoutId = LayoutConstants.DEFAULT_PARENT_LAYOUT_ID;
2408                            }
2409                    }
2410    
2411                    return parentLayoutId;
2412            }
2413    
2414            protected boolean hasLayoutSetPrototypeLayout(
2415                            LayoutSetPrototype layoutSetPrototype, String layoutUuid)
2416                    throws PortalException, SystemException {
2417    
2418                    Group group = layoutSetPrototype.getGroup();
2419    
2420                    Layout layout = layoutPersistence.fetchByUUID_G(
2421                            layoutUuid, group.getGroupId());
2422    
2423                    if (layout != null) {
2424                            return true;
2425                    }
2426    
2427                    return false;
2428            }
2429    
2430            protected void validate(
2431                            long groupId, boolean privateLayout, long layoutId,
2432                            long parentLayoutId, String name, String type, boolean hidden,
2433                            String friendlyURL)
2434                    throws PortalException, SystemException {
2435    
2436                    validateName(name);
2437    
2438                    boolean firstLayout = false;
2439    
2440                    if (parentLayoutId == LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
2441                            List<Layout> layouts = layoutPersistence.findByG_P_P(
2442                                    groupId, privateLayout, parentLayoutId, 0, 1);
2443    
2444                            if (layouts.size() == 0) {
2445                                    firstLayout = true;
2446                            }
2447                            else {
2448                                    long firstLayoutId = layouts.get(0).getLayoutId();
2449    
2450                                    if (firstLayoutId == layoutId) {
2451                                            firstLayout = true;
2452                                    }
2453                            }
2454                    }
2455    
2456                    if (firstLayout) {
2457                            validateFirstLayout(type);
2458                    }
2459    
2460                    if (!PortalUtil.isLayoutParentable(type)) {
2461                            if (layoutPersistence.countByG_P_P(
2462                                            groupId, privateLayout, layoutId) > 0) {
2463    
2464                                    throw new LayoutTypeException(
2465                                            LayoutTypeException.NOT_PARENTABLE);
2466                            }
2467                    }
2468    
2469                    validateFriendlyURL(groupId, privateLayout, layoutId, friendlyURL);
2470            }
2471    
2472            protected void validateFirstLayout(String type) throws PortalException {
2473                    if (Validator.isNull(type) || !PortalUtil.isLayoutFirstPageable(type)) {
2474                            LayoutTypeException lte = new LayoutTypeException(
2475                                    LayoutTypeException.FIRST_LAYOUT);
2476    
2477                            lte.setLayoutType(type);
2478    
2479                            throw lte;
2480                    }
2481            }
2482    
2483            protected void validateFriendlyURL(
2484                            long groupId, boolean privateLayout, long layoutId,
2485                            String friendlyURL)
2486                    throws PortalException, SystemException {
2487    
2488                    if (Validator.isNull(friendlyURL)) {
2489                            return;
2490                    }
2491    
2492                    int exceptionType = LayoutImpl.validateFriendlyURL(friendlyURL);
2493    
2494                    if (exceptionType != -1) {
2495                            throw new LayoutFriendlyURLException(exceptionType);
2496                    }
2497    
2498                    Layout layout = layoutPersistence.fetchByG_P_F(
2499                            groupId, privateLayout, friendlyURL);
2500    
2501                    if ((layout != null) && (layout.getLayoutId() != layoutId)) {
2502                            throw new LayoutFriendlyURLException(
2503                                    LayoutFriendlyURLException.DUPLICATE);
2504                    }
2505    
2506                    LayoutImpl.validateFriendlyURLKeyword(friendlyURL);
2507    
2508                    /*List<FriendlyURLMapper> friendlyURLMappers =
2509                            portletLocalService.getFriendlyURLMappers();
2510    
2511                    for (FriendlyURLMapper friendlyURLMapper : friendlyURLMappers) {
2512                            if (friendlyURL.indexOf(friendlyURLMapper.getMapping()) != -1) {
2513                                    LayoutFriendlyURLException lfurle =
2514                                            new LayoutFriendlyURLException(
2515                                                    LayoutFriendlyURLException.KEYWORD_CONFLICT);
2516    
2517                                    lfurle.setKeywordConflict(friendlyURLMapper.getMapping());
2518    
2519                                    throw lfurle;
2520                            }
2521                    }*/
2522    
2523                    String layoutIdFriendlyURL = friendlyURL.substring(1);
2524    
2525                    if (Validator.isNumber(layoutIdFriendlyURL) &&
2526                            !layoutIdFriendlyURL.equals(String.valueOf(layoutId))) {
2527    
2528                            LayoutFriendlyURLException lfurle = new LayoutFriendlyURLException(
2529                                    LayoutFriendlyURLException.POSSIBLE_DUPLICATE);
2530    
2531                            lfurle.setKeywordConflict(layoutIdFriendlyURL);
2532    
2533                            throw lfurle;
2534                    }
2535            }
2536    
2537            protected void validateName(String name) throws PortalException {
2538                    if (Validator.isNull(name)) {
2539                            throw new LayoutNameException();
2540                    }
2541            }
2542    
2543            protected void validateName(String name, String languageId)
2544                    throws PortalException {
2545    
2546                    String defaultLanguageId = LocaleUtil.toLanguageId(
2547                            LocaleUtil.getDefault());
2548    
2549                    if (defaultLanguageId.equals(languageId)) {
2550                            validateName(name);
2551                    }
2552            }
2553    
2554            protected void validateParentLayoutId(
2555                            long groupId, boolean privateLayout, long layoutId,
2556                            long parentLayoutId)
2557                    throws PortalException, SystemException {
2558    
2559                    Layout layout = layoutPersistence.findByG_P_L(
2560                            groupId, privateLayout, layoutId);
2561    
2562                    if (parentLayoutId != layout.getParentLayoutId()) {
2563    
2564                            // Layouts can always be moved to the root level
2565    
2566                            if (parentLayoutId == LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
2567                                    return;
2568                            }
2569    
2570                            // Layout cannot become a child of a layout that is not parentable
2571    
2572                            Layout parentLayout = layoutPersistence.findByG_P_L(
2573                                    groupId, privateLayout, parentLayoutId);
2574    
2575                            if (!PortalUtil.isLayoutParentable(parentLayout)) {
2576                                    throw new LayoutParentLayoutIdException(
2577                                            LayoutParentLayoutIdException.NOT_PARENTABLE);
2578                            }
2579    
2580                            // Layout cannot become descendant of itself
2581    
2582                            if (PortalUtil.isLayoutDescendant(layout, parentLayoutId)) {
2583                                    throw new LayoutParentLayoutIdException(
2584                                            LayoutParentLayoutIdException.SELF_DESCENDANT);
2585                            }
2586    
2587                            // If layout is moved, the new first layout must be valid
2588    
2589                            if (layout.getParentLayoutId() ==
2590                                            LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
2591    
2592                                    List<Layout> layouts = layoutPersistence.findByG_P_P(
2593                                            groupId, privateLayout,
2594                                            LayoutConstants.DEFAULT_PARENT_LAYOUT_ID, 0, 2);
2595    
2596                                    // You can only reach this point if there are more than two
2597                                    // layouts at the root level because of the descendant check
2598    
2599                                    long firstLayoutId = layouts.get(0).getLayoutId();
2600    
2601                                    if (firstLayoutId == layoutId) {
2602                                            Layout secondLayout = layouts.get(1);
2603    
2604                                            try {
2605                                                    validateFirstLayout(secondLayout.getType());
2606                                            }
2607                                            catch (LayoutHiddenException lhe) {
2608                                                    throw new LayoutParentLayoutIdException(
2609                                                            LayoutParentLayoutIdException.FIRST_LAYOUT_HIDDEN);
2610                                            }
2611                                            catch (LayoutTypeException lte) {
2612                                                    throw new LayoutParentLayoutIdException(
2613                                                            LayoutParentLayoutIdException.FIRST_LAYOUT_TYPE);
2614                                            }
2615                                    }
2616                            }
2617                    }
2618            }
2619    
2620            private static final int _PRIORITY_BUFFER = 1000000;
2621    
2622    }