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