001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.service.impl;
016    
017    import com.liferay.portal.NoSuchGroupException;
018    import com.liferay.portal.kernel.dao.orm.QueryUtil;
019    import com.liferay.portal.kernel.exception.PortalException;
020    import com.liferay.portal.kernel.exception.SystemException;
021    import com.liferay.portal.kernel.staging.StagingUtil;
022    import com.liferay.portal.kernel.util.ArrayUtil;
023    import com.liferay.portal.kernel.util.ListUtil;
024    import com.liferay.portal.kernel.util.MapUtil;
025    import com.liferay.portal.kernel.util.OrderByComparator;
026    import com.liferay.portal.kernel.util.UnicodeProperties;
027    import com.liferay.portal.kernel.util.UniqueList;
028    import com.liferay.portal.model.Group;
029    import com.liferay.portal.model.GroupConstants;
030    import com.liferay.portal.model.Organization;
031    import com.liferay.portal.model.Portlet;
032    import com.liferay.portal.model.User;
033    import com.liferay.portal.model.UserGroup;
034    import com.liferay.portal.security.auth.PrincipalException;
035    import com.liferay.portal.security.membershippolicy.SiteMembershipPolicyUtil;
036    import com.liferay.portal.security.permission.ActionKeys;
037    import com.liferay.portal.security.permission.PermissionChecker;
038    import com.liferay.portal.security.permission.PermissionCheckerFactoryUtil;
039    import com.liferay.portal.service.ServiceContext;
040    import com.liferay.portal.service.base.GroupServiceBaseImpl;
041    import com.liferay.portal.service.permission.GroupPermissionUtil;
042    import com.liferay.portal.service.permission.PortalPermissionUtil;
043    import com.liferay.portal.service.permission.PortletPermissionUtil;
044    import com.liferay.portal.service.permission.RolePermissionUtil;
045    import com.liferay.portal.service.permission.UserPermissionUtil;
046    import com.liferay.portal.util.PropsValues;
047    import com.liferay.portlet.asset.model.AssetCategory;
048    import com.liferay.portlet.asset.model.AssetTag;
049    import com.liferay.portlet.expando.model.ExpandoBridge;
050    
051    import java.io.Serializable;
052    
053    import java.util.ArrayList;
054    import java.util.Collection;
055    import java.util.Collections;
056    import java.util.Iterator;
057    import java.util.LinkedHashMap;
058    import java.util.List;
059    import java.util.Map;
060    
061    /**
062     * Provides the remote service for accessing, adding, deleting, and updating
063     * groups. Its methods include permission checks. Groups are mostly used in
064     * Liferay as a resource container for permissioning and content scoping
065     * purposes.
066     *
067     * @author Brian Wing Shun Chan
068     * @see    com.liferay.portal.service.impl.GroupLocalServiceImpl
069     */
070    public class GroupServiceImpl extends GroupServiceBaseImpl {
071    
072            /**
073             * Adds a group.
074             *
075             * @param  parentGroupId the primary key of the parent group
076             * @param  liveGroupId the primary key of the live group
077             * @param  name the entity's name
078             * @param  description the group's description (optionally
079             *         <code>null</code>)
080             * @param  type the group's type. For more information see {@link
081             *         com.liferay.portal.model.GroupConstants}
082             * @param  friendlyURL the group's friendlyURL (optionally
083             *         <code>null</code>)
084             * @param  site whether the group is to be associated with a main site
085             * @param  active whether the group is active
086             * @param  serviceContext the service context to be applied (optionally
087             *         <code>null</code>). Can set the asset category IDs and asset tag
088             *         names for the group, and can set whether the group is for staging
089             * @return the group
090             * @throws PortalException if the user did not have permission to add the
091             *         group, if a creator could not be found, if the group's
092             *         information was invalid, if a layout could not be found, or if a
093             *         valid friendly URL could not be created for the group
094             * @throws SystemException if a system exception occurred
095             */
096            @Override
097            public Group addGroup(
098                            long parentGroupId, long liveGroupId, String name,
099                            String description, int type, boolean manualMembership,
100                            int membershipRestriction, String friendlyURL, boolean site,
101                            boolean active, ServiceContext serviceContext)
102                    throws PortalException, SystemException {
103    
104                    if (parentGroupId == GroupConstants.DEFAULT_PARENT_GROUP_ID) {
105                            PortalPermissionUtil.check(
106                                    getPermissionChecker(), ActionKeys.ADD_COMMUNITY);
107                    }
108                    else {
109                            GroupPermissionUtil.check(
110                                    getPermissionChecker(), parentGroupId,
111                                    ActionKeys.ADD_COMMUNITY);
112                    }
113    
114                    Group group = groupLocalService.addGroup(
115                            getUserId(), parentGroupId, null, 0, liveGroupId, name, description,
116                            type, manualMembership, membershipRestriction, friendlyURL, site,
117                            active, serviceContext);
118    
119                    if (site) {
120                            SiteMembershipPolicyUtil.verifyPolicy(group);
121                    }
122    
123                    return group;
124            }
125    
126            /**
127             * Adds the group using the group default live group ID.
128             *
129             * @param      parentGroupId the primary key of the parent group
130             * @param      name the entity's name
131             * @param      description the group's description (optionally
132             *             <code>null</code>)
133             * @param      type the group's type. For more information see {@link
134             *             com.liferay.portal.model.GroupConstants}
135             * @param      friendlyURL the group's friendlyURL
136             * @param      site whether the group is to be associated with a main site
137             * @param      active whether the group is active
138             * @param      serviceContext the service context to be applied (optionally
139             *             <code>null</code>). Can set asset category IDs and asset tag
140             *             names for the group, and can set whether the group is for
141             *             staging
142             * @return     the group
143             * @throws     PortalException if the user did not have permission to add
144             *             the group, if a creator could not be found, if the group's
145             *             information was invalid, if a layout could not be found, or
146             *             if a valid friendly URL could not be created for the group
147             * @throws     SystemException if a system exception occurred
148             * @deprecated As of 6.2.0, replaced by {@link #addGroup(long, long, String,
149             *             String, int, boolean, int, String, boolean, boolean,
150             *             ServiceContext)}
151             */
152            @Override
153            public Group addGroup(
154                            long parentGroupId, String name, String description, int type,
155                            String friendlyURL, boolean site, boolean active,
156                            ServiceContext serviceContext)
157                    throws PortalException, SystemException {
158    
159                    return addGroup(
160                            parentGroupId, GroupConstants.DEFAULT_LIVE_GROUP_ID, name,
161                            description, type, true,
162                            GroupConstants.DEFAULT_MEMBERSHIP_RESTRICTION, friendlyURL, site,
163                            active, serviceContext);
164            }
165    
166            /**
167             * @deprecated As of 6.2.0, replaced by {@link #addGroup(long, String,
168             *             String, int, String, boolean, boolean, ServiceContext)}
169             */
170            @Override
171            public Group addGroup(
172                            String name, String description, int type, String friendlyURL,
173                            boolean site, boolean active, ServiceContext serviceContext)
174                    throws PortalException, SystemException {
175    
176                    return addGroup(
177                            GroupConstants.DEFAULT_PARENT_GROUP_ID, name, description, type,
178                            friendlyURL, site, active, serviceContext);
179            }
180    
181            /**
182             * Adds the groups to the role.
183             *
184             * @param  roleId the primary key of the role
185             * @param  groupIds the primary keys of the groups
186             * @throws PortalException if the user did not have permission to update the
187             *         role
188             * @throws SystemException if a system exception occurred
189             */
190            @Override
191            public void addRoleGroups(long roleId, long[] groupIds)
192                    throws PortalException, SystemException {
193    
194                    RolePermissionUtil.check(
195                            getPermissionChecker(), roleId, ActionKeys.UPDATE);
196    
197                    groupLocalService.addRoleGroups(roleId, groupIds);
198            }
199    
200            /**
201             * Checks that the current user is permitted to use the group for Remote
202             * Staging.
203             *
204             * @param  groupId the primary key of the group
205             * @throws PortalException if a group with the primary key could not be
206             *         found, if the current user did not have permission to view the
207             *         group, or if the group's company was different from the current
208             *         user's company
209             * @throws SystemException if a system exception occurred
210             */
211            @Override
212            public void checkRemoteStagingGroup(long groupId)
213                    throws PortalException, SystemException {
214    
215                    Group group = getGroup(groupId);
216    
217                    PermissionChecker permissionChecker = getPermissionChecker();
218    
219                    if (group.getCompanyId() != permissionChecker.getCompanyId()) {
220                            throw new NoSuchGroupException(
221                                    "Group " + groupId + " does not belong in company " +
222                                            permissionChecker.getCompanyId());
223                    }
224            }
225    
226            /**
227             * Deletes the group.
228             *
229             * <p>
230             * The group is unstaged and its assets and resources including layouts,
231             * membership requests, subscriptions, teams, blogs, bookmarks, calendar
232             * events, image gallery, journals, message boards, polls, shopping related
233             * entities, software catalog, and wikis are also deleted.
234             * </p>
235             *
236             * @param  groupId the primary key of the group
237             * @throws PortalException if the user did not have permission to delete the
238             *         group or its assets or resources, if a group with the primary key
239             *         could not be found, or if the group was a system group
240             * @throws SystemException if a system exception occurred
241             */
242            @Override
243            public void deleteGroup(long groupId)
244                    throws PortalException, SystemException {
245    
246                    GroupPermissionUtil.check(
247                            getPermissionChecker(), groupId, ActionKeys.DELETE);
248    
249                    groupLocalService.deleteGroup(groupId);
250            }
251    
252            @Override
253            public void disableStaging(long groupId)
254                    throws PortalException, SystemException {
255    
256                    Group group = groupLocalService.getGroup(groupId);
257    
258                    GroupPermissionUtil.check(
259                            getPermissionChecker(), group, ActionKeys.UPDATE);
260    
261                    groupLocalService.disableStaging(groupId);
262            }
263    
264            @Override
265            public void enableStaging(long groupId)
266                    throws PortalException, SystemException {
267    
268                    Group group = groupLocalService.getGroup(groupId);
269    
270                    GroupPermissionUtil.check(
271                            getPermissionChecker(), group, ActionKeys.UPDATE);
272    
273                    groupLocalService.enableStaging(groupId);
274            }
275    
276            /**
277             * Returns the company group.
278             *
279             * @param  companyId the primary key of the company
280             * @return the group associated with the company
281             * @throws PortalException if a matching group could not be found
282             * @throws SystemException if a system exception occurred
283             */
284            @Override
285            public Group getCompanyGroup(long companyId)
286                    throws PortalException, SystemException {
287    
288                    Group group = groupLocalService.getCompanyGroup(companyId);
289    
290                    GroupPermissionUtil.check(
291                            getPermissionChecker(), group.getGroupId(), ActionKeys.VIEW);
292    
293                    return group;
294            }
295    
296            /**
297             * Returns the group with the primary key.
298             *
299             * @param  groupId the primary key of the group
300             * @return the group with the primary key
301             * @throws PortalException if a group with the primary key could not be
302             *         found or if the current user did not have permission to view the
303             *         group
304             * @throws SystemException if a system exception occurred
305             */
306            @Override
307            public Group getGroup(long groupId)
308                    throws PortalException, SystemException {
309    
310                    GroupPermissionUtil.check(
311                            getPermissionChecker(), groupId, ActionKeys.VIEW);
312    
313                    return groupLocalService.getGroup(groupId);
314            }
315    
316            /**
317             * Returns the group with the name.
318             *
319             * @param  companyId the primary key of the company
320             * @param  name the group's name
321             * @return the group with the name
322             * @throws PortalException if a matching group could not be found or if the
323             *         current user did not have permission to view the group
324             * @throws SystemException if a system exception occurred
325             */
326            @Override
327            public Group getGroup(long companyId, String name)
328                    throws PortalException, SystemException {
329    
330                    Group group = groupLocalService.getGroup(companyId, name);
331    
332                    GroupPermissionUtil.check(
333                            getPermissionChecker(), group.getGroupId(), ActionKeys.VIEW);
334    
335                    return group;
336            }
337    
338            /**
339             * Returns all the groups that are direct children of the parent group.
340             *
341             * @param  companyId the primary key of the company
342             * @param  parentGroupId the primary key of the parent group
343             * @param  site whether the group is to be associated with a main site
344             * @return the matching groups, or <code>null</code> if no matches were
345             *         found
346             * @throws PortalException if the user did not have permission to view the
347             *         group or if a portal exception occurred
348             * @throws SystemException if a system exception occurred
349             */
350            @Override
351            public List<Group> getGroups(
352                            long companyId, long parentGroupId, boolean site)
353                    throws PortalException, SystemException {
354    
355                    return filterGroups(
356                            groupLocalService.getGroups(companyId, parentGroupId, site));
357            }
358    
359            /**
360             * Returns a range of all the site groups for which the user has control
361             * panel access.
362             *
363             * @param  portlets the portlets to manage
364             * @param  max the upper bound of the range of groups to consider (not
365             *         inclusive)
366             * @return the range of site groups for which the user has Control Panel
367             *         access
368             * @throws PortalException if a portal exception occurred
369             * @throws SystemException if a system exception occurred
370             */
371            @Override
372            public List<Group> getManageableSiteGroups(
373                            Collection<Portlet> portlets, int max)
374                    throws PortalException, SystemException {
375    
376                    PermissionChecker permissionChecker = getPermissionChecker();
377    
378                    if (permissionChecker.isCompanyAdmin()) {
379                            LinkedHashMap<String, Object> params =
380                                    new LinkedHashMap<String, Object>();
381    
382                            params.put("site", Boolean.TRUE);
383    
384                            return groupLocalService.search(
385                                    permissionChecker.getCompanyId(), null, null, null, params,
386                                    true, 0, max);
387                    }
388    
389                    List<Group> groups = new UniqueList<Group>();
390    
391                    List<Group> userSitesGroups = getUserSitesGroups(null, max);
392    
393                    Iterator<Group> itr = userSitesGroups.iterator();
394    
395                    while (itr.hasNext()) {
396                            Group group = itr.next();
397    
398                            if (group.isSite() &&
399                                    PortletPermissionUtil.hasControlPanelAccessPermission(
400                                            permissionChecker, group.getGroupId(), portlets)) {
401    
402                                    groups.add(group);
403                            }
404                    }
405    
406                    return groups;
407            }
408    
409            /**
410             * Returns a range of all the site groups for which the user has control
411             * panel access.
412             *
413             * @param      portlets the portlets to manage
414             * @param      max the upper bound of the range of groups to consider (not
415             *             inclusive)
416             * @return     the range of site groups for which the user has Control Panel
417             *             access
418             * @throws     PortalException if a portal exception occurred
419             * @throws     SystemException if a system exception occurred
420             * @deprecated As of 6.2.0, replaced by {@link
421             *             #getManageableSiteGroups(Collection, int)}
422             */
423            @Override
424            public List<Group> getManageableSites(Collection<Portlet> portlets, int max)
425                    throws PortalException, SystemException {
426    
427                    return getManageableSiteGroups(portlets, max);
428            }
429    
430            /**
431             * Returns the groups associated with the organizations.
432             *
433             * @param  organizations the organizations
434             * @return the groups associated with the organizations
435             * @throws PortalException if a portal exception occurred
436             * @throws SystemException if a system exception occurred
437             */
438            @Override
439            public List<Group> getOrganizationsGroups(List<Organization> organizations)
440                    throws PortalException, SystemException {
441    
442                    List<Group> groups = groupLocalService.getOrganizationsGroups(
443                            organizations);
444    
445                    return filterGroups(groups);
446            }
447    
448            /**
449             * Returns the group associated with the user.
450             *
451             * @param  companyId the primary key of the company
452             * @param  userId the primary key of the user
453             * @return the group associated with the user
454             * @throws PortalException if a matching group could not be found or if the
455             *         current user did not have permission to view the group
456             * @throws SystemException if a system exception occurred
457             */
458            @Override
459            public Group getUserGroup(long companyId, long userId)
460                    throws PortalException, SystemException {
461    
462                    Group group = groupLocalService.getUserGroup(companyId, userId);
463    
464                    GroupPermissionUtil.check(
465                            getPermissionChecker(), group.getGroupId(), ActionKeys.VIEW);
466    
467                    return group;
468            }
469    
470            /**
471             * Returns the groups associated with the user groups.
472             *
473             * @param  userGroups the user groups
474             * @return the groups associated with the user groups
475             * @throws PortalException if any one of the user group's group could not be
476             *         found
477             * @throws SystemException if a system exception occurred
478             */
479            @Override
480            public List<Group> getUserGroupsGroups(List<UserGroup> userGroups)
481                    throws PortalException, SystemException {
482    
483                    List<Group> groups = groupLocalService.getUserGroupsGroups(userGroups);
484    
485                    return filterGroups(groups);
486            }
487    
488            /**
489             * Returns the range of all groups associated with the user's organization
490             * groups, including the ancestors of the organization groups, unless portal
491             * property <code>organizations.membership.strict</code> is set to
492             * <code>true</code>.
493             *
494             * <p>
495             * Useful when paginating results. Returns a maximum of <code>end -
496             * start</code> instances. <code>start</code> and <code>end</code> are not
497             * primary keys, they are indexes in the result set. Thus, <code>0</code>
498             * refers to the first result in the set. Setting both <code>start</code>
499             * and <code>end</code> to {@link
500             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
501             * result set.
502             * </p>
503             *
504             * @param  userId the primary key of the user
505             * @param  start the lower bound of the range of groups to consider
506             * @param  end the upper bound of the range of groups to consider (not
507             *         inclusive)
508             * @return the range of groups associated with the user's organizations
509             * @throws PortalException if a user with the primary key could not be found
510             *         or if another portal exception occurred
511             * @throws SystemException if a system exception occurred
512             */
513            @Override
514            public List<Group> getUserOrganizationsGroups(
515                            long userId, int start, int end)
516                    throws PortalException, SystemException {
517    
518                    List<Group> groups = groupLocalService.getUserOrganizationsGroups(
519                            userId, start, end);
520    
521                    return filterGroups(groups);
522            }
523    
524            /**
525             * @deprecated As of 6.2.0, replaced by {@link #getUserSitesGroups(long,
526             *             String[], boolean, int)}
527             */
528            @Override
529            public List<Group> getUserPlaces(
530                            long userId, String[] classNames, boolean includeControlPanel,
531                            int max)
532                    throws PortalException, SystemException {
533    
534                    return getUserSitesGroups(userId, classNames, includeControlPanel, max);
535            }
536    
537            /**
538             * Returns the user's groups &quot;sites&quot; associated with the group
539             * entity class names, including the Control Panel group if the user is
540             * permitted to view the Control Panel.
541             *
542             * <ul>
543             * <li>
544             * Class name &quot;User&quot; includes the user's layout set
545             * group.
546             * </li>
547             * <li>
548             * Class name &quot;Organization&quot; includes the user's
549             * immediate organization groups and inherited organization groups.
550             * </li>
551             * <li>
552             * Class name &quot;Group&quot; includes the user's immediate
553             * organization groups and site groups.
554             * </li>
555             * <li>
556             * A <code>classNames</code>
557             * value of <code>null</code> includes the user's layout set group,
558             * organization groups, inherited organization groups, and site groups.
559             * </li>
560             * </ul>
561             *
562             * @param      userId the primary key of the user
563             * @param      classNames the group entity class names (optionally
564             *             <code>null</code>). For more information see {@link
565             *             #getUserSitesGroups(long, String[], int)}
566             * @param      max the maximum number of groups to return
567             * @return     the user's groups &quot;sites&quot;
568             * @throws     PortalException if a portal exception occurred
569             * @throws     SystemException if a system exception occurred
570             * @deprecated As of 6.2.0, replaced by {@link #getUserSitesGroups(long,
571             *             String[], int)}
572             */
573            @Override
574            public List<Group> getUserPlaces(long userId, String[] classNames, int max)
575                    throws PortalException, SystemException {
576    
577                    return getUserSitesGroups(userId, classNames, max);
578            }
579    
580            /**
581             * Returns the guest or current user's groups &quot;sites&quot; associated
582             * with the group entity class names, including the Control Panel group if
583             * the user is permitted to view the Control Panel.
584             *
585             * <ul>
586             * <li>
587             * Class name &quot;User&quot; includes the user's layout set
588             * group.
589             * </li>
590             * <li>
591             * Class name &quot;Organization&quot; includes the user's
592             * immediate organization groups and inherited organization groups.
593             * </li>
594             * <li>
595             * Class name &quot;Group&quot; includes the user's immediate
596             * organization groups and site groups.
597             * </li>
598             * <li>
599             * A <code>classNames</code>
600             * value of <code>null</code> includes the user's layout set group,
601             * organization groups, inherited organization groups, and site groups.
602             * </li>
603             * </ul>
604             *
605             * @param      classNames the group entity class names (optionally
606             *             <code>null</code>). For more information see {@link
607             *             #getUserSitesGroups(String[], int)}
608             * @param      max the maximum number of groups to return
609             * @return     the user's groups &quot;sites&quot;
610             * @throws     PortalException if a portal exception occurred
611             * @throws     SystemException if a system exception occurred
612             * @deprecated As of 6.2.0, replaced by {@link #getUserSitesGroups(
613             *             String[], int)}
614             */
615            @Override
616            public List<Group> getUserPlaces(String[] classNames, int max)
617                    throws PortalException, SystemException {
618    
619                    return getUserSitesGroups(classNames, max);
620            }
621    
622            /**
623             * Returns the number of the guest or current user's groups
624             * &quot;sites&quot; associated with the group entity class names, including
625             * the Control Panel group if the user is permitted to view the Control
626             * Panel.
627             *
628             * @return     the number of user's groups &quot;sites&quot;
629             * @throws     PortalException if a portal exception occurred
630             * @throws     SystemException if a system exception occurred
631             * @deprecated As of 6.2.0, replaced by {@link #getUserSitesGroupsCount()}
632             */
633            @Override
634            public int getUserPlacesCount() throws PortalException, SystemException {
635                    return getUserSitesGroupsCount();
636            }
637    
638            /**
639             * Returns the guest or current user's layout set group, organization
640             * groups, inherited organization groups, and site groups.
641             *
642             * @return     the user's layout set group, organization groups, and
643             *             inherited organization groups, and site groups
644             * @throws     PortalException if a portal exception occurred
645             * @throws     SystemException if a system exception occurred
646             * @deprecated As of 6.2.0, replaced by {@link #getUserSitesGroups}
647             */
648            @Override
649            public List<Group> getUserSites() throws PortalException, SystemException {
650                    return getUserSitesGroups();
651            }
652    
653            @Override
654            public List<Group> getUserSitesGroups()
655                    throws PortalException, SystemException {
656    
657                    return getUserSitesGroups(null, QueryUtil.ALL_POS);
658            }
659    
660            @Override
661            public List<Group> getUserSitesGroups(
662                            long userId, String[] classNames, boolean includeControlPanel,
663                            int max)
664                    throws PortalException, SystemException {
665    
666                    User user = userPersistence.fetchByPrimaryKey(userId);
667    
668                    if (user.isDefaultUser()) {
669                            return Collections.emptyList();
670                    }
671    
672                    List<Group> userSiteGroups = new UniqueList<Group>();
673    
674                    int start = QueryUtil.ALL_POS;
675                    int end = QueryUtil.ALL_POS;
676    
677                    if (max != QueryUtil.ALL_POS) {
678                            start = 0;
679                            end = max;
680                    }
681    
682                    if ((classNames == null) ||
683                            ArrayUtil.contains(classNames, Group.class.getName())) {
684    
685                            LinkedHashMap<String, Object> groupParams =
686                                    new LinkedHashMap<String, Object>();
687    
688                            groupParams.put("active", true);
689                            groupParams.put("usersGroups", userId);
690    
691                            userSiteGroups.addAll(
692                                    groupLocalService.search(
693                                            user.getCompanyId(), null, groupParams, start, end));
694                    }
695    
696                    if ((classNames == null) ||
697                            ArrayUtil.contains(classNames, Organization.class.getName())) {
698    
699                            List<Organization> userOrgs =
700                                    organizationLocalService.getOrganizations(
701                                            userId, start, end, null);
702    
703                            for (Organization organization : userOrgs) {
704                                    if (!organization.hasPrivateLayouts() &&
705                                            !organization.hasPublicLayouts()) {
706    
707                                            userSiteGroups.remove(organization.getGroup());
708                                    }
709                                    else {
710                                            userSiteGroups.add(0, organization.getGroup());
711                                    }
712    
713                                    if (!PropsValues.ORGANIZATIONS_MEMBERSHIP_STRICT) {
714                                            for (Organization ancestorOrganization :
715                                                            organization.getAncestors()) {
716    
717                                                    if (!ancestorOrganization.hasPrivateLayouts() &&
718                                                            !ancestorOrganization.hasPublicLayouts()) {
719    
720                                                            continue;
721                                                    }
722    
723                                                    userSiteGroups.add(0, ancestorOrganization.getGroup());
724                                            }
725                                    }
726                            }
727                    }
728    
729                    if ((classNames == null) ||
730                            ArrayUtil.contains(classNames, User.class.getName())) {
731    
732                            if (PropsValues.LAYOUT_USER_PRIVATE_LAYOUTS_ENABLED ||
733                                    PropsValues.LAYOUT_USER_PUBLIC_LAYOUTS_ENABLED) {
734    
735                                    Group userGroup = user.getGroup();
736    
737                                    userSiteGroups.add(0, userGroup);
738                            }
739                    }
740    
741                    PermissionChecker permissionChecker = getPermissionChecker();
742    
743                    if (permissionChecker.getUserId() != userId) {
744                            try {
745                                    permissionChecker = PermissionCheckerFactoryUtil.create(user);
746                            }
747                            catch (Exception e) {
748                                    throw new PrincipalException(e);
749                            }
750                    }
751    
752                    if (includeControlPanel &&
753                            PortalPermissionUtil.contains(
754                                    permissionChecker, ActionKeys.VIEW_CONTROL_PANEL)) {
755    
756                            Group controlPanelGroup = groupLocalService.getGroup(
757                                    user.getCompanyId(), GroupConstants.CONTROL_PANEL);
758    
759                            userSiteGroups.add(0, controlPanelGroup);
760                    }
761    
762                    return Collections.unmodifiableList(
763                            ListUtil.subList(userSiteGroups, start, end));
764            }
765    
766            /**
767             * Returns the user's groups &quot;sites&quot; associated with the group
768             * entity class names, including the Control Panel group if the user is
769             * permitted to view the Control Panel.
770             *
771             * <ul>
772             * <li>
773             * Class name &quot;User&quot; includes the user's layout set
774             * group.
775             * </li>
776             * <li>
777             * Class name &quot;Organization&quot; includes the user's
778             * immediate organization groups and inherited organization groups.
779             * </li>
780             * <li>
781             * Class name &quot;Group&quot; includes the user's immediate
782             * organization groups and site groups.
783             * </li>
784             * <li>
785             * A <code>classNames</code>
786             * value of <code>null</code> includes the user's layout set group,
787             * organization groups, inherited organization groups, and site groups.
788             * </li>
789             * </ul>
790             *
791             * @param  userId the primary key of the user
792             * @param  classNames the group entity class names (optionally
793             *         <code>null</code>). For more information see {@link
794             *         #getUserSitesGroups(long, String[], boolean, int)}
795             * @param  max the maximum number of groups to return
796             * @return the user's groups &quot;sites&quot;
797             * @throws PortalException if a portal exception occurred
798             * @throws SystemException if a system exception occurred
799             */
800            @Override
801            public List<Group> getUserSitesGroups(
802                            long userId, String[] classNames, int max)
803                    throws PortalException, SystemException {
804    
805                    return getUserSitesGroups(userId, classNames, false, max);
806            }
807    
808            /**
809             * Returns the guest or current user's groups &quot;sites&quot; associated
810             * with the group entity class names, including the Control Panel group if
811             * the user is permitted to view the Control Panel.
812             *
813             * <ul>
814             * <li>
815             * Class name &quot;User&quot; includes the user's layout set
816             * group.
817             * </li>
818             * <li>
819             * Class name &quot;Organization&quot; includes the user's
820             * immediate organization groups and inherited organization groups.
821             * </li>
822             * <li>
823             * Class name &quot;Group&quot; includes the user's immediate
824             * organization groups and site groups.
825             * </li>
826             * <li>
827             * A <code>classNames</code>
828             * value of <code>null</code> includes the user's layout set group,
829             * organization groups, inherited organization groups, and site groups.
830             * </li>
831             * </ul>
832             *
833             * @param  classNames the group entity class names (optionally
834             *         <code>null</code>). For more information see {@link
835             *         #getUserSitesGroups(long, String[], boolean, int)}
836             * @param  max the maximum number of groups to return
837             * @return the user's groups &quot;sites&quot;
838             * @throws PortalException if a portal exception occurred
839             * @throws SystemException if a system exception occurred
840             */
841            @Override
842            public List<Group> getUserSitesGroups(String[] classNames, int max)
843                    throws PortalException, SystemException {
844    
845                    return getUserSitesGroups(getGuestOrUserId(), classNames, false, max);
846            }
847    
848            /**
849             * Returns the number of the guest or current user's groups
850             * &quot;sites&quot; associated with the group entity class names, including
851             * the Control Panel group if the user is permitted to view the Control
852             * Panel.
853             *
854             * @return the number of user's groups &quot;sites&quot;
855             * @throws PortalException if a portal exception occurred
856             * @throws SystemException if a system exception occurred
857             */
858            @Override
859            public int getUserSitesGroupsCount()
860                    throws PortalException, SystemException {
861    
862                    List<Group> userSitesGroups = getUserSitesGroups(
863                            getGuestOrUserId(), null, true, QueryUtil.ALL_POS);
864    
865                    return userSitesGroups.size();
866            }
867    
868            /**
869             * Returns <code>true</code> if the user is associated with the group,
870             * including the user's inherited organizations and user groups. System and
871             * staged groups are not included.
872             *
873             * @param  userId the primary key of the user
874             * @param  groupId the primary key of the group
875             * @return <code>true</code> if the user is associated with the group;
876             *         <code>false</code> otherwise
877             * @throws PortalException if the current user did not have permission to
878             *         view the user or group members
879             * @throws SystemException if a system exception occurred
880             */
881            @Override
882            public boolean hasUserGroup(long userId, long groupId)
883                    throws PortalException, SystemException {
884    
885                    try {
886                            UserPermissionUtil.check(
887                                    getPermissionChecker(), userId, ActionKeys.VIEW);
888                    }
889                    catch (PrincipalException pe) {
890                            GroupPermissionUtil.check(
891                                    getPermissionChecker(), groupId, ActionKeys.VIEW_MEMBERS);
892                    }
893    
894                    return groupLocalService.hasUserGroup(userId, groupId);
895            }
896    
897            @Override
898            public List<Group> search(
899                            long companyId, long[] classNameIds, String keywords,
900                            LinkedHashMap<String, Object> params, int start, int end,
901                            OrderByComparator obc)
902                    throws PortalException, SystemException {
903    
904                    List<Group> groups = groupLocalService.search(
905                            companyId, classNameIds, keywords, params, start, end, obc);
906    
907                    return filterGroups(groups);
908            }
909    
910            @Override
911            public List<Group> search(
912                            long companyId, long[] classNameIds, String name,
913                            String description, LinkedHashMap<String, Object> params,
914                            boolean andOperator, int start, int end, OrderByComparator obc)
915                    throws PortalException, SystemException {
916    
917                    List<Group> groups = groupLocalService.search(
918                            companyId, classNameIds, name, description, params, andOperator,
919                            start, end, obc);
920    
921                    return filterGroups(groups);
922            }
923    
924            /**
925             * Returns an ordered range of all the site groups and organization groups
926             * that match the name and description, optionally including the user's
927             * inherited organization groups and user groups. System and staged groups
928             * are not included.
929             *
930             * <p>
931             * Useful when paginating results. Returns a maximum of <code>end -
932             * start</code> instances. <code>start</code> and <code>end</code> are not
933             * primary keys, they are indexes in the result set. Thus, <code>0</code>
934             * refers to the first result in the set. Setting both <code>start</code>
935             * and <code>end</code> to {@link
936             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
937             * result set.
938             * </p>
939             *
940             * @param  companyId the primary key of the company
941             * @param  name the group's name (optionally <code>null</code>)
942             * @param  description the group's description (optionally
943             *         <code>null</code>)
944             * @param  params the finder params (optionally <code>null</code>). To
945             *         include the user's inherited organizations and user groups in the
946             *         search, add entries having &quot;usersGroups&quot; and
947             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
948             *         information see {@link
949             *         com.liferay.portal.service.persistence.GroupFinder}
950             * @param  start the lower bound of the range of groups to return
951             * @param  end the upper bound of the range of groups to return (not
952             *         inclusive)
953             * @return the matching groups ordered by name
954             * @throws PortalException if a portal exception occurred
955             * @throws SystemException if a system exception occurred
956             */
957            @Override
958            public List<Group> search(
959                            long companyId, String name, String description, String[] params,
960                            int start, int end)
961                    throws PortalException, SystemException {
962    
963                    if (params == null) {
964                            params = new String[0];
965                    }
966    
967                    LinkedHashMap<String, Object> paramsObj = MapUtil.toLinkedHashMap(
968                            params);
969    
970                    List<Group> groups = groupLocalService.search(
971                            companyId, name, description, paramsObj, true, start, end);
972    
973                    return filterGroups(groups);
974            }
975    
976            /**
977             * Returns the number of groups and organization groups that match the name
978             * and description, optionally including the user's inherited organizations
979             * and user groups. System and staged groups are not included.
980             *
981             * @param  companyId the primary key of the company
982             * @param  name the group's name (optionally <code>null</code>)
983             * @param  description the group's description (optionally
984             *         <code>null</code>)
985             * @param  params the finder params (optionally <code>null</code>). To
986             *         include the user's inherited organizations and user groups in the
987             *         search, add entries having &quot;usersGroups&quot; and
988             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
989             *         information see {@link
990             *         com.liferay.portal.service.persistence.GroupFinder}
991             * @return the number of matching groups
992             * @throws SystemException if a system exception occurred
993             */
994            @Override
995            public int searchCount(
996                            long companyId, String name, String description, String[] params)
997                    throws SystemException {
998    
999                    if (params == null) {
1000                            params = new String[0];
1001                    }
1002    
1003                    LinkedHashMap<String, Object> paramsObj = MapUtil.toLinkedHashMap(
1004                            params);
1005    
1006                    return groupLocalService.searchCount(
1007                            companyId, name, description, paramsObj, true);
1008            }
1009    
1010            /**
1011             * Sets the groups associated with the role, removing and adding
1012             * associations as necessary.
1013             *
1014             * @param  roleId the primary key of the role
1015             * @param  groupIds the primary keys of the groups
1016             * @throws PortalException if the user did not have permission to update
1017             *         update the role
1018             * @throws SystemException if a system exception occurred
1019             */
1020            @Override
1021            public void setRoleGroups(long roleId, long[] groupIds)
1022                    throws PortalException, SystemException {
1023    
1024                    RolePermissionUtil.check(
1025                            getPermissionChecker(), roleId, ActionKeys.ASSIGN_MEMBERS);
1026    
1027                    groupLocalService.setRoleGroups(roleId, groupIds);
1028            }
1029    
1030            /**
1031             * Removes the groups from the role.
1032             *
1033             * @param  roleId the primary key of the role
1034             * @param  groupIds the primary keys of the groups
1035             * @throws PortalException if the user did not have permission to update the
1036             *         role
1037             * @throws SystemException if a system exception occurred
1038             */
1039            @Override
1040            public void unsetRoleGroups(long roleId, long[] groupIds)
1041                    throws PortalException, SystemException {
1042    
1043                    RolePermissionUtil.check(
1044                            getPermissionChecker(), roleId, ActionKeys.ASSIGN_MEMBERS);
1045    
1046                    groupLocalService.unsetRoleGroups(roleId, groupIds);
1047            }
1048    
1049            /**
1050             * Updates the group's friendly URL.
1051             *
1052             * @param  groupId the primary key of the group
1053             * @param  friendlyURL the group's new friendlyURL (optionally
1054             *         <code>null</code>)
1055             * @return the group
1056             * @throws PortalException if the user did not have permission to update the
1057             *         group, if a group with the primary key could not be found, or if
1058             *         a valid friendly URL could not be created for the group
1059             * @throws SystemException if a system exception occurred
1060             */
1061            @Override
1062            public Group updateFriendlyURL(long groupId, String friendlyURL)
1063                    throws PortalException, SystemException {
1064    
1065                    GroupPermissionUtil.check(
1066                            getPermissionChecker(), groupId, ActionKeys.UPDATE);
1067    
1068                    return groupLocalService.updateFriendlyURL(groupId, friendlyURL);
1069            }
1070    
1071            /**
1072             * Updates the group.
1073             *
1074             * @param  groupId the primary key of the group
1075             * @param  parentGroupId the primary key of the parent group
1076             * @param  name the group's new name
1077             * @param  description the group's new description (optionally
1078             *         <code>null</code>)
1079             * @param  type the group's new type. For more information see {@link
1080             *         com.liferay.portal.model.GroupConstants}
1081             * @param  friendlyURL the group's new friendlyURL (optionally
1082             *         <code>null</code>)
1083             * @param  active whether the group is active
1084             * @param  serviceContext the service context to be applied (optionally
1085             *         <code>null</code>). Can set the asset category IDs and asset tag
1086             *         names for the group.
1087             * @return the group
1088             * @throws PortalException if the user did not have permission to update the
1089             *         group, if a group with the primary key could not be found, if the
1090             *         friendly URL was invalid or could one not be created
1091             * @throws SystemException if a system exception occurred
1092             */
1093            @Override
1094            public Group updateGroup(
1095                            long groupId, long parentGroupId, String name, String description,
1096                            int type, boolean manualMembership, int membershipRestriction,
1097                            String friendlyURL, boolean active, ServiceContext serviceContext)
1098                    throws PortalException, SystemException {
1099    
1100                    Group group = groupPersistence.findByPrimaryKey(groupId);
1101    
1102                    GroupPermissionUtil.check(
1103                            getPermissionChecker(), group, ActionKeys.UPDATE);
1104    
1105                    if (group.getParentGroupId() != parentGroupId) {
1106                            if (parentGroupId == GroupConstants.DEFAULT_PARENT_GROUP_ID) {
1107                                    PortalPermissionUtil.check(
1108                                            getPermissionChecker(), ActionKeys.ADD_COMMUNITY);
1109                            }
1110                            else {
1111                                    GroupPermissionUtil.check(
1112                                            getPermissionChecker(), parentGroupId,
1113                                            ActionKeys.ADD_COMMUNITY);
1114                            }
1115                    }
1116    
1117                    if (group.isSite()) {
1118                            Group oldGroup = group;
1119    
1120                            List<AssetCategory> oldAssetCategories =
1121                                    assetCategoryLocalService.getCategories(
1122                                            Group.class.getName(), groupId);
1123    
1124                            List<AssetTag> oldAssetTags = assetTagLocalService.getTags(
1125                                    Group.class.getName(), groupId);
1126    
1127                            ExpandoBridge oldExpandoBridge = oldGroup.getExpandoBridge();
1128    
1129                            Map<String, Serializable> oldExpandoAttributes =
1130                                    oldExpandoBridge.getAttributes();
1131    
1132                            group = groupLocalService.updateGroup(
1133                                    groupId, parentGroupId, name, description, type,
1134                                    manualMembership, membershipRestriction, friendlyURL, active,
1135                                    serviceContext);
1136    
1137                            SiteMembershipPolicyUtil.verifyPolicy(
1138                                    group, oldGroup, oldAssetCategories, oldAssetTags,
1139                                    oldExpandoAttributes, null);
1140    
1141                            return group;
1142                    }
1143                    else {
1144                            return groupLocalService.updateGroup(
1145                                    groupId, parentGroupId, name, description, type,
1146                                    manualMembership, membershipRestriction, friendlyURL, active,
1147                                    serviceContext);
1148                    }
1149            }
1150    
1151            /**
1152             * Updates the group's type settings.
1153             *
1154             * @param  groupId the primary key of the group
1155             * @param  typeSettings the group's new type settings (optionally
1156             *         <code>null</code>)
1157             * @return the group
1158             * @throws PortalException if the user did not have permission to update the
1159             *         group or if a group with the primary key could not be found
1160             * @throws SystemException if a system exception occurred
1161             */
1162            @Override
1163            public Group updateGroup(long groupId, String typeSettings)
1164                    throws PortalException, SystemException {
1165    
1166                    GroupPermissionUtil.check(
1167                            getPermissionChecker(), groupId, ActionKeys.UPDATE);
1168    
1169                    Group group = groupPersistence.findByPrimaryKey(groupId);
1170    
1171                    if (group.isSite()) {
1172                            Group oldGroup = group;
1173    
1174                            UnicodeProperties oldTypeSettingsProperties =
1175                                    oldGroup.getTypeSettingsProperties();
1176    
1177                            group = groupLocalService.updateGroup(groupId, typeSettings);
1178    
1179                            SiteMembershipPolicyUtil.verifyPolicy(
1180                                    group, oldGroup, null, null, null, oldTypeSettingsProperties);
1181    
1182                            return group;
1183                    }
1184                    else {
1185                            return groupLocalService.updateGroup(groupId, typeSettings);
1186                    }
1187            }
1188    
1189            @Override
1190            public void updateStagedPortlets(
1191                            long groupId, Map<String, String> stagedPortletIds)
1192                    throws PortalException, SystemException {
1193    
1194                    GroupPermissionUtil.check(
1195                            getPermissionChecker(), groupId, ActionKeys.UPDATE);
1196    
1197                    Group group = groupPersistence.findByPrimaryKey(groupId);
1198    
1199                    UnicodeProperties typeSettingsProperties =
1200                            group.getTypeSettingsProperties();
1201    
1202                    for (String stagedPortletId : stagedPortletIds.keySet()) {
1203                            typeSettingsProperties.setProperty(
1204                                    StagingUtil.getStagedPortletId(stagedPortletId),
1205                                    stagedPortletIds.get(stagedPortletId));
1206                    }
1207    
1208                    groupLocalService.updateGroup(group);
1209            }
1210    
1211            protected List<Group> filterGroups(List<Group> groups)
1212                    throws PortalException, SystemException {
1213    
1214                    List<Group> filteredGroups = new ArrayList<Group>();
1215    
1216                    for (Group group : groups) {
1217                            if (GroupPermissionUtil.contains(
1218                                            getPermissionChecker(), group.getGroupId(),
1219                                            ActionKeys.VIEW)) {
1220    
1221                                    filteredGroups.add(group);
1222                            }
1223                    }
1224    
1225                    return filteredGroups;
1226            }
1227    
1228    }