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