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