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