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