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