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