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