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