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