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