001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
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.ASSIGN_MEMBERS);
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                            int filteredUserSiteGroupsCount = 0;
700    
701                            List<Organization> userOrgs =
702                                    organizationLocalService.getOrganizations(
703                                            userId, QueryUtil.ALL_POS, QueryUtil.ALL_POS, null);
704    
705                            for (Organization organization : userOrgs) {
706                                    if (filteredUserSiteGroupsCount == max) {
707                                            break;
708                                    }
709    
710                                    if (!organization.hasPrivateLayouts() &&
711                                            !organization.hasPublicLayouts()) {
712    
713                                            userSiteGroups.remove(organization.getGroup());
714    
715                                            filteredUserSiteGroupsCount--;
716                                    }
717                                    else {
718                                            userSiteGroups.add(organization.getGroup());
719    
720                                            filteredUserSiteGroupsCount++;
721                                    }
722    
723                                    if (!PropsValues.ORGANIZATIONS_MEMBERSHIP_STRICT) {
724                                            for (Organization ancestorOrganization :
725                                                            organization.getAncestors()) {
726    
727                                                    if (!ancestorOrganization.hasPrivateLayouts() &&
728                                                            !ancestorOrganization.hasPublicLayouts()) {
729    
730                                                            continue;
731                                                    }
732    
733                                                    userSiteGroups.add(ancestorOrganization.getGroup());
734    
735                                                    filteredUserSiteGroupsCount++;
736                                            }
737                                    }
738                            }
739                    }
740    
741                    if ((classNames == null) ||
742                            ArrayUtil.contains(classNames, User.class.getName())) {
743    
744                            if (PropsValues.LAYOUT_USER_PRIVATE_LAYOUTS_ENABLED ||
745                                    PropsValues.LAYOUT_USER_PUBLIC_LAYOUTS_ENABLED) {
746    
747                                    Group userGroup = user.getGroup();
748    
749                                    userSiteGroups.add(0, userGroup);
750                            }
751                    }
752    
753                    PermissionChecker permissionChecker = getPermissionChecker();
754    
755                    if (permissionChecker.getUserId() != userId) {
756                            try {
757                                    permissionChecker = PermissionCheckerFactoryUtil.create(user);
758                            }
759                            catch (Exception e) {
760                                    throw new PrincipalException(e);
761                            }
762                    }
763    
764                    if (includeControlPanel &&
765                            PortalPermissionUtil.contains(
766                                    permissionChecker, ActionKeys.VIEW_CONTROL_PANEL)) {
767    
768                            Group controlPanelGroup = groupLocalService.getGroup(
769                                    user.getCompanyId(), GroupConstants.CONTROL_PANEL);
770    
771                            userSiteGroups.add(0, controlPanelGroup);
772                    }
773    
774                    return Collections.unmodifiableList(
775                            ListUtil.subList(userSiteGroups, start, end));
776            }
777    
778            /**
779             * Returns the user's groups &quot;sites&quot; associated with the group
780             * entity class names, including the Control Panel group if the user is
781             * permitted to view the Control Panel.
782             *
783             * <ul>
784             * <li>
785             * Class name &quot;User&quot; includes the user's layout set
786             * group.
787             * </li>
788             * <li>
789             * Class name &quot;Organization&quot; includes the user's
790             * immediate organization groups and inherited organization groups.
791             * </li>
792             * <li>
793             * Class name &quot;Group&quot; includes the user's immediate
794             * organization groups and site groups.
795             * </li>
796             * <li>
797             * A <code>classNames</code>
798             * value of <code>null</code> includes the user's layout set group,
799             * organization groups, inherited organization groups, and site groups.
800             * </li>
801             * </ul>
802             *
803             * @param  userId the primary key of the user
804             * @param  classNames the group entity class names (optionally
805             *         <code>null</code>). For more information see {@link
806             *         #getUserSitesGroups(long, String[], boolean, int)}
807             * @param  max the maximum number of groups to return
808             * @return the user's groups &quot;sites&quot;
809             * @throws PortalException if a portal exception occurred
810             * @throws SystemException if a system exception occurred
811             */
812            @Override
813            public List<Group> getUserSitesGroups(
814                            long userId, String[] classNames, int max)
815                    throws PortalException, SystemException {
816    
817                    return getUserSitesGroups(userId, classNames, false, max);
818            }
819    
820            /**
821             * Returns the guest or current user's groups &quot;sites&quot; associated
822             * with the group entity class names, including the Control Panel group if
823             * the user is permitted to view the Control Panel.
824             *
825             * <ul>
826             * <li>
827             * Class name &quot;User&quot; includes the user's layout set
828             * group.
829             * </li>
830             * <li>
831             * Class name &quot;Organization&quot; includes the user's
832             * immediate organization groups and inherited organization groups.
833             * </li>
834             * <li>
835             * Class name &quot;Group&quot; includes the user's immediate
836             * organization groups and site groups.
837             * </li>
838             * <li>
839             * A <code>classNames</code>
840             * value of <code>null</code> includes the user's layout set group,
841             * organization groups, inherited organization groups, and site groups.
842             * </li>
843             * </ul>
844             *
845             * @param  classNames the group entity class names (optionally
846             *         <code>null</code>). For more information see {@link
847             *         #getUserSitesGroups(long, String[], boolean, int)}
848             * @param  max the maximum number of groups to return
849             * @return the user's groups &quot;sites&quot;
850             * @throws PortalException if a portal exception occurred
851             * @throws SystemException if a system exception occurred
852             */
853            @Override
854            public List<Group> getUserSitesGroups(String[] classNames, int max)
855                    throws PortalException, SystemException {
856    
857                    return getUserSitesGroups(getGuestOrUserId(), classNames, false, max);
858            }
859    
860            /**
861             * Returns the number of the guest or current user's groups
862             * &quot;sites&quot; associated with the group entity class names, including
863             * the Control Panel group if the user is permitted to view the Control
864             * Panel.
865             *
866             * @return the number of user's groups &quot;sites&quot;
867             * @throws PortalException if a portal exception occurred
868             * @throws SystemException if a system exception occurred
869             */
870            @Override
871            public int getUserSitesGroupsCount()
872                    throws PortalException, SystemException {
873    
874                    List<Group> userSitesGroups = getUserSitesGroups(
875                            getGuestOrUserId(), null, true, QueryUtil.ALL_POS);
876    
877                    return userSitesGroups.size();
878            }
879    
880            /**
881             * Returns <code>true</code> if the user is associated with the group,
882             * including the user's inherited organizations and user groups. System and
883             * staged groups are not included.
884             *
885             * @param  userId the primary key of the user
886             * @param  groupId the primary key of the group
887             * @return <code>true</code> if the user is associated with the group;
888             *         <code>false</code> otherwise
889             * @throws PortalException if the current user did not have permission to
890             *         view the user or group members
891             * @throws SystemException if a system exception occurred
892             */
893            @Override
894            public boolean hasUserGroup(long userId, long groupId)
895                    throws PortalException, SystemException {
896    
897                    try {
898                            UserPermissionUtil.check(
899                                    getPermissionChecker(), userId, ActionKeys.VIEW);
900                    }
901                    catch (PrincipalException pe) {
902                            GroupPermissionUtil.check(
903                                    getPermissionChecker(), groupId, ActionKeys.VIEW_MEMBERS);
904                    }
905    
906                    return groupLocalService.hasUserGroup(userId, groupId);
907            }
908    
909            @Override
910            public List<Group> search(
911                            long companyId, long[] classNameIds, String keywords,
912                            LinkedHashMap<String, Object> params, int start, int end,
913                            OrderByComparator obc)
914                    throws PortalException, SystemException {
915    
916                    List<Group> groups = groupLocalService.search(
917                            companyId, classNameIds, keywords, params, start, end, obc);
918    
919                    return filterGroups(groups);
920            }
921    
922            @Override
923            public List<Group> search(
924                            long companyId, long[] classNameIds, String name,
925                            String description, LinkedHashMap<String, Object> params,
926                            boolean andOperator, int start, int end, OrderByComparator obc)
927                    throws PortalException, SystemException {
928    
929                    List<Group> groups = groupLocalService.search(
930                            companyId, classNameIds, name, description, params, andOperator,
931                            start, end, obc);
932    
933                    return filterGroups(groups);
934            }
935    
936            /**
937             * Returns an ordered range of all the site groups and organization groups
938             * that match the name and description, optionally including the user's
939             * inherited organization groups and user groups. System and staged groups
940             * are not included.
941             *
942             * <p>
943             * Useful when paginating results. Returns a maximum of <code>end -
944             * start</code> instances. <code>start</code> and <code>end</code> are not
945             * primary keys, they are indexes in the result set. Thus, <code>0</code>
946             * refers to the first result in the set. Setting both <code>start</code>
947             * and <code>end</code> to {@link
948             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
949             * result set.
950             * </p>
951             *
952             * @param  companyId the primary key of the company
953             * @param  name the group's name (optionally <code>null</code>)
954             * @param  description the group's description (optionally
955             *         <code>null</code>)
956             * @param  params the finder params (optionally <code>null</code>). To
957             *         include the user's inherited organizations and user groups in the
958             *         search, add entries having &quot;usersGroups&quot; and
959             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
960             *         information see {@link
961             *         com.liferay.portal.service.persistence.GroupFinder}
962             * @param  start the lower bound of the range of groups to return
963             * @param  end the upper bound of the range of groups to return (not
964             *         inclusive)
965             * @return the matching groups ordered by name
966             * @throws PortalException if a portal exception occurred
967             * @throws SystemException if a system exception occurred
968             */
969            @Override
970            public List<Group> search(
971                            long companyId, String name, String description, String[] params,
972                            int start, int end)
973                    throws PortalException, SystemException {
974    
975                    if (params == null) {
976                            params = new String[0];
977                    }
978    
979                    LinkedHashMap<String, Object> paramsObj = MapUtil.toLinkedHashMap(
980                            params);
981    
982                    List<Group> groups = groupLocalService.search(
983                            companyId, name, description, paramsObj, true, start, end);
984    
985                    return filterGroups(groups);
986            }
987    
988            /**
989             * Returns the number of groups and organization groups that match the name
990             * and description, optionally including the user's inherited organizations
991             * and user groups. System and staged groups are not included.
992             *
993             * @param  companyId the primary key of the company
994             * @param  name the group's name (optionally <code>null</code>)
995             * @param  description the group's description (optionally
996             *         <code>null</code>)
997             * @param  params the finder params (optionally <code>null</code>). To
998             *         include the user's inherited organizations and user groups in the
999             *         search, add entries having &quot;usersGroups&quot; and
1000             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
1001             *         information see {@link
1002             *         com.liferay.portal.service.persistence.GroupFinder}
1003             * @return the number of matching groups
1004             * @throws SystemException if a system exception occurred
1005             */
1006            @Override
1007            public int searchCount(
1008                            long companyId, String name, String description, String[] params)
1009                    throws SystemException {
1010    
1011                    if (params == null) {
1012                            params = new String[0];
1013                    }
1014    
1015                    LinkedHashMap<String, Object> paramsObj = MapUtil.toLinkedHashMap(
1016                            params);
1017    
1018                    return groupLocalService.searchCount(
1019                            companyId, name, description, paramsObj, true);
1020            }
1021    
1022            /**
1023             * Sets the groups associated with the role, removing and adding
1024             * associations as necessary.
1025             *
1026             * @param  roleId the primary key of the role
1027             * @param  groupIds the primary keys of the groups
1028             * @throws PortalException if the user did not have permission to update
1029             *         update the role
1030             * @throws SystemException if a system exception occurred
1031             */
1032            @Override
1033            public void setRoleGroups(long roleId, long[] groupIds)
1034                    throws PortalException, SystemException {
1035    
1036                    RolePermissionUtil.check(
1037                            getPermissionChecker(), roleId, ActionKeys.ASSIGN_MEMBERS);
1038    
1039                    groupLocalService.setRoleGroups(roleId, groupIds);
1040            }
1041    
1042            /**
1043             * Removes the groups from the role.
1044             *
1045             * @param  roleId the primary key of the role
1046             * @param  groupIds the primary keys of the groups
1047             * @throws PortalException if the user did not have permission to update the
1048             *         role
1049             * @throws SystemException if a system exception occurred
1050             */
1051            @Override
1052            public void unsetRoleGroups(long roleId, long[] groupIds)
1053                    throws PortalException, SystemException {
1054    
1055                    RolePermissionUtil.check(
1056                            getPermissionChecker(), roleId, ActionKeys.ASSIGN_MEMBERS);
1057    
1058                    groupLocalService.unsetRoleGroups(roleId, groupIds);
1059            }
1060    
1061            /**
1062             * Updates the group's friendly URL.
1063             *
1064             * @param  groupId the primary key of the group
1065             * @param  friendlyURL the group's new friendlyURL (optionally
1066             *         <code>null</code>)
1067             * @return the group
1068             * @throws PortalException if the user did not have permission to update the
1069             *         group, if a group with the primary key could not be found, or if
1070             *         a valid friendly URL could not be created for the group
1071             * @throws SystemException if a system exception occurred
1072             */
1073            @Override
1074            public Group updateFriendlyURL(long groupId, String friendlyURL)
1075                    throws PortalException, SystemException {
1076    
1077                    GroupPermissionUtil.check(
1078                            getPermissionChecker(), groupId, ActionKeys.UPDATE);
1079    
1080                    return groupLocalService.updateFriendlyURL(groupId, friendlyURL);
1081            }
1082    
1083            /**
1084             * Updates the group.
1085             *
1086             * @param  groupId the primary key of the group
1087             * @param  parentGroupId the primary key of the parent group
1088             * @param  name the group's new name
1089             * @param  description the group's new description (optionally
1090             *         <code>null</code>)
1091             * @param  type the group's new type. For more information see {@link
1092             *         com.liferay.portal.model.GroupConstants}
1093             * @param  friendlyURL the group's new friendlyURL (optionally
1094             *         <code>null</code>)
1095             * @param  active whether the group is active
1096             * @param  serviceContext the service context to be applied (optionally
1097             *         <code>null</code>). Can set the asset category IDs and asset tag
1098             *         names for the group.
1099             * @return the group
1100             * @throws PortalException if the user did not have permission to update the
1101             *         group, if a group with the primary key could not be found, if the
1102             *         friendly URL was invalid or could one not be created
1103             * @throws SystemException if a system exception occurred
1104             */
1105            @Override
1106            public Group updateGroup(
1107                            long groupId, long parentGroupId, String name, String description,
1108                            int type, boolean manualMembership, int membershipRestriction,
1109                            String friendlyURL, boolean active, ServiceContext serviceContext)
1110                    throws PortalException, SystemException {
1111    
1112                    Group group = groupPersistence.findByPrimaryKey(groupId);
1113    
1114                    GroupPermissionUtil.check(
1115                            getPermissionChecker(), group, ActionKeys.UPDATE);
1116    
1117                    if (group.getParentGroupId() != parentGroupId) {
1118                            if (parentGroupId == GroupConstants.DEFAULT_PARENT_GROUP_ID) {
1119                                    PortalPermissionUtil.check(
1120                                            getPermissionChecker(), ActionKeys.ADD_COMMUNITY);
1121                            }
1122                            else {
1123                                    GroupPermissionUtil.check(
1124                                            getPermissionChecker(), parentGroupId,
1125                                            ActionKeys.ADD_COMMUNITY);
1126                            }
1127                    }
1128    
1129                    if (group.isSite()) {
1130                            Group oldGroup = group;
1131    
1132                            List<AssetCategory> oldAssetCategories =
1133                                    assetCategoryLocalService.getCategories(
1134                                            Group.class.getName(), groupId);
1135    
1136                            List<AssetTag> oldAssetTags = assetTagLocalService.getTags(
1137                                    Group.class.getName(), groupId);
1138    
1139                            ExpandoBridge oldExpandoBridge = oldGroup.getExpandoBridge();
1140    
1141                            Map<String, Serializable> oldExpandoAttributes =
1142                                    oldExpandoBridge.getAttributes();
1143    
1144                            group = groupLocalService.updateGroup(
1145                                    groupId, parentGroupId, name, description, type,
1146                                    manualMembership, membershipRestriction, friendlyURL, active,
1147                                    serviceContext);
1148    
1149                            SiteMembershipPolicyUtil.verifyPolicy(
1150                                    group, oldGroup, oldAssetCategories, oldAssetTags,
1151                                    oldExpandoAttributes, null);
1152    
1153                            return group;
1154                    }
1155                    else {
1156                            return groupLocalService.updateGroup(
1157                                    groupId, parentGroupId, name, description, type,
1158                                    manualMembership, membershipRestriction, friendlyURL, active,
1159                                    serviceContext);
1160                    }
1161            }
1162    
1163            /**
1164             * Updates the group's type settings.
1165             *
1166             * @param  groupId the primary key of the group
1167             * @param  typeSettings the group's new type settings (optionally
1168             *         <code>null</code>)
1169             * @return the group
1170             * @throws PortalException if the user did not have permission to update the
1171             *         group or if a group with the primary key could not be found
1172             * @throws SystemException if a system exception occurred
1173             */
1174            @Override
1175            public Group updateGroup(long groupId, String typeSettings)
1176                    throws PortalException, SystemException {
1177    
1178                    GroupPermissionUtil.check(
1179                            getPermissionChecker(), groupId, ActionKeys.UPDATE);
1180    
1181                    Group group = groupPersistence.findByPrimaryKey(groupId);
1182    
1183                    if (group.isSite()) {
1184                            Group oldGroup = group;
1185    
1186                            UnicodeProperties oldTypeSettingsProperties =
1187                                    oldGroup.getTypeSettingsProperties();
1188    
1189                            group = groupLocalService.updateGroup(groupId, typeSettings);
1190    
1191                            SiteMembershipPolicyUtil.verifyPolicy(
1192                                    group, oldGroup, null, null, null, oldTypeSettingsProperties);
1193    
1194                            return group;
1195                    }
1196                    else {
1197                            return groupLocalService.updateGroup(groupId, typeSettings);
1198                    }
1199            }
1200    
1201            @Override
1202            public void updateStagedPortlets(
1203                            long groupId, Map<String, String> stagedPortletIds)
1204                    throws PortalException, SystemException {
1205    
1206                    GroupPermissionUtil.check(
1207                            getPermissionChecker(), groupId, ActionKeys.UPDATE);
1208    
1209                    Group group = groupPersistence.findByPrimaryKey(groupId);
1210    
1211                    UnicodeProperties typeSettingsProperties =
1212                            group.getTypeSettingsProperties();
1213    
1214                    for (String stagedPortletId : stagedPortletIds.keySet()) {
1215                            typeSettingsProperties.setProperty(
1216                                    StagingUtil.getStagedPortletId(stagedPortletId),
1217                                    stagedPortletIds.get(stagedPortletId));
1218                    }
1219    
1220                    groupLocalService.updateGroup(group);
1221            }
1222    
1223            protected List<Group> filterGroups(List<Group> groups)
1224                    throws PortalException, SystemException {
1225    
1226                    List<Group> filteredGroups = new ArrayList<Group>();
1227    
1228                    for (Group group : groups) {
1229                            if (GroupPermissionUtil.contains(
1230                                            getPermissionChecker(), group.getGroupId(),
1231                                            ActionKeys.VIEW)) {
1232    
1233                                    filteredGroups.add(group);
1234                            }
1235                    }
1236    
1237                    return filteredGroups;
1238            }
1239    
1240    }