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.DuplicateGroupException;
018    import com.liferay.portal.GroupFriendlyURLException;
019    import com.liferay.portal.GroupInheritContentException;
020    import com.liferay.portal.GroupKeyException;
021    import com.liferay.portal.GroupParentException;
022    import com.liferay.portal.LocaleException;
023    import com.liferay.portal.NoSuchGroupException;
024    import com.liferay.portal.NoSuchLayoutSetException;
025    import com.liferay.portal.PendingBackgroundTaskException;
026    import com.liferay.portal.RequiredGroupException;
027    import com.liferay.portal.kernel.backgroundtask.BackgroundTask;
028    import com.liferay.portal.kernel.backgroundtask.BackgroundTaskConstants;
029    import com.liferay.portal.kernel.backgroundtask.BackgroundTaskManagerUtil;
030    import com.liferay.portal.kernel.cache.thread.local.ThreadLocalCachable;
031    import com.liferay.portal.kernel.dao.orm.QueryUtil;
032    import com.liferay.portal.kernel.exception.PortalException;
033    import com.liferay.portal.kernel.exception.SystemException;
034    import com.liferay.portal.kernel.language.LanguageUtil;
035    import com.liferay.portal.kernel.log.Log;
036    import com.liferay.portal.kernel.log.LogFactoryUtil;
037    import com.liferay.portal.kernel.messaging.DestinationNames;
038    import com.liferay.portal.kernel.scheduler.SchedulerEngineHelperUtil;
039    import com.liferay.portal.kernel.scheduler.StorageType;
040    import com.liferay.portal.kernel.spring.aop.Skip;
041    import com.liferay.portal.kernel.transaction.Propagation;
042    import com.liferay.portal.kernel.transaction.Transactional;
043    import com.liferay.portal.kernel.util.ArrayUtil;
044    import com.liferay.portal.kernel.util.CharPool;
045    import com.liferay.portal.kernel.util.FileUtil;
046    import com.liferay.portal.kernel.util.FriendlyURLNormalizerUtil;
047    import com.liferay.portal.kernel.util.GetterUtil;
048    import com.liferay.portal.kernel.util.GroupThreadLocal;
049    import com.liferay.portal.kernel.util.ListUtil;
050    import com.liferay.portal.kernel.util.LocaleUtil;
051    import com.liferay.portal.kernel.util.MapUtil;
052    import com.liferay.portal.kernel.util.OrderByComparator;
053    import com.liferay.portal.kernel.util.ParamUtil;
054    import com.liferay.portal.kernel.util.PropsKeys;
055    import com.liferay.portal.kernel.util.StringBundler;
056    import com.liferay.portal.kernel.util.StringPool;
057    import com.liferay.portal.kernel.util.StringUtil;
058    import com.liferay.portal.kernel.util.TreeModelTasksAdapter;
059    import com.liferay.portal.kernel.util.TreePathUtil;
060    import com.liferay.portal.kernel.util.UnicodeProperties;
061    import com.liferay.portal.kernel.util.Validator;
062    import com.liferay.portal.kernel.workflow.WorkflowHandler;
063    import com.liferay.portal.kernel.workflow.WorkflowHandlerRegistryUtil;
064    import com.liferay.portal.model.Account;
065    import com.liferay.portal.model.Company;
066    import com.liferay.portal.model.Group;
067    import com.liferay.portal.model.GroupConstants;
068    import com.liferay.portal.model.Layout;
069    import com.liferay.portal.model.LayoutConstants;
070    import com.liferay.portal.model.LayoutPrototype;
071    import com.liferay.portal.model.LayoutSet;
072    import com.liferay.portal.model.LayoutSetPrototype;
073    import com.liferay.portal.model.LayoutTemplate;
074    import com.liferay.portal.model.LayoutTypePortlet;
075    import com.liferay.portal.model.Organization;
076    import com.liferay.portal.model.Portlet;
077    import com.liferay.portal.model.ResourceAction;
078    import com.liferay.portal.model.ResourceConstants;
079    import com.liferay.portal.model.ResourcePermission;
080    import com.liferay.portal.model.ResourceTypePermission;
081    import com.liferay.portal.model.Role;
082    import com.liferay.portal.model.RoleConstants;
083    import com.liferay.portal.model.User;
084    import com.liferay.portal.model.UserGroup;
085    import com.liferay.portal.model.UserGroupRole;
086    import com.liferay.portal.model.UserPersonalSite;
087    import com.liferay.portal.model.WorkflowDefinitionLink;
088    import com.liferay.portal.model.impl.LayoutImpl;
089    import com.liferay.portal.security.auth.CompanyThreadLocal;
090    import com.liferay.portal.security.permission.ActionKeys;
091    import com.liferay.portal.security.permission.PermissionCacheUtil;
092    import com.liferay.portal.security.permission.ResourceActionsUtil;
093    import com.liferay.portal.security.permission.RolePermissions;
094    import com.liferay.portal.service.ServiceContext;
095    import com.liferay.portal.service.base.GroupLocalServiceBaseImpl;
096    import com.liferay.portal.theme.ThemeLoader;
097    import com.liferay.portal.theme.ThemeLoaderFactory;
098    import com.liferay.portal.util.PortalUtil;
099    import com.liferay.portal.util.PortletCategoryKeys;
100    import com.liferay.portal.util.PortletKeys;
101    import com.liferay.portal.util.PropsUtil;
102    import com.liferay.portal.util.PropsValues;
103    import com.liferay.portal.util.comparator.GroupIdComparator;
104    import com.liferay.portal.util.comparator.GroupNameComparator;
105    import com.liferay.portlet.exportimport.configuration.ExportImportConfigurationConstants;
106    import com.liferay.portlet.exportimport.configuration.ExportImportConfigurationSettingsMapFactory;
107    import com.liferay.portlet.exportimport.lar.PortletDataContext;
108    import com.liferay.portlet.exportimport.lar.PortletDataContextFactoryUtil;
109    import com.liferay.portlet.exportimport.lar.PortletDataHandler;
110    import com.liferay.portlet.exportimport.lar.PortletDataHandlerKeys;
111    import com.liferay.portlet.exportimport.model.ExportImportConfiguration;
112    import com.liferay.portlet.exportimport.staging.StagingConstants;
113    import com.liferay.portlet.exportimport.staging.StagingUtil;
114    import com.liferay.util.dao.orm.CustomSQLUtil;
115    
116    import java.io.File;
117    import java.io.Serializable;
118    
119    import java.util.ArrayList;
120    import java.util.Arrays;
121    import java.util.Collection;
122    import java.util.Collections;
123    import java.util.HashMap;
124    import java.util.HashSet;
125    import java.util.Iterator;
126    import java.util.LinkedHashMap;
127    import java.util.List;
128    import java.util.Locale;
129    import java.util.Map;
130    import java.util.Set;
131    
132    /**
133     * Provides the local service for accessing, adding, deleting, and updating
134     * groups. Groups are mostly used in Liferay as a resource container for
135     * permissioning and content scoping purposes.
136     *
137     * <p>
138     * Groups are also the entity to which LayoutSets are generally associated.
139     * Since LayoutSets are the parent entities of Layouts (i.e. pages), no entity
140     * can have associated pages without also having an associated Group. This
141     * relationship can be depicted as ... Layout -> LayoutSet -> Group[type] [->
142     * Entity]. Note, the Entity part is optional.
143     * </p>
144     *
145     * <p>
146     * Group has a "type" definition that is typically identified by two fields of
147     * the entity - <code>String className</code>, and <code>int type </code>.
148     * </p>
149     *
150     * <p>
151     * The <code>className</code> field helps create the group's association with
152     * other entities (e.g. Organization, User, Company, UserGroup, ... etc.). The
153     * value of <code>className</code> is the full name of the entity's class and
154     * the primary key of the associated entity instance. A site has
155     * <code>className="Group"</code> and has no associated entity.
156     * </p>
157     *
158     * <p>
159     * The <code>type</code> field helps distinguish between a group used strictly
160     * for scoping and a group that also has pages (in which case the type is
161     * <code>SITE</code>). For a list of types, see {@link GroupConstants}.
162     * </p>
163     *
164     * <p>
165     * Here is a listing of how Group is related to some portal entities ...
166     * </p>
167     *
168     * <ul>
169     * <li>
170     * Site is a Group with <code>className="Group"</code>
171     * </li>
172     * <li>
173     * Company has 1 Group (this is the global scope, but never has pages)
174     * </li>
175     * <li>
176     * User has 1 Group (pages are optional based on the behavior configuration for
177     * personal pages)
178     * </li>
179     * <li>
180     * Layout Template (<code>LayoutPrototype</code>) has 1 Group which uses only 1
181     * of it's 2 LayoutSets to store a single page which can later be used to
182     * derive a single page in any Site
183     * </li>
184     * <li>
185     * Site Template (<code>LayoutSetPrototype</code>) has 1 Group which uses only
186     * 1 of it's 2 LayoutSets to store many pages which can later be used to derive
187     * entire Sites or pulled into an existing Site
188     * </li>
189     * <li>
190     * Organization has 1 Group, but can also be associated to a Site at any point
191     * in it's life cycle in order to support having pages
192     * </li>
193     * <li>
194     * UserGroup has 1 Group that can have pages in both of the group's LayoutSets
195     * which are later inherited by users assigned to the UserGroup
196     * </li>
197     * </ul>
198     *
199     * @author Brian Wing Shun Chan
200     * @author Alexander Chow
201     * @author Bruno Farache
202     * @author Wesley Gong
203     * @see    com.liferay.portal.model.impl.GroupImpl
204     */
205    public class GroupLocalServiceImpl extends GroupLocalServiceBaseImpl {
206    
207            public static final String ORGANIZATION_NAME_SUFFIX = " LFR_ORGANIZATION";
208    
209            public static final String ORGANIZATION_STAGING_SUFFIX = " (Staging)";
210    
211            /**
212             * Constructs a group local service.
213             */
214            public GroupLocalServiceImpl() {
215                    initImportLARFile();
216            }
217    
218            @Override
219            public Group addGroup(
220                            long userId, long parentGroupId, String className, long classPK,
221                            long liveGroupId, Map<Locale, String> nameMap,
222                            Map<Locale, String> descriptionMap, int type,
223                            boolean manualMembership, int membershipRestriction,
224                            String friendlyURL, boolean site, boolean inheritContent,
225                            boolean active, ServiceContext serviceContext)
226                    throws PortalException {
227    
228                    // Group
229    
230                    User user = userPersistence.findByPrimaryKey(userId);
231                    className = GetterUtil.getString(className);
232                    long classNameId = classNameLocalService.getClassNameId(className);
233    
234                    String groupKey = StringPool.BLANK;
235                    String friendlyName = StringPool.BLANK;
236    
237                    if (nameMap != null) {
238                            groupKey = nameMap.get(LocaleUtil.getDefault());
239                            friendlyName = nameMap.get(LocaleUtil.getDefault());
240                    }
241    
242                    long groupId = 0;
243    
244                    while (true) {
245                            groupId = counterLocalService.increment();
246    
247                            User screenNameUser = userPersistence.fetchByC_SN(
248                                    user.getCompanyId(), String.valueOf(groupId));
249    
250                            if (screenNameUser == null) {
251                                    break;
252                            }
253                    }
254    
255                    boolean staging = isStaging(serviceContext);
256    
257                    long groupClassNameId = classNameLocalService.getClassNameId(
258                            Group.class);
259    
260                    if ((classNameId <= 0) || className.equals(Group.class.getName()) ||
261                            (className.equals(Company.class.getName()) && staging)) {
262    
263                            className = Group.class.getName();
264                            classNameId = groupClassNameId;
265                            classPK = groupId;
266                    }
267                    else if (className.equals(Organization.class.getName())) {
268                            groupKey = getOrgGroupName(groupKey);
269                    }
270                    else if (!GroupConstants.USER_PERSONAL_SITE.equals(groupKey)) {
271                            groupKey = String.valueOf(classPK);
272                    }
273    
274                    if (className.equals(Organization.class.getName()) && staging) {
275                            classPK = liveGroupId;
276                    }
277    
278                    if (className.equals(Layout.class.getName())) {
279                            Layout layout = layoutLocalService.getLayout(classPK);
280    
281                            parentGroupId = layout.getGroupId();
282                    }
283    
284                    friendlyURL = getFriendlyURL(
285                            user.getCompanyId(), groupId, classNameId, classPK, friendlyName,
286                            friendlyURL);
287    
288                    if (staging) {
289                            groupKey = groupKey.concat("-staging");
290    
291                            for (Locale locale : nameMap.keySet()) {
292                                    String name = nameMap.get(locale);
293    
294                                    if (Validator.isNull(name)) {
295                                            continue;
296                                    }
297    
298                                    nameMap.put(locale, name.concat(ORGANIZATION_STAGING_SUFFIX));
299                            }
300    
301                            friendlyURL = getFriendlyURL(friendlyURL.concat("-staging"));
302                    }
303    
304                    if (parentGroupId == GroupConstants.DEFAULT_PARENT_GROUP_ID) {
305                            membershipRestriction =
306                                    GroupConstants.DEFAULT_MEMBERSHIP_RESTRICTION;
307                    }
308    
309                    if (className.equals(Group.class.getName())) {
310                            if (!site && (liveGroupId == 0) &&
311                                    !groupKey.equals(GroupConstants.CONTROL_PANEL)) {
312    
313                                    throw new IllegalArgumentException();
314                            }
315                    }
316                    else if (!className.equals(Company.class.getName()) &&
317                                     !className.equals(Organization.class.getName()) &&
318                                     className.startsWith("com.liferay.portal.model.")) {
319    
320                            if (site) {
321                                    throw new IllegalArgumentException();
322                            }
323                    }
324    
325                    if ((classNameId <= 0) || className.equals(Group.class.getName())) {
326                            validateGroupKey(groupId, user.getCompanyId(), groupKey, site);
327                    }
328    
329                    validateInheritContent(parentGroupId, inheritContent);
330    
331                    validateFriendlyURL(
332                            user.getCompanyId(), groupId, classNameId, classPK, friendlyURL);
333    
334                    validateParentGroup(groupId, parentGroupId);
335    
336                    Group group = groupPersistence.create(groupId);
337    
338                    if (serviceContext != null) {
339                            group.setUuid(serviceContext.getUuid());
340                    }
341    
342                    group.setCompanyId(user.getCompanyId());
343                    group.setCreatorUserId(userId);
344                    group.setClassNameId(classNameId);
345                    group.setClassPK(classPK);
346                    group.setParentGroupId(parentGroupId);
347                    group.setLiveGroupId(liveGroupId);
348                    group.setTreePath(group.buildTreePath());
349                    group.setGroupKey(groupKey);
350                    group.setNameMap(nameMap);
351                    group.setDescriptionMap(descriptionMap);
352                    group.setType(type);
353                    group.setManualMembership(manualMembership);
354                    group.setMembershipRestriction(membershipRestriction);
355                    group.setFriendlyURL(friendlyURL);
356                    group.setInheritContent(inheritContent);
357                    group.setSite(site);
358                    group.setActive(active);
359    
360                    if ((serviceContext != null) && (classNameId == groupClassNameId) &&
361                            !user.isDefaultUser()) {
362    
363                            group.setExpandoBridgeAttributes(serviceContext);
364                    }
365    
366                    groupPersistence.update(group);
367    
368                    // Layout sets
369    
370                    layoutSetLocalService.addLayoutSet(groupId, true);
371    
372                    layoutSetLocalService.addLayoutSet(groupId, false);
373    
374                    // Resources
375    
376                    resourceLocalService.addResources(
377                            group.getCompanyId(), 0, 0, Group.class.getName(),
378                            group.getGroupId(), false, false, false);
379    
380                    if ((classNameId == groupClassNameId) && !user.isDefaultUser()) {
381    
382                            // Site roles
383    
384                            Role role = roleLocalService.getRole(
385                                    group.getCompanyId(), RoleConstants.SITE_OWNER);
386    
387                            userGroupRoleLocalService.addUserGroupRoles(
388                                    userId, groupId, new long[] {role.getRoleId()});
389    
390                            // User
391    
392                            userLocalService.addGroupUsers(
393                                    group.getGroupId(), new long[] {userId});
394    
395                            // Asset
396    
397                            if (serviceContext != null) {
398                                    updateAsset(
399                                            userId, group, serviceContext.getAssetCategoryIds(),
400                                            serviceContext.getAssetTagNames());
401                            }
402                    }
403    
404                    addPortletDefaultData(group);
405    
406                    return group;
407            }
408    
409            @Override
410            public Group addGroup(
411                            long userId, long parentGroupId, String className, long classPK,
412                            long liveGroupId, Map<Locale, String> nameMap,
413                            Map<Locale, String> descriptionMap, int type,
414                            boolean manualMembership, int membershipRestriction,
415                            String friendlyURL, boolean site, boolean active,
416                            ServiceContext serviceContext)
417                    throws PortalException {
418    
419                    return addGroup(
420                            userId, parentGroupId, className, classPK, liveGroupId, nameMap,
421                            descriptionMap, type, manualMembership, membershipRestriction,
422                            friendlyURL, site, false, active, serviceContext);
423            }
424    
425            /**
426             * Adds a group.
427             *
428             * @param      userId the primary key of the group's creator/owner
429             * @param      parentGroupId the primary key of the parent group
430             * @param      className the entity's class name
431             * @param      classPK the primary key of the entity's instance
432             * @param      liveGroupId the primary key of the live group
433             * @param      name the entity's name
434             * @param      description the group's description (optionally
435             *             <code>null</code>)
436             * @param      type the group's type. For more information see {@link
437             *             GroupConstants}.
438             * @param      manualMembership whether manual membership is allowed for the
439             *             group
440             * @param      membershipRestriction the group's membership restriction. For
441             *             more information see {@link GroupConstants}.
442             * @param      friendlyURL the group's friendlyURL (optionally
443             *             <code>null</code>)
444             * @param      site whether the group is to be associated with a main site
445             * @param      active whether the group is active
446             * @param      serviceContext the service context to be applied (optionally
447             *             <code>null</code>). Can set asset category IDs and asset tag
448             *             names for the group, and whether the group is for staging.
449             * @return     the group
450             * @throws     PortalException if a portal exception occured
451             * @deprecated As of 7.0.0, replaced by {@link #addGroup(long, long, String,
452             *             long, long, Map, Map, int, boolean, int, String, boolean,
453             *             boolean, ServiceContext)}
454             */
455            @Deprecated
456            @Override
457            public Group addGroup(
458                            long userId, long parentGroupId, String className, long classPK,
459                            long liveGroupId, String name, String description, int type,
460                            boolean manualMembership, int membershipRestriction,
461                            String friendlyURL, boolean site, boolean active,
462                            ServiceContext serviceContext)
463                    throws PortalException {
464    
465                    return addGroup(
466                            userId, parentGroupId, className, classPK, liveGroupId,
467                            getLocalizationMap(name), getLocalizationMap(description), type,
468                            manualMembership, membershipRestriction, friendlyURL, site, false,
469                            active, serviceContext);
470            }
471    
472            /**
473             * Adds the group using the default live group.
474             *
475             * @param      userId the primary key of the group's creator/owner
476             * @param      parentGroupId the primary key of the parent group
477             * @param      className the entity's class name
478             * @param      classPK the primary key of the entity's instance
479             * @param      name the entity's name
480             * @param      description the group's description (optionally
481             *             <code>null</code>)
482             * @param      type the group's type. For more information see {@link
483             *             GroupConstants}.
484             * @param      friendlyURL the group's friendlyURL
485             * @param      site whether the group is to be associated with a main site
486             * @param      active whether the group is active
487             * @param      serviceContext the service context to be applied (optionally
488             *             <code>null</code>). Can set asset category IDs and asset tag
489             *             names for the group, and whether the group is for staging.
490             * @return     the group
491             * @throws     PortalException if a portal exception occurred
492             * @deprecated As of 6.2.0, replaced by {@link #addGroup(long, long, String,
493             *             long, long, Map, Map, int, boolean, int, String, boolean,
494             *             boolean, ServiceContext)}
495             */
496            @Deprecated
497            @Override
498            public Group addGroup(
499                            long userId, long parentGroupId, String className, long classPK,
500                            String name, String description, int type, String friendlyURL,
501                            boolean site, boolean active, ServiceContext serviceContext)
502                    throws PortalException {
503    
504                    return addGroup(
505                            userId, parentGroupId, className, classPK,
506                            GroupConstants.DEFAULT_LIVE_GROUP_ID, getLocalizationMap(name),
507                            getLocalizationMap(description), type, true,
508                            GroupConstants.DEFAULT_MEMBERSHIP_RESTRICTION, friendlyURL, site,
509                            active, serviceContext);
510            }
511    
512            /**
513             * Adds a group.
514             *
515             * @param      userId the primary key of the group's creator/owner
516             * @param      className the entity's class name
517             * @param      classPK the primary key of the entity's instance
518             * @param      liveGroupId the primary key of the live group
519             * @param      name the entity's name
520             * @param      description the group's description (optionally
521             *             <code>null</code>)
522             * @param      type the group's type. For more information see {@link
523             *             GroupConstants}.
524             * @param      friendlyURL the group's friendlyURL (optionally
525             *             <code>null</code>)
526             * @param      site whether the group is to be associated with a main site
527             * @param      active whether the group is active
528             * @param      serviceContext the service context to be applied (optionally
529             *             <code>null</code>). Can set asset category IDs and asset tag
530             *             names for the group, and whether the group is for staging.
531             * @return     the group
532             * @throws     PortalException if a portal exception occurred
533             * @deprecated As of 6.2.0, replaced by {@link #addGroup(long, long, String,
534             *             long, long, Map, Map, int, boolean, int, String, boolean,
535             *             boolean, ServiceContext)}
536             */
537            @Deprecated
538            @Override
539            public Group addGroup(
540                            long userId, String className, long classPK, long liveGroupId,
541                            String name, String description, int type, String friendlyURL,
542                            boolean site, boolean active, ServiceContext serviceContext)
543                    throws PortalException {
544    
545                    return addGroup(
546                            userId, GroupConstants.DEFAULT_PARENT_GROUP_ID, className, classPK,
547                            liveGroupId, getLocalizationMap(name),
548                            getLocalizationMap(description), type, true,
549                            GroupConstants.DEFAULT_MEMBERSHIP_RESTRICTION, friendlyURL, site,
550                            active, serviceContext);
551            }
552    
553            /**
554             * Adds the group using the default live group.
555             *
556             * @param      userId the primary key of the group's creator/owner
557             * @param      className the entity's class name
558             * @param      classPK the primary key of the entity's instance
559             * @param      name the entity's name
560             * @param      description the group's description (optionally
561             *             <code>null</code>)
562             * @param      type the group's type. For more information see {@link
563             *             GroupConstants}.
564             * @param      friendlyURL the group's friendlyURL
565             * @param      site whether the group is to be associated with a main site
566             * @param      active whether the group is active
567             * @param      serviceContext the service context to be applied (optionally
568             *             <code>null</code>). Can set asset category IDs and asset tag
569             *             names for the group, and whether the group is for staging.
570             * @return     the group
571             * @throws     PortalException if a portal exception occurred
572             * @deprecated As of 6.2.0, replaced by {@link #addGroup(long, long, String,
573             *             long, long, Map, Map, int, boolean, int, String, boolean,
574             *             boolean, ServiceContext)}
575             */
576            @Deprecated
577            @Override
578            public Group addGroup(
579                            long userId, String className, long classPK, String name,
580                            String description, int type, String friendlyURL, boolean site,
581                            boolean active, ServiceContext serviceContext)
582                    throws PortalException {
583    
584                    return addGroup(
585                            userId, GroupConstants.DEFAULT_PARENT_GROUP_ID, className, classPK,
586                            GroupConstants.DEFAULT_LIVE_GROUP_ID, getLocalizationMap(name),
587                            getLocalizationMap(description), type, true,
588                            GroupConstants.DEFAULT_MEMBERSHIP_RESTRICTION, friendlyURL, site,
589                            active, serviceContext);
590            }
591    
592            /**
593             * Adds the groups to the role.
594             *
595             * @param roleId the primary key of the role
596             * @param groupIds the primary keys of the groups
597             */
598            @Override
599            public void addRoleGroups(long roleId, long[] groupIds) {
600                    rolePersistence.addGroups(roleId, groupIds);
601    
602                    PermissionCacheUtil.clearCache();
603            }
604    
605            /**
606             * Adds the user to the groups.
607             *
608             * @param userId the primary key of the user
609             * @param groupIds the primary keys of the groups
610             */
611            @Override
612            public void addUserGroups(long userId, long[] groupIds) {
613                    userPersistence.addGroups(userId, groupIds);
614    
615                    PermissionCacheUtil.clearCache(userId);
616            }
617    
618            /**
619             * Adds a company group if it does not exist. This method is typically used
620             * when a virtual host is added.
621             *
622             * @param  companyId the primary key of the company
623             * @throws PortalException if a portal exception occurred
624             */
625            @Override
626            @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
627            public void checkCompanyGroup(long companyId) throws PortalException {
628                    long classNameId = classNameLocalService.getClassNameId(Company.class);
629    
630                    int count = groupPersistence.countByC_C_C(
631                            companyId, classNameId, companyId);
632    
633                    if (count == 0) {
634                            long defaultUserId = userLocalService.getDefaultUserId(companyId);
635    
636                            groupLocalService.addGroup(
637                                    defaultUserId, GroupConstants.DEFAULT_PARENT_GROUP_ID,
638                                    Company.class.getName(), companyId,
639                                    GroupConstants.DEFAULT_LIVE_GROUP_ID,
640                                    getLocalizationMap(GroupConstants.GLOBAL), null, 0, true,
641                                    GroupConstants.DEFAULT_MEMBERSHIP_RESTRICTION,
642                                    GroupConstants.GLOBAL_FRIENDLY_URL, true, true, null);
643                    }
644            }
645    
646            /**
647             * Creates systems groups and other related data needed by the system on the
648             * very first startup. Also takes care of creating the Control Panel groups
649             * and layouts.
650             *
651             * @param  companyId the primary key of the company
652             * @throws PortalException if a portal exception occurred
653             */
654            @Override
655            @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
656            public void checkSystemGroups(long companyId) throws PortalException {
657                    String companyIdHexString = StringUtil.toHexString(companyId);
658    
659                    for (Group group : groupFinder.findBySystem(companyId)) {
660                            _systemGroupsMap.put(
661                                    companyIdHexString.concat(group.getGroupKey()), group);
662                    }
663    
664                    long defaultUserId = userLocalService.getDefaultUserId(companyId);
665    
666                    String[] systemGroups = PortalUtil.getSystemGroups();
667    
668                    for (String groupKey : systemGroups) {
669                            String groupCacheKey = companyIdHexString.concat(groupKey);
670    
671                            Group group = _systemGroupsMap.get(groupCacheKey);
672    
673                            if (group == null) {
674                                    group = groupPersistence.fetchByC_GK(companyId, groupKey);
675                            }
676    
677                            if (group == null) {
678                                    String className = null;
679                                    long classPK = 0;
680                                    int type = GroupConstants.TYPE_SITE_OPEN;
681                                    String friendlyURL = null;
682                                    boolean site = true;
683    
684                                    if (groupKey.equals(GroupConstants.CONTROL_PANEL)) {
685                                            type = GroupConstants.TYPE_SITE_PRIVATE;
686                                            friendlyURL = GroupConstants.CONTROL_PANEL_FRIENDLY_URL;
687                                            site = false;
688                                    }
689                                    else if (groupKey.equals(GroupConstants.GUEST)) {
690                                            friendlyURL = "/guest";
691                                    }
692                                    else if (groupKey.equals(GroupConstants.USER_PERSONAL_SITE)) {
693                                            className = UserPersonalSite.class.getName();
694                                            classPK = defaultUserId;
695                                            type = GroupConstants.TYPE_SITE_PRIVATE;
696                                            friendlyURL =
697                                                    GroupConstants.USER_PERSONAL_SITE_FRIENDLY_URL;
698                                            site = false;
699                                    }
700    
701                                    group = groupLocalService.addGroup(
702                                            defaultUserId, GroupConstants.DEFAULT_PARENT_GROUP_ID,
703                                            className, classPK, GroupConstants.DEFAULT_LIVE_GROUP_ID,
704                                            getLocalizationMap(groupKey), null, type, true,
705                                            GroupConstants.DEFAULT_MEMBERSHIP_RESTRICTION, friendlyURL,
706                                            site, true, null);
707    
708                                    if (groupKey.equals(GroupConstants.USER_PERSONAL_SITE)) {
709                                            initUserPersonalSitePermissions(group);
710                                    }
711                            }
712    
713                            if (group.isControlPanel()) {
714                                    LayoutSet layoutSet = layoutSetLocalService.getLayoutSet(
715                                            group.getGroupId(), true);
716    
717                                    if (layoutSet.getPageCount() == 0) {
718                                            addControlPanelLayouts(group);
719                                    }
720                            }
721    
722                            if (group.isGuest()) {
723                                    LayoutSet layoutSet = layoutSetLocalService.getLayoutSet(
724                                            group.getGroupId(), false);
725    
726                                    if (layoutSet.getPageCount() == 0) {
727                                            addDefaultGuestPublicLayouts(group);
728                                    }
729                            }
730    
731                            _systemGroupsMap.put(groupCacheKey, group);
732                    }
733            }
734    
735            /**
736             * Deletes the group and its associated data.
737             *
738             * <p>
739             * The group is unstaged and its assets and resources including layouts,
740             * membership requests, subscriptions, teams, blogs, bookmarks, events,
741             * image gallery, journals, message boards, polls, shopping related
742             * entities, and wikis are also deleted.
743             * </p>
744             *
745             * @param  group the group
746             * @return the deleted group
747             * @throws PortalException if a portal exception occurred
748             */
749            @Override
750            public Group deleteGroup(Group group) throws PortalException {
751                    boolean deleteInProcess = GroupThreadLocal.isDeleteInProcess();
752    
753                    try {
754                            GroupThreadLocal.setDeleteInProcess(true);
755    
756                            if (((group.isCompany() && !group.isCompanyStagingGroup()) ||
757                                     PortalUtil.isSystemGroup(group.getGroupKey())) &&
758                                    !CompanyThreadLocal.isDeleteInProcess()) {
759    
760                                    throw new RequiredGroupException.MustNotDeleteSystemGroup(
761                                            group.getGroupId());
762                            }
763    
764                            if (groupPersistence.countByC_P_S(
765                                            group.getCompanyId(), group.getGroupId(), true) > 0) {
766    
767                                    throw new RequiredGroupException.MustNotDeleteGroupThatHasChild(
768                                            group.getGroupId());
769                            }
770    
771                            List<BackgroundTask> backgroundTasks =
772                                    BackgroundTaskManagerUtil.getBackgroundTasks(
773                                            group.getGroupId(),
774                                            BackgroundTaskConstants.STATUS_IN_PROGRESS);
775    
776                            if (!backgroundTasks.isEmpty()) {
777                                    throw new PendingBackgroundTaskException(
778                                            "Unable to delete group with pending background tasks");
779                            }
780    
781                            // Background tasks
782    
783                            BackgroundTaskManagerUtil.deleteGroupBackgroundTasks(
784                                    group.getGroupId());
785    
786                            // Layout set branches
787    
788                            layoutSetBranchLocalService.deleteLayoutSetBranches(
789                                    group.getGroupId(), true, true);
790    
791                            layoutSetBranchLocalService.deleteLayoutSetBranches(
792                                    group.getGroupId(), false, true);
793    
794                            // Layout sets
795    
796                            ServiceContext serviceContext = new ServiceContext();
797    
798                            try {
799                                    layoutSetLocalService.deleteLayoutSet(
800                                            group.getGroupId(), true, serviceContext);
801                            }
802                            catch (NoSuchLayoutSetException nslse) {
803                            }
804    
805                            try {
806                                    layoutSetLocalService.deleteLayoutSet(
807                                            group.getGroupId(), false, serviceContext);
808                            }
809                            catch (NoSuchLayoutSetException nslse) {
810                            }
811    
812                            // Membership requests
813    
814                            membershipRequestLocalService.deleteMembershipRequests(
815                                    group.getGroupId());
816    
817                            // Portlet preferences
818    
819                            portletPreferencesLocalService.deletePortletPreferences(
820                                    group.getGroupId(), PortletKeys.PREFS_OWNER_TYPE_GROUP,
821                                    PortletKeys.PREFS_PLID_SHARED);
822    
823                            // Repositories
824    
825                            dlAppLocalService.deleteAllRepositories(group.getGroupId());
826    
827                            // Teams
828    
829                            teamLocalService.deleteTeams(group.getGroupId());
830    
831                            // Staging
832    
833                            exportImportConfigurationLocalService.
834                                    deleteExportImportConfigurations(group.getGroupId());
835    
836                            unscheduleStaging(group);
837    
838                            if (group.hasStagingGroup()) {
839                                    try {
840                                            stagingLocalService.disableStaging(group, serviceContext);
841                                    }
842                                    catch (Exception e) {
843                                            _log.error(
844                                                    "Unable to disable staging for group " +
845                                                            group.getGroupId());
846                                    }
847                            }
848    
849                            // Themes
850    
851                            ThemeLoader themeLoader =
852                                    ThemeLoaderFactory.getDefaultThemeLoader();
853    
854                            if (themeLoader != null) {
855                                    String themePath =
856                                            themeLoader.getFileStorage() + StringPool.SLASH +
857                                                    group.getGroupId();
858    
859                                    FileUtil.deltree(themePath + "-private");
860                                    FileUtil.deltree(themePath + "-public");
861                            }
862    
863                            // Portlet data
864    
865                            deletePortletData(group);
866    
867                            // Asset
868    
869                            if (group.isRegularSite()) {
870                                    assetEntryLocalService.deleteEntry(
871                                            Group.class.getName(), group.getGroupId());
872                            }
873    
874                            assetEntryLocalService.deleteGroupEntries(group.getGroupId());
875    
876                            assetTagLocalService.deleteGroupTags(group.getGroupId());
877    
878                            assetVocabularyLocalService.deleteVocabularies(group.getGroupId());
879    
880                            // Expando
881    
882                            expandoRowLocalService.deleteRows(group.getGroupId());
883    
884                            // Social
885    
886                            socialActivityLocalService.deleteActivities(group.getGroupId());
887                            socialActivitySettingLocalService.deleteActivitySettings(
888                                    group.getGroupId());
889                            socialRequestLocalService.deleteRequests(
890                                    classNameLocalService.getClassNameId(Group.class),
891                                    group.getGroupId());
892    
893                            // Resources
894    
895                            List<ResourcePermission> resourcePermissions =
896                                    resourcePermissionPersistence.findByC_LikeP(
897                                            group.getCompanyId(), String.valueOf(group.getGroupId()));
898    
899                            for (ResourcePermission resourcePermission : resourcePermissions) {
900                                    resourcePermissionLocalService.deleteResourcePermission(
901                                            resourcePermission);
902                            }
903    
904                            if (!group.isStagingGroup() &&
905                                    (group.isOrganization() || group.isRegularSite())) {
906    
907                                    resourceLocalService.deleteResource(
908                                            group.getCompanyId(), Group.class.getName(),
909                                            ResourceConstants.SCOPE_INDIVIDUAL, group.getGroupId());
910                            }
911    
912                            // Trash
913    
914                            trashEntryLocalService.deleteEntries(group.getGroupId());
915    
916                            // Workflow
917    
918                            List<WorkflowHandler<?>> scopeableWorkflowHandlers =
919                                    WorkflowHandlerRegistryUtil.getScopeableWorkflowHandlers();
920    
921                            for (WorkflowHandler<?> scopeableWorkflowHandler :
922                                            scopeableWorkflowHandlers) {
923    
924                                    if (!scopeableWorkflowHandler.isVisible()) {
925                                            continue;
926                                    }
927    
928                                    WorkflowDefinitionLink workflowDefinitionLink =
929                                            workflowDefinitionLinkLocalService.
930                                                    fetchWorkflowDefinitionLink(
931                                                            group.getCompanyId(), group.getGroupId(),
932                                                            scopeableWorkflowHandler.getClassName(), 0, 0,
933                                                            true);
934    
935                                    if (workflowDefinitionLink == null) {
936                                            continue;
937                                    }
938    
939                                    workflowDefinitionLinkLocalService.deleteWorkflowDefinitionLink(
940                                            workflowDefinitionLink);
941                            }
942    
943                            // Group
944    
945                            if (!group.isStagingGroup() && group.isOrganization() &&
946                                    group.isSite()) {
947    
948                                    group.setSite(false);
949    
950                                    groupPersistence.update(group);
951    
952                                    // Group roles
953    
954                                    userGroupRoleLocalService.deleteUserGroupRoles(
955                                            group.getGroupId(), RoleConstants.TYPE_SITE);
956    
957                                    // User group roles
958    
959                                    userGroupGroupRoleLocalService.deleteUserGroupGroupRoles(
960                                            group.getGroupId(), RoleConstants.TYPE_SITE);
961                            }
962                            else {
963                                    groupPersistence.remove(group);
964    
965                                    // Group roles
966    
967                                    userGroupRoleLocalService.deleteUserGroupRolesByGroupId(
968                                            group.getGroupId());
969    
970                                    // User group roles
971    
972                                    userGroupGroupRoleLocalService.
973                                            deleteUserGroupGroupRolesByGroupId(group.getGroupId());
974                            }
975    
976                            // Permission cache
977    
978                            PermissionCacheUtil.clearCache();
979    
980                            return group;
981                    }
982                    finally {
983                            GroupThreadLocal.setDeleteInProcess(deleteInProcess);
984                    }
985            }
986    
987            /**
988             * Deletes the group and its associated data.
989             *
990             * <p>
991             * The group is unstaged and its assets and resources including layouts,
992             * membership requests, subscriptions, teams, blogs, bookmarks, events,
993             * image gallery, journals, message boards, polls, shopping related
994             * entities, and wikis are also deleted.
995             * </p>
996             *
997             * @param  groupId the primary key of the group
998             * @return the deleted group
999             * @throws PortalException if a portal exception occurred
1000             */
1001            @Override
1002            public Group deleteGroup(long groupId) throws PortalException {
1003                    Group group = groupPersistence.findByPrimaryKey(groupId);
1004    
1005                    return deleteGroup(group);
1006            }
1007    
1008            @Override
1009            public synchronized void disableStaging(long groupId)
1010                    throws PortalException {
1011    
1012                    Group group = groupPersistence.findByPrimaryKey(groupId);
1013    
1014                    int stagingGroupCount = group.getRemoteStagingGroupCount();
1015    
1016                    if (stagingGroupCount > 0) {
1017                            stagingGroupCount = stagingGroupCount - 1;
1018    
1019                            group.setRemoteStagingGroupCount(stagingGroupCount);
1020    
1021                            if (stagingGroupCount == 0) {
1022                                    UnicodeProperties typeSettingsProperties =
1023                                            group.getTypeSettingsProperties();
1024    
1025                                    List<String> keys = new ArrayList<>();
1026    
1027                                    for (String key : typeSettingsProperties.keySet()) {
1028                                            if (key.startsWith(StagingConstants.STAGED_PORTLET)) {
1029                                                    keys.add(key);
1030                                            }
1031                                    }
1032    
1033                                    for (String key : keys) {
1034                                            typeSettingsProperties.remove(key);
1035                                    }
1036    
1037                                    group.setTypeSettingsProperties(typeSettingsProperties);
1038                            }
1039    
1040                            groupPersistence.update(group);
1041                    }
1042            }
1043    
1044            @Override
1045            public synchronized void enableStaging(long groupId)
1046                    throws PortalException {
1047    
1048                    Group group = groupPersistence.findByPrimaryKey(groupId);
1049    
1050                    int stagingGroupCount = group.getRemoteStagingGroupCount() + 1;
1051    
1052                    group.setRemoteStagingGroupCount(stagingGroupCount);
1053    
1054                    groupPersistence.update(group);
1055            }
1056    
1057            /**
1058             * Returns the company's group.
1059             *
1060             * @param  companyId the primary key of the company
1061             * @return the company's group, or <code>null</code> if a matching group
1062             *         could not be found
1063             */
1064            @Override
1065            public Group fetchCompanyGroup(long companyId) {
1066                    long classNameId = classNameLocalService.getClassNameId(Company.class);
1067    
1068                    return groupPersistence.fetchByC_C_C(companyId, classNameId, companyId);
1069            }
1070    
1071            /**
1072             * Returns the group with the matching friendly URL.
1073             *
1074             * @param  companyId the primary key of the company
1075             * @param  friendlyURL the friendly URL
1076             * @return the group with the friendly URL, or <code>null</code> if a
1077             *         matching group could not be found
1078             */
1079            @Override
1080            public Group fetchFriendlyURLGroup(long companyId, String friendlyURL) {
1081                    if (Validator.isNull(friendlyURL)) {
1082                            return null;
1083                    }
1084    
1085                    friendlyURL = getFriendlyURL(friendlyURL);
1086    
1087                    return groupPersistence.fetchByC_F(companyId, friendlyURL);
1088            }
1089    
1090            /**
1091             * Returns the group with the matching group key by first searching the
1092             * system groups and then using the finder cache.
1093             *
1094             * @param  companyId the primary key of the company
1095             * @param  groupKey the group key
1096             * @return the group with the group key and associated company, or
1097             *         <code>null</code> if a matching group could not be found
1098             */
1099            @Override
1100            @Skip
1101            public Group fetchGroup(long companyId, String groupKey) {
1102                    Group group = _systemGroupsMap.get(
1103                            StringUtil.toHexString(companyId).concat(groupKey));
1104    
1105                    if (group != null) {
1106                            return group;
1107                    }
1108    
1109                    return groupLocalService.loadFetchGroup(companyId, groupKey);
1110            }
1111    
1112            @Override
1113            public Group fetchUserGroup(long companyId, long userId) {
1114                    long classNameId = classNameLocalService.getClassNameId(User.class);
1115    
1116                    return groupPersistence.fetchByC_C_C(companyId, classNameId, userId);
1117            }
1118    
1119            /**
1120             * Returns the default user's personal site group.
1121             *
1122             * @param  companyId the primary key of the company
1123             * @return the default user's personal site group, or <code>null</code> if a
1124             *         matching group could not be found
1125             * @throws PortalException if a portal exception occurred
1126             */
1127            @Override
1128            public Group fetchUserPersonalSiteGroup(long companyId)
1129                    throws PortalException {
1130    
1131                    long classNameId = classNameLocalService.getClassNameId(
1132                            UserPersonalSite.class);
1133                    long defaultUserId = userLocalService.getDefaultUserId(companyId);
1134    
1135                    return groupPersistence.fetchByC_C_C(
1136                            companyId, classNameId, defaultUserId);
1137            }
1138    
1139            /**
1140             * Returns all the active or inactive groups associated with the company.
1141             *
1142             * @param  companyId the primary key of the company
1143             * @param  active whether to return only active groups, or only inactive
1144             *         groups
1145             * @return the active or inactive groups associated with the company
1146             */
1147            @Override
1148            public List<Group> getActiveGroups(long companyId, boolean active) {
1149                    return groupPersistence.findByC_A(companyId, active);
1150            }
1151    
1152            /**
1153             * Returns the company group.
1154             *
1155             * @param  companyId the primary key of the company
1156             * @return the group associated with the company
1157             * @throws PortalException if a portal exception occurred
1158             */
1159            @Override
1160            public Group getCompanyGroup(long companyId) throws PortalException {
1161                    long classNameId = classNameLocalService.getClassNameId(Company.class);
1162    
1163                    return groupPersistence.findByC_C_C(companyId, classNameId, companyId);
1164            }
1165    
1166            /**
1167             * Returns a range of all the groups associated with the company.
1168             *
1169             * <p>
1170             * Useful when paginating results. Returns a maximum of <code>end -
1171             * start</code> instances. <code>start</code> and <code>end</code> are not
1172             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1173             * refers to the first result in the set. Setting both <code>start</code>
1174             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
1175             * result set.
1176             * </p>
1177             *
1178             * @param  companyId the primary key of the company
1179             * @param  start the lower bound of the range of groups to return
1180             * @param  end the upper bound of the range of groups to return (not
1181             *         inclusive)
1182             * @return the range of groups associated with the company
1183             */
1184            @Override
1185            public List<Group> getCompanyGroups(long companyId, int start, int end) {
1186                    return groupPersistence.findByCompanyId(companyId, start, end);
1187            }
1188    
1189            /**
1190             * Returns the number of groups associated with the company.
1191             *
1192             * @param  companyId the primary key of the company
1193             * @return the number of groups associated with the company
1194             */
1195            @Override
1196            public int getCompanyGroupsCount(long companyId) {
1197                    return groupPersistence.countByCompanyId(companyId);
1198            }
1199    
1200            /**
1201             * Returns the group with the matching friendly URL.
1202             *
1203             * @param  companyId the primary key of the company
1204             * @param  friendlyURL the group's friendlyURL
1205             * @return the group with the friendly URL
1206             * @throws PortalException if a portal exception occurred
1207             */
1208            @Override
1209            public Group getFriendlyURLGroup(long companyId, String friendlyURL)
1210                    throws PortalException {
1211    
1212                    if (Validator.isNull(friendlyURL)) {
1213                            StringBundler sb = new StringBundler(5);
1214    
1215                            sb.append("{companyId=");
1216                            sb.append(companyId);
1217                            sb.append(", friendlyURL=");
1218                            sb.append(friendlyURL);
1219                            sb.append("}");
1220    
1221                            throw new NoSuchGroupException(sb.toString());
1222                    }
1223    
1224                    friendlyURL = getFriendlyURL(friendlyURL);
1225    
1226                    return groupPersistence.findByC_F(companyId, friendlyURL);
1227            }
1228    
1229            /**
1230             * Returns the group with the matching primary key.
1231             *
1232             * @param  groupId the primary key of the group
1233             * @return the group with the primary key
1234             * @throws PortalException if a portal exception occurred
1235             */
1236            @Override
1237            @ThreadLocalCachable
1238            public Group getGroup(long groupId) throws PortalException {
1239                    return groupPersistence.findByPrimaryKey(groupId);
1240            }
1241    
1242            /**
1243             * Returns the group with the matching group key.
1244             *
1245             * @param  companyId the primary key of the company
1246             * @param  groupKey the group key
1247             * @return the group with the group key
1248             * @throws PortalException if a portal exception occurred
1249             */
1250            @Override
1251            @Skip
1252            public Group getGroup(long companyId, String groupKey)
1253                    throws PortalException {
1254    
1255                    Group group = _systemGroupsMap.get(
1256                            StringUtil.toHexString(companyId).concat(groupKey));
1257    
1258                    if (group != null) {
1259                            return group;
1260                    }
1261    
1262                    return groupLocalService.loadGetGroup(companyId, groupKey);
1263            }
1264    
1265            /**
1266             * @deprecated As of 7.0.0, replaced by {@link
1267             *             Group#getDescriptiveName(Locale)}
1268             */
1269            @Deprecated
1270            @Override
1271            public String getGroupDescriptiveName(Group group, Locale locale)
1272                    throws PortalException {
1273    
1274                    return group.getDescriptiveName(locale);
1275            }
1276    
1277            /**
1278             * @deprecated As of 7.0.0, replaced by {@link
1279             *             Group#getDescriptiveName(Locale)}
1280             */
1281            @Deprecated
1282            @Override
1283            public String getGroupDescriptiveName(long groupId, Locale locale)
1284                    throws PortalException {
1285    
1286                    Group group = groupPersistence.findByPrimaryKey(groupId);
1287    
1288                    return group.getDescriptiveName(locale);
1289            }
1290    
1291            /**
1292             * Returns all the groups that are direct children of the parent group.
1293             *
1294             * @param  companyId the primary key of the company
1295             * @param  parentGroupId the primary key of the parent group
1296             * @param  site whether the group is to be associated with a main site
1297             * @return the matching groups, or <code>null</code> if no matches were
1298             *         found
1299             */
1300            @Override
1301            public List<Group> getGroups(
1302                    long companyId, long parentGroupId, boolean site) {
1303    
1304                    if (parentGroupId == GroupConstants.ANY_PARENT_GROUP_ID) {
1305                            return groupPersistence.findByC_S(companyId, site);
1306                    }
1307    
1308                    return groupPersistence.findByC_P_S(companyId, parentGroupId, site);
1309            }
1310    
1311            @Override
1312            public List<Group> getGroups(
1313                    long companyId, long parentGroupId, boolean site,
1314                    boolean inheritContent) {
1315    
1316                    return groupPersistence.findByC_P_S_I(
1317                            companyId, parentGroupId, site, inheritContent);
1318            }
1319    
1320            /**
1321             * Returns all the groups that are direct children of the parent group with
1322             * the matching className.
1323             *
1324             * @param  companyId the primary key of the company
1325             * @param  className the class name of the group
1326             * @param  parentGroupId the primary key of the parent group
1327             * @return the matching groups, or <code>null</code> if no matches were
1328             *         found
1329             */
1330            @Override
1331            public List<Group> getGroups(
1332                    long companyId, String className, long parentGroupId) {
1333    
1334                    long classNameId = classNameLocalService.getClassNameId(className);
1335    
1336                    return groupPersistence.findByC_C_P(
1337                            companyId, classNameId, parentGroupId);
1338            }
1339    
1340            /**
1341             * Returns a range of all the groups that are direct children of the parent
1342             * group with the matching className.
1343             *
1344             * @param  companyId the primary key of the company
1345             * @param  className the class name of the group
1346             * @param  parentGroupId the primary key of the parent group
1347             * @param  start the lower bound of the range of results
1348             * @param  end the upper bound of the range of results (not inclusive)
1349             * @return the range of matching groups
1350             */
1351            @Override
1352            public List<Group> getGroups(
1353                    long companyId, String className, long parentGroupId, int start,
1354                    int end) {
1355    
1356                    long classNameId = classNameLocalService.getClassNameId(className);
1357    
1358                    return groupPersistence.findByC_C_P(
1359                            companyId, classNameId, parentGroupId, start, end);
1360            }
1361    
1362            /**
1363             * Returns the groups with the matching primary keys.
1364             *
1365             * @param  groupIds the primary keys of the groups
1366             * @return the groups with the primary keys
1367             * @throws PortalException if a portal exception occurred
1368             */
1369            @Override
1370            public List<Group> getGroups(long[] groupIds) throws PortalException {
1371                    List<Group> groups = new ArrayList<>(groupIds.length);
1372    
1373                    for (long groupId : groupIds) {
1374                            Group group = getGroup(groupId);
1375    
1376                            groups.add(group);
1377                    }
1378    
1379                    return groups;
1380            }
1381    
1382            /**
1383             * Returns the number of groups that are direct children of the parent
1384             * group.
1385             *
1386             * @param  companyId the primary key of the company
1387             * @param  parentGroupId the primary key of the parent group
1388             * @param  site whether the group is to be associated with a main site
1389             * @return the number of matching groups
1390             */
1391            @Override
1392            public int getGroupsCount(
1393                    long companyId, long parentGroupId, boolean site) {
1394    
1395                    if (parentGroupId == GroupConstants.ANY_PARENT_GROUP_ID) {
1396                            return groupPersistence.countByC_S(companyId, site);
1397                    }
1398    
1399                    return groupPersistence.countByC_P_S(companyId, parentGroupId, site);
1400            }
1401    
1402            /**
1403             * Returns the number of groups that are direct children of the parent group
1404             * with the matching className.
1405             *
1406             * @param  companyId the primary key of the company
1407             * @param  className the class name of the group
1408             * @param  parentGroupId the primary key of the parent group
1409             * @return the number of matching groups
1410             */
1411            @Override
1412            public int getGroupsCount(
1413                    long companyId, String className, long parentGroupId) {
1414    
1415                    long classNameId = classNameLocalService.getClassNameId(className);
1416    
1417                    return groupPersistence.countByC_C_P(
1418                            companyId, classNameId, parentGroupId);
1419            }
1420    
1421            /**
1422             * Returns the group associated with the layout.
1423             *
1424             * @param  companyId the primary key of the company
1425             * @param  plid the primary key of the layout
1426             * @return the group associated with the layout
1427             * @throws PortalException if a portal exception occurred
1428             */
1429            @Override
1430            public Group getLayoutGroup(long companyId, long plid)
1431                    throws PortalException {
1432    
1433                    long classNameId = classNameLocalService.getClassNameId(Layout.class);
1434    
1435                    return groupPersistence.findByC_C_C(companyId, classNameId, plid);
1436            }
1437    
1438            /**
1439             * Returns the group associated with the layout prototype.
1440             *
1441             * @param  companyId the primary key of the company
1442             * @param  layoutPrototypeId the primary key of the layout prototype
1443             * @return the group associated with the layout prototype
1444             * @throws PortalException if a portal exception occurred
1445             */
1446            @Override
1447            public Group getLayoutPrototypeGroup(long companyId, long layoutPrototypeId)
1448                    throws PortalException {
1449    
1450                    long classNameId = classNameLocalService.getClassNameId(
1451                            LayoutPrototype.class);
1452    
1453                    return groupPersistence.findByC_C_C(
1454                            companyId, classNameId, layoutPrototypeId);
1455            }
1456    
1457            /**
1458             * Returns the group associated with the layout set prototype.
1459             *
1460             * @param  companyId the primary key of the company
1461             * @param  layoutSetPrototypeId the primary key of the layout set prototype
1462             * @return the group associated with the layout set prototype
1463             * @throws PortalException if a portal exception occurred
1464             */
1465            @Override
1466            public Group getLayoutSetPrototypeGroup(
1467                            long companyId, long layoutSetPrototypeId)
1468                    throws PortalException {
1469    
1470                    long classNameId = classNameLocalService.getClassNameId(
1471                            LayoutSetPrototype.class);
1472    
1473                    return groupPersistence.findByC_C_C(
1474                            companyId, classNameId, layoutSetPrototypeId);
1475            }
1476    
1477            /**
1478             * Returns a range of all groups that are children of the parent group and
1479             * that have at least one layout.
1480             *
1481             * <p>
1482             * Useful when paginating results. Returns a maximum of <code>end -
1483             * start</code> instances. <code>start</code> and <code>end</code> are not
1484             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1485             * refers to the first result in the set. Setting both <code>start</code>
1486             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
1487             * result set.
1488             * </p>
1489             *
1490             * @param      companyId the primary key of the company
1491             * @param      parentGroupId the primary key of the parent group
1492             * @param      site whether the group is to be associated with a main site
1493             * @param      start the lower bound of the range of groups to return
1494             * @param      end the upper bound of the range of groups to return (not
1495             *             inclusive)
1496             * @return     the range of matching groups
1497             * @deprecated As of 6.2.0, replaced by {@link #getLayoutsGroups(long, long,
1498             *             boolean, int, int, OrderByComparator)}
1499             */
1500            @Deprecated
1501            @Override
1502            public List<Group> getLayoutsGroups(
1503                    long companyId, long parentGroupId, boolean site, int start, int end) {
1504    
1505                    return getLayoutsGroups(
1506                            companyId, parentGroupId, site, start, end, null);
1507            }
1508    
1509            /**
1510             * Returns a range of all groups that are children of the parent group and
1511             * that have at least one layout.
1512             *
1513             * <p>
1514             * Useful when paginating results. Returns a maximum of <code>end -
1515             * start</code> instances. <code>start</code> and <code>end</code> are not
1516             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1517             * refers to the first result in the set. Setting both <code>start</code>
1518             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
1519             * result set.
1520             * </p>
1521             *
1522             * @param  companyId the primary key of the company
1523             * @param  parentGroupId the primary key of the parent group
1524             * @param  site whether the group is to be associated with a main site
1525             * @param  start the lower bound of the range of groups to return
1526             * @param  end the upper bound of the range of groups to return (not
1527             *         inclusive)
1528             * @param  obc the comparator to order the groups (optionally
1529             *         <code>null</code>)
1530             * @return the range of matching groups ordered by comparator
1531             *         <code>obc</code>
1532             */
1533            @Override
1534            public List<Group> getLayoutsGroups(
1535                    long companyId, long parentGroupId, boolean site, int start, int end,
1536                    OrderByComparator<Group> obc) {
1537    
1538                    return groupFinder.findByLayouts(
1539                            companyId, parentGroupId, site, start, end, obc);
1540            }
1541    
1542            /**
1543             * Returns the number of groups that are children or the parent group and
1544             * that have at least one layout
1545             *
1546             * @param  companyId the primary key of the company
1547             * @param  parentGroupId the primary key of the parent group
1548             * @param  site whether the group is to be associated with a main site
1549             * @return the number of matching groups
1550             */
1551            @Override
1552            public int getLayoutsGroupsCount(
1553                    long companyId, long parentGroupId, boolean site) {
1554    
1555                    return groupFinder.countByLayouts(companyId, parentGroupId, site);
1556            }
1557    
1558            /**
1559             * Returns all live groups.
1560             *
1561             * @return all live groups
1562             */
1563            @Override
1564            public List<Group> getLiveGroups() {
1565                    return groupFinder.findByLiveGroups();
1566            }
1567    
1568            /**
1569             * Returns a range of all non-system groups of a specified type (className)
1570             * that have no layouts.
1571             *
1572             * <p>
1573             * Useful when paginating results. Returns a maximum of <code>end -
1574             * start</code> instances. <code>start</code> and <code>end</code> are not
1575             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1576             * refers to the first result in the set. Setting both <code>start</code>
1577             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
1578             * result set.
1579             * </p>
1580             *
1581             * @param  className the entity's class name
1582             * @param  privateLayout whether to include groups with private layout sets
1583             *         or non-private layout sets
1584             * @param  start the lower bound of the range of groups to return
1585             * @param  end the upper bound of the range of groups to return (not
1586             *         inclusive)
1587             * @return the range of matching groups
1588             */
1589            @Override
1590            public List<Group> getNoLayoutsGroups(
1591                    String className, boolean privateLayout, int start, int end) {
1592    
1593                    long classNameId = classNameLocalService.getClassNameId(className);
1594    
1595                    return groupFinder.findByNoLayouts(
1596                            classNameId, privateLayout, start, end);
1597            }
1598    
1599            /**
1600             * Returns all non-system groups having <code>null</code> or empty friendly
1601             * URLs.
1602             *
1603             * @return the non-system groups having <code>null</code> or empty friendly
1604             *         URLs
1605             */
1606            @Override
1607            public List<Group> getNullFriendlyURLGroups() {
1608                    return groupFinder.findByNullFriendlyURL();
1609            }
1610    
1611            /**
1612             * Returns the specified organization group.
1613             *
1614             * @param  companyId the primary key of the company
1615             * @param  organizationId the primary key of the organization
1616             * @return the group associated with the organization
1617             * @throws PortalException if a portal exception occurred
1618             */
1619            @Override
1620            public Group getOrganizationGroup(long companyId, long organizationId)
1621                    throws PortalException {
1622    
1623                    long classNameId = classNameLocalService.getClassNameId(
1624                            Organization.class);
1625    
1626                    return groupPersistence.findByC_C_C(
1627                            companyId, classNameId, organizationId);
1628            }
1629    
1630            /**
1631             * Returns the specified organization groups.
1632             *
1633             * @param  organizations the organizations
1634             * @return the groups associated with the organizations
1635             */
1636            @Override
1637            public List<Group> getOrganizationsGroups(
1638                    List<Organization> organizations) {
1639    
1640                    List<Group> organizationGroups = new ArrayList<>();
1641    
1642                    for (int i = 0; i < organizations.size(); i++) {
1643                            Organization organization = organizations.get(i);
1644    
1645                            Group group = organization.getGroup();
1646    
1647                            organizationGroups.add(group);
1648                    }
1649    
1650                    return organizationGroups;
1651            }
1652    
1653            /**
1654             * Returns all the groups related to the organizations.
1655             *
1656             * @param  organizations the organizations
1657             * @return the groups related to the organizations
1658             */
1659            @Override
1660            public List<Group> getOrganizationsRelatedGroups(
1661                    List<Organization> organizations) {
1662    
1663                    List<Group> organizationGroups = new ArrayList<>();
1664    
1665                    for (int i = 0; i < organizations.size(); i++) {
1666                            Organization organization = organizations.get(i);
1667    
1668                            List<Group> groups = organizationPersistence.getGroups(
1669                                    organization.getOrganizationId());
1670    
1671                            organizationGroups.addAll(groups);
1672                    }
1673    
1674                    return organizationGroups;
1675            }
1676    
1677            /**
1678             * Returns the group followed by all its parent groups ordered by closest
1679             * ancestor.
1680             *
1681             * @param  groupId the primary key of the group
1682             * @return the group followed by all its parent groups ordered by closest
1683             *         ancestor
1684             * @throws PortalException if a portal exception occurred
1685             */
1686            @Override
1687            public List<Group> getParentGroups(long groupId) throws PortalException {
1688                    if (groupId == GroupConstants.DEFAULT_PARENT_GROUP_ID) {
1689                            return new ArrayList<>();
1690                    }
1691    
1692                    Group group = groupPersistence.findByPrimaryKey(groupId);
1693    
1694                    return group.getAncestors();
1695            }
1696    
1697            /**
1698             * Returns the staging group.
1699             *
1700             * @param  liveGroupId the primary key of the live group
1701             * @return the staging group
1702             * @throws PortalException if a portal exception occurred
1703             */
1704            @Override
1705            public Group getStagingGroup(long liveGroupId) throws PortalException {
1706                    return groupPersistence.findByLiveGroupId(liveGroupId);
1707            }
1708    
1709            /**
1710             * Returns the group directly associated with the user.
1711             *
1712             * @param  companyId the primary key of the company
1713             * @param  userId the primary key of the user
1714             * @return the group directly associated with the user
1715             * @throws PortalException if a portal exception occurred
1716             */
1717            @Override
1718            public Group getUserGroup(long companyId, long userId)
1719                    throws PortalException {
1720    
1721                    long classNameId = classNameLocalService.getClassNameId(User.class);
1722    
1723                    return groupPersistence.findByC_C_C(companyId, classNameId, userId);
1724            }
1725    
1726            /**
1727             * Returns the specified "user group" group. That is, the group that
1728             * represents the {@link UserGroup} entity.
1729             *
1730             * @param  companyId the primary key of the company
1731             * @param  userGroupId the primary key of the user group
1732             * @return the group associated with the user group
1733             * @throws PortalException if a portal exception occurred
1734             */
1735            @Override
1736            public Group getUserGroupGroup(long companyId, long userGroupId)
1737                    throws PortalException {
1738    
1739                    long classNameId = classNameLocalService.getClassNameId(
1740                            UserGroup.class);
1741    
1742                    return groupPersistence.findByC_C_C(
1743                            companyId, classNameId, userGroupId);
1744            }
1745    
1746            /**
1747             * Returns all the user's site groups and immediate organization groups,
1748             * optionally including the user's inherited organization groups and user
1749             * groups. System and staged groups are not included.
1750             *
1751             * @param  userId the primary key of the user
1752             * @param  inherit whether to include the user's inherited organization
1753             *         groups and user groups
1754             * @return the user's groups and immediate organization groups
1755             * @throws PortalException if a portal exception occurred
1756             */
1757            @Override
1758            public List<Group> getUserGroups(long userId, boolean inherit)
1759                    throws PortalException {
1760    
1761                    return getUserGroups(
1762                            userId, inherit, QueryUtil.ALL_POS, QueryUtil.ALL_POS);
1763            }
1764    
1765            /**
1766             * Returns an ordered range of all the user's site groups and immediate
1767             * organization groups, optionally including the user's inherited
1768             * organization groups and user groups. System and staged groups are not
1769             * included.
1770             *
1771             * <p>
1772             * Useful when paginating results. Returns a maximum of <code>end -
1773             * start</code> instances. <code>start</code> and <code>end</code> are not
1774             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1775             * refers to the first result in the set. Setting both <code>start</code>
1776             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
1777             * result set.
1778             * </p>
1779             *
1780             * @param  userId the primary key of the user
1781             * @param  inherit whether to include the user's inherited organization
1782             *         groups and user groups
1783             * @param  start the lower bound of the range of groups to return
1784             * @param  end the upper bound of the range of groups to return (not
1785             *         inclusive)
1786             * @return the range of the user's groups and immediate organization groups
1787             *         ordered by name
1788             * @throws PortalException if a portal exception occurred
1789             */
1790            @Override
1791            public List<Group> getUserGroups(
1792                            long userId, boolean inherit, int start, int end)
1793                    throws PortalException {
1794    
1795                    if (inherit) {
1796                            User user = userPersistence.findByPrimaryKey(userId);
1797    
1798                            LinkedHashMap<String, Object> groupParams = new LinkedHashMap<>();
1799    
1800                            groupParams.put("usersGroups", Long.valueOf(userId));
1801    
1802                            return search(
1803                                    user.getCompanyId(), null, null, groupParams, start, end);
1804                    }
1805                    else {
1806                            return userPersistence.getGroups(userId, start, end);
1807                    }
1808            }
1809    
1810            /**
1811             * Returns the groups associated with the user groups.
1812             *
1813             * @param  userGroups the user groups
1814             * @return the groups associated with the user groups
1815             * @throws PortalException if a portal exception occurred
1816             */
1817            @Override
1818            public List<Group> getUserGroupsGroups(List<UserGroup> userGroups)
1819                    throws PortalException {
1820    
1821                    List<Group> userGroupGroups = new ArrayList<>();
1822    
1823                    for (int i = 0; i < userGroups.size(); i++) {
1824                            UserGroup userGroup = userGroups.get(i);
1825    
1826                            Group group = userGroup.getGroup();
1827    
1828                            userGroupGroups.add(group);
1829                    }
1830    
1831                    return userGroupGroups;
1832            }
1833    
1834            /**
1835             * Returns all the groups related to the user groups.
1836             *
1837             * @param  userGroups the user groups
1838             * @return the groups related to the user groups
1839             */
1840            @Override
1841            public List<Group> getUserGroupsRelatedGroups(List<UserGroup> userGroups) {
1842                    List<Group> userGroupGroups = new ArrayList<>();
1843    
1844                    for (int i = 0; i < userGroups.size(); i++) {
1845                            UserGroup userGroup = userGroups.get(i);
1846    
1847                            List<Group> groups = userGroupPersistence.getGroups(
1848                                    userGroup.getUserGroupId());
1849    
1850                            userGroupGroups.addAll(groups);
1851                    }
1852    
1853                    return userGroupGroups;
1854            }
1855    
1856            /**
1857             * Returns the range of all groups associated with the user's organization
1858             * groups, including the ancestors of the organization groups, unless portal
1859             * property <code>organizations.membership.strict</code> is set to
1860             * <code>true</code>.
1861             *
1862             * <p>
1863             * Useful when paginating results. Returns a maximum of <code>end -
1864             * start</code> instances. <code>start</code> and <code>end</code> are not
1865             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1866             * refers to the first result in the set. Setting both <code>start</code>
1867             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
1868             * result set.
1869             * </p>
1870             *
1871             * @param  userId the primary key of the user
1872             * @param  start the lower bound of the range of groups to consider
1873             * @param  end the upper bound of the range of groups to consider (not
1874             *         inclusive)
1875             * @return the range of groups associated with the user's organization
1876             *         groups
1877             * @throws PortalException if a portal exception occurred
1878             */
1879            @Override
1880            public List<Group> getUserOrganizationsGroups(
1881                            long userId, int start, int end)
1882                    throws PortalException {
1883    
1884                    List<Group> userOrgsGroups = new ArrayList<>();
1885    
1886                    List<Organization> userOrgs =
1887                            organizationLocalService.getUserOrganizations(userId, start, end);
1888    
1889                    for (Organization organization : userOrgs) {
1890                            userOrgsGroups.add(0, organization.getGroup());
1891    
1892                            if (!PropsValues.ORGANIZATIONS_MEMBERSHIP_STRICT) {
1893                                    for (Organization ancestorOrganization :
1894                                                    organization.getAncestors()) {
1895    
1896                                            userOrgsGroups.add(0, ancestorOrganization.getGroup());
1897                                    }
1898                            }
1899                    }
1900    
1901                    return ListUtil.unique(userOrgsGroups);
1902            }
1903    
1904            /**
1905             * Returns the default user's personal site group.
1906             *
1907             * @param  companyId the primary key of the company
1908             * @return the default user's personal site group
1909             * @throws PortalException if a portal exception occurred
1910             */
1911            @Override
1912            public Group getUserPersonalSiteGroup(long companyId)
1913                    throws PortalException {
1914    
1915                    long classNameId = classNameLocalService.getClassNameId(
1916                            UserPersonalSite.class);
1917                    long defaultUserId = userLocalService.getDefaultUserId(companyId);
1918    
1919                    return groupPersistence.findByC_C_C(
1920                            companyId, classNameId, defaultUserId);
1921            }
1922    
1923            @Override
1924            public List<Group> getUserSitesGroups(long userId) throws PortalException {
1925                    User user = userPersistence.findByPrimaryKey(userId);
1926    
1927                    LinkedHashMap<String, Object> groupParams = new LinkedHashMap<>();
1928    
1929                    groupParams.put("inherit", Boolean.TRUE);
1930                    groupParams.put("site", Boolean.TRUE);
1931                    groupParams.put("usersGroups", userId);
1932    
1933                    return groupFinder.findByCompanyId(
1934                            user.getCompanyId(), groupParams, QueryUtil.ALL_POS,
1935                            QueryUtil.ALL_POS, new GroupNameComparator(true));
1936            }
1937    
1938            @Override
1939            public List<Group> getUserSitesGroups(
1940                            long userId, boolean includeAdministrative)
1941                    throws PortalException {
1942    
1943                    if (!includeAdministrative) {
1944                            return getUserSitesGroups(userId);
1945                    }
1946    
1947                    Set<Group> sites = new HashSet<>();
1948    
1949                    List<UserGroupRole> userGroupRoles =
1950                            userGroupRoleLocalService.getUserGroupRoles(userId);
1951    
1952                    for (UserGroupRole userGroupRole : userGroupRoles) {
1953                            Role role = userGroupRole.getRole();
1954    
1955                            String roleName = role.getName();
1956    
1957                            if (roleName.equals(RoleConstants.SITE_ADMINISTRATOR) ||
1958                                    roleName.equals(RoleConstants.SITE_OWNER)) {
1959    
1960                                    Group group = userGroupRole.getGroup();
1961    
1962                                    sites.add(group);
1963                            }
1964                    }
1965    
1966                    sites.addAll(getUserSitesGroups(userId));
1967    
1968                    return new ArrayList<>(sites);
1969            }
1970    
1971            /**
1972             * Returns <code>true</code> if the live group has a staging group.
1973             *
1974             * @param  liveGroupId the primary key of the live group
1975             * @return <code>true</code> if the live group has a staging group;
1976             *         <code>false</code> otherwise
1977             */
1978            @Override
1979            public boolean hasStagingGroup(long liveGroupId) {
1980                    if (groupPersistence.fetchByLiveGroupId(liveGroupId) != null) {
1981                            return true;
1982                    }
1983                    else {
1984                            return false;
1985                    }
1986            }
1987    
1988            /**
1989             * Returns <code>true</code> if the user is immediately associated with the
1990             * group, or associated with the group via the user's organizations,
1991             * inherited organizations, or user groups.
1992             *
1993             * @param  userId the primary key of the user
1994             * @param  groupId the primary key of the group
1995             * @return <code>true</code> if the user is associated with the group;
1996             *         <code>false</code> otherwise
1997             */
1998            @Override
1999            public boolean hasUserGroup(long userId, long groupId) {
2000                    return hasUserGroup(userId, groupId, true);
2001            }
2002    
2003            /**
2004             * Returns <code>true</code> if the user is immediately associated with the
2005             * group, or optionally if the user is associated with the group via the
2006             * user's organizations, inherited organizations, or user groups.
2007             *
2008             * @param  userId the primary key of the user
2009             * @param  groupId the primary key of the group
2010             * @param  inherit whether to include organization groups and user groups to
2011             *         which the user belongs in the determination
2012             * @return <code>true</code> if the user is associated with the group;
2013             *         <code>false</code> otherwise
2014             */
2015            @Override
2016            public boolean hasUserGroup(long userId, long groupId, boolean inherit) {
2017                    if (groupFinder.countByG_U(groupId, userId, inherit) > 0) {
2018                            return true;
2019                    }
2020                    else {
2021                            return false;
2022                    }
2023            }
2024    
2025            /**
2026             * Returns the group with the matching group key by first searching the
2027             * system groups and then using the finder cache.
2028             *
2029             * @param  companyId the primary key of the company
2030             * @param  groupKey the group key
2031             * @return the group with the group key and associated company, or
2032             *         <code>null</code> if a matching group could not be found
2033             */
2034            @Override
2035            public Group loadFetchGroup(long companyId, String groupKey) {
2036                    return groupPersistence.fetchByC_GK(companyId, groupKey);
2037            }
2038    
2039            /**
2040             * Returns the group with the matching group key.
2041             *
2042             * @param  companyId the primary key of the company
2043             * @param  groupKey the group key
2044             * @return the group with the group key and associated company
2045             * @throws PortalException if a portal exception occurred
2046             */
2047            @Override
2048            public Group loadGetGroup(long companyId, String groupKey)
2049                    throws PortalException {
2050    
2051                    return groupPersistence.findByC_GK(companyId, groupKey);
2052            }
2053    
2054            /**
2055             * Rebuilds the group tree.
2056             *
2057             * <p>
2058             * Only call this method if the tree has become stale through operations
2059             * other than normal CRUD. Under normal circumstances the tree is
2060             * automatically rebuilt whenever necessary.
2061             * </p>
2062             *
2063             * @param  companyId the primary key of the group's company
2064             * @throws PortalException if a portal exception occurred
2065             */
2066            @Override
2067            public void rebuildTree(long companyId) throws PortalException {
2068                    TreePathUtil.rebuildTree(
2069                            companyId, GroupConstants.DEFAULT_PARENT_GROUP_ID, StringPool.SLASH,
2070                            new TreeModelTasksAdapter<Group>() {
2071    
2072                                    @Override
2073                                    public List<Group> findTreeModels(
2074                                            long previousId, long companyId, long parentPrimaryKey,
2075                                            int size) {
2076    
2077                                            return groupPersistence.findByG_C_P(
2078                                                    previousId, companyId, parentPrimaryKey,
2079                                                    QueryUtil.ALL_POS, size, new GroupIdComparator(true));
2080                                    }
2081    
2082                            }
2083                    );
2084            }
2085    
2086            /**
2087             * Returns an ordered range of all the company's groups, optionally
2088             * including the user's inherited organization groups and user groups.
2089             * System and staged groups are not included.
2090             *
2091             * <p>
2092             * Useful when paginating results. Returns a maximum of <code>end -
2093             * start</code> instances. <code>start</code> and <code>end</code> are not
2094             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2095             * refers to the first result in the set. Setting both <code>start</code>
2096             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
2097             * result set.
2098             * </p>
2099             *
2100             * @param  companyId the primary key of the company
2101             * @param  params the finder params (optionally <code>null</code>). To
2102             *         include a user's organizations, inherited organizations, and user
2103             *         groups in the search, add an entry with key
2104             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
2105             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
2106             *         For more information see {@link
2107             *         com.liferay.portal.service.persistence.GroupFinder}.
2108             * @param  start the lower bound of the range of groups to return
2109             * @param  end the upper bound of the range of groups to return (not
2110             *         inclusive)
2111             * @return the matching groups ordered by name
2112             */
2113            @Override
2114            public List<Group> search(
2115                    long companyId, LinkedHashMap<String, Object> params, int start,
2116                    int end) {
2117    
2118                    return groupFinder.findByCompanyId(
2119                            companyId, params, start, end, new GroupNameComparator(true));
2120            }
2121    
2122            /**
2123             * Returns an ordered range of all the groups belonging to the parent group
2124             * that match the keywords, optionally including the user's inherited
2125             * organization groups and user groups. System and staged groups are not
2126             * included.
2127             *
2128             * <p>
2129             * Useful when paginating results. Returns a maximum of <code>end -
2130             * start</code> instances. <code>start</code> and <code>end</code> are not
2131             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2132             * refers to the first result in the set. Setting both <code>start</code>
2133             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
2134             * result set.
2135             * </p>
2136             *
2137             * @param  companyId the primary key of the company
2138             * @param  parentGroupId the primary key of the parent group
2139             * @param  keywords the keywords (space separated), which may occur in the
2140             *         sites's name, or description (optionally <code>null</code>)
2141             * @param  params the finder params (optionally <code>null</code>). To
2142             *         include the user's inherited organizations and user groups in the
2143             *         search, add entries having &quot;usersGroups&quot; and
2144             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2145             *         information see {@link
2146             *         com.liferay.portal.service.persistence.GroupFinder}.
2147             * @param  start the lower bound of the range of groups to return
2148             * @param  end the upper bound of the range of groups to return (not
2149             *         inclusive)
2150             * @return the matching groups ordered by name
2151             */
2152            @Override
2153            public List<Group> search(
2154                    long companyId, long parentGroupId, String keywords,
2155                    LinkedHashMap<String, Object> params, int start, int end) {
2156    
2157                    return search(
2158                            companyId, getClassNameIds(), parentGroupId, keywords, params,
2159                            start, end, null);
2160            }
2161    
2162            /**
2163             * Returns an ordered range of all the groups belonging to the parent group
2164             * that match the keywords, optionally including the user's inherited
2165             * organization groups and user groups. System and staged groups are not
2166             * included.
2167             *
2168             * <p>
2169             * Useful when paginating results. Returns a maximum of <code>end -
2170             * start</code> instances. <code>start</code> and <code>end</code> are not
2171             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2172             * refers to the first result in the set. Setting both <code>start</code>
2173             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
2174             * result set.
2175             * </p>
2176             *
2177             * @param  companyId the primary key of the company
2178             * @param  parentGroupId the primary key of the parent group
2179             * @param  keywords the keywords (space separated), which may occur in the
2180             *         sites's name, or description (optionally <code>null</code>)
2181             * @param  params the finder params (optionally <code>null</code>). To
2182             *         include the user's inherited organizations and user groups in the
2183             *         search, add entries having &quot;usersGroups&quot; and
2184             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2185             *         information see {@link
2186             *         com.liferay.portal.service.persistence.GroupFinder}.
2187             * @param  start the lower bound of the range of groups to return
2188             * @param  end the upper bound of the range of groups to return (not
2189             *         inclusive)
2190             * @param  obc the comparator to order the groups (optionally
2191             *         <code>null</code>)
2192             * @return the matching groups ordered by comparator <code>obc</code>
2193             */
2194            @Override
2195            public List<Group> search(
2196                    long companyId, long parentGroupId, String keywords,
2197                    LinkedHashMap<String, Object> params, int start, int end,
2198                    OrderByComparator<Group> obc) {
2199    
2200                    return search(
2201                            companyId, getClassNameIds(), parentGroupId, keywords, params,
2202                            start, end, obc);
2203            }
2204    
2205            /**
2206             * Returns an ordered range of all the site groups belonging to the parent
2207             * group and organization groups that match the name and description,
2208             * optionally including the user's inherited organization groups and user
2209             * groups. System and staged groups are not included.
2210             *
2211             * <p>
2212             * Useful when paginating results. Returns a maximum of <code>end -
2213             * start</code> instances. <code>start</code> and <code>end</code> are not
2214             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2215             * refers to the first result in the set. Setting both <code>start</code>
2216             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
2217             * result set.
2218             * </p>
2219             *
2220             * @param  companyId the primary key of the company
2221             * @param  parentGroupId the primary key of the parent group
2222             * @param  name the group's name (optionally <code>null</code>)
2223             * @param  description the group's description (optionally
2224             *         <code>null</code>)
2225             * @param  params the finder params (optionally <code>null</code>). To
2226             *         include the user's inherited organizations and user groups in the
2227             *         search, add entries having &quot;usersGroups&quot; and
2228             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2229             *         information see {@link
2230             *         com.liferay.portal.service.persistence.GroupFinder}.
2231             * @param  andOperator whether every field must match its keywords, or just
2232             *         one field.
2233             * @param  start the lower bound of the range of groups to return
2234             * @param  end the upper bound of the range of groups to return (not
2235             *         inclusive)
2236             * @return the matching groups ordered by name
2237             */
2238            @Override
2239            public List<Group> search(
2240                    long companyId, long parentGroupId, String name, String description,
2241                    LinkedHashMap<String, Object> params, boolean andOperator, int start,
2242                    int end) {
2243    
2244                    return search(
2245                            companyId, getClassNameIds(), parentGroupId, name, description,
2246                            params, andOperator, start, end, null);
2247            }
2248    
2249            /**
2250             * Returns an ordered range of all the site groups belonging to the parent
2251             * group and organization groups that match the name and description,
2252             * optionally including the user's inherited organization groups and user
2253             * groups. System and staged groups are not included.
2254             *
2255             * <p>
2256             * Useful when paginating results. Returns a maximum of <code>end -
2257             * start</code> instances. <code>start</code> and <code>end</code> are not
2258             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2259             * refers to the first result in the set. Setting both <code>start</code>
2260             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
2261             * result set.
2262             * </p>
2263             *
2264             * @param  companyId the primary key of the company
2265             * @param  parentGroupId the primary key of the parent group
2266             * @param  name the group's name (optionally <code>null</code>)
2267             * @param  description the group's description (optionally
2268             *         <code>null</code>)
2269             * @param  params the finder params (optionally <code>null</code>). To
2270             *         include the user's inherited organizations and user groups in the
2271             *         search, add entries having &quot;usersGroups&quot; and
2272             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2273             *         information see {@link
2274             *         com.liferay.portal.service.persistence.GroupFinder}.
2275             * @param  andOperator whether every field must match its keywords, or just
2276             *         one field.
2277             * @param  start the lower bound of the range of groups to return
2278             * @param  end the upper bound of the range of groups to return (not
2279             *         inclusive)
2280             * @param  obc the comparator to order the groups (optionally
2281             *         <code>null</code>)
2282             * @return the matching groups ordered by comparator <code>obc</code>
2283             */
2284            @Override
2285            public List<Group> search(
2286                    long companyId, long parentGroupId, String name, String description,
2287                    LinkedHashMap<String, Object> params, boolean andOperator, int start,
2288                    int end, OrderByComparator<Group> obc) {
2289    
2290                    return search(
2291                            companyId, getClassNameIds(), parentGroupId, name, description,
2292                            params, andOperator, start, end, obc);
2293            }
2294    
2295            /**
2296             * Returns an ordered range of all the groups belonging to the parent group
2297             * that match the class name IDs and keywords, optionally including the
2298             * user's inherited organization groups and user groups. System and staged
2299             * groups are not included.
2300             *
2301             * <p>
2302             * Useful when paginating results. Returns a maximum of <code>end -
2303             * start</code> instances. <code>start</code> and <code>end</code> are not
2304             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2305             * refers to the first result in the set. Setting both <code>start</code>
2306             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
2307             * result set.
2308             * </p>
2309             *
2310             * @param  companyId the primary key of the company
2311             * @param  classNameIds the primary keys of the class names of the entities
2312             *         the groups are related to (optionally <code>null</code>)
2313             * @param  parentGroupId the primary key of the parent group
2314             * @param  keywords the keywords (space separated), which may occur in the
2315             *         sites's name, or description (optionally <code>null</code>)
2316             * @param  params the finder params (optionally <code>null</code>). To
2317             *         include a user's organizations, inherited organizations, and user
2318             *         groups in the search, add an entry with key
2319             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
2320             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
2321             *         For more information see {@link
2322             *         com.liferay.portal.service.persistence.GroupFinder}.
2323             * @param  start the lower bound of the range of groups to return
2324             * @param  end the upper bound of the range of groups to return (not
2325             *         inclusive)
2326             * @return the matching groups ordered by name
2327             */
2328            @Override
2329            public List<Group> search(
2330                    long companyId, long[] classNameIds, long parentGroupId,
2331                    String keywords, LinkedHashMap<String, Object> params, int start,
2332                    int end) {
2333    
2334                    return search(
2335                            companyId, classNameIds, parentGroupId, keywords, params, start,
2336                            end, null);
2337            }
2338    
2339            /**
2340             * Returns an ordered range of all the groups belonging to the parent group
2341             * that match the class name IDs and keywords, optionally including the
2342             * user's inherited organization groups and user groups. System and staged
2343             * groups are not included.
2344             *
2345             * <p>
2346             * Useful when paginating results. Returns a maximum of <code>end -
2347             * start</code> instances. <code>start</code> and <code>end</code> are not
2348             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2349             * refers to the first result in the set. Setting both <code>start</code>
2350             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
2351             * result set.
2352             * </p>
2353             *
2354             * @param  companyId the primary key of the company
2355             * @param  classNameIds the primary keys of the class names of the entities
2356             *         the groups are related to (optionally <code>null</code>)
2357             * @param  parentGroupId the primary key of the parent group
2358             * @param  keywords the keywords (space separated), which may occur in the
2359             *         sites's name, or description (optionally <code>null</code>)
2360             * @param  params the finder params (optionally <code>null</code>). To
2361             *         include a user's organizations, inherited organizations, and user
2362             *         groups in the search, add an entry with key
2363             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
2364             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
2365             *         For more information see {@link
2366             *         com.liferay.portal.service.persistence.GroupFinder}.
2367             * @param  start the lower bound of the range of groups to return
2368             * @param  end the upper bound of the range of groups to return (not
2369             *         inclusive)
2370             * @param  obc the comparator to order the groups (optionally
2371             *         <code>null</code>)
2372             * @return the matching groups ordered by comparator <code>obc</code>
2373             */
2374            @Override
2375            public List<Group> search(
2376                    long companyId, long[] classNameIds, long parentGroupId,
2377                    String keywords, LinkedHashMap<String, Object> params, int start,
2378                    int end, OrderByComparator<Group> obc) {
2379    
2380                    String[] keywordsArray = getSearchNames(companyId, keywords);
2381    
2382                    boolean andOperator = false;
2383    
2384                    if (Validator.isNull(keywords)) {
2385                            andOperator = true;
2386                    }
2387    
2388                    if (isUseComplexSQL(classNameIds)) {
2389                            return groupFinder.findByC_C_PG_N_D(
2390                                    companyId, classNameIds, parentGroupId, keywordsArray,
2391                                    keywordsArray, params, andOperator, start, end, obc);
2392                    }
2393    
2394                    Collection<Group> groups = doSearch(
2395                            companyId, classNameIds, parentGroupId, keywordsArray,
2396                            keywordsArray, params, andOperator);
2397    
2398                    return sort(groups, start, end, obc);
2399            }
2400    
2401            /**
2402             * Returns an ordered range of all the groups belonging to the parent group
2403             * that match the class name IDs, name, and description, optionally
2404             * including the user's inherited organization groups and user groups.
2405             * System and staged groups are not included.
2406             *
2407             * <p>
2408             * Useful when paginating results. Returns a maximum of <code>end -
2409             * start</code> instances. <code>start</code> and <code>end</code> are not
2410             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2411             * refers to the first result in the set. Setting both <code>start</code>
2412             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
2413             * result set.
2414             * </p>
2415             *
2416             * @param  companyId the primary key of the company
2417             * @param  classNameIds the primary keys of the class names of the entities
2418             *         the groups are related to (optionally <code>null</code>)
2419             * @param  parentGroupId the primary key of the parent group
2420             * @param  name the group's name (optionally <code>null</code>)
2421             * @param  description the group's description (optionally
2422             *         <code>null</code>)
2423             * @param  params the finder params (optionally <code>null</code>). To
2424             *         include a user's organizations, inherited organizations, and user
2425             *         groups in the search, add an entry with key
2426             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
2427             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
2428             *         For more information see {@link
2429             *         com.liferay.portal.service.persistence.GroupFinder}.
2430             * @param  andOperator whether every field must match its keywords, or just
2431             *         one field.
2432             * @param  start the lower bound of the range of groups to return
2433             * @param  end the upper bound of the range of groups to return (not
2434             *         inclusive)
2435             * @return the matching groups ordered by name
2436             */
2437            @Override
2438            public List<Group> search(
2439                    long companyId, long[] classNameIds, long parentGroupId, String name,
2440                    String description, LinkedHashMap<String, Object> params,
2441                    boolean andOperator, int start, int end) {
2442    
2443                    return search(
2444                            companyId, classNameIds, parentGroupId, name, description, params,
2445                            andOperator, start, end, null);
2446            }
2447    
2448            /**
2449             * Returns an ordered range of all the groups belonging to the parent group
2450             * that match the class name IDs, name, and description, optionally
2451             * including the user's inherited organization groups and user groups.
2452             * System and staged groups are not included.
2453             *
2454             * <p>
2455             * Useful when paginating results. Returns a maximum of <code>end -
2456             * start</code> instances. <code>start</code> and <code>end</code> are not
2457             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2458             * refers to the first result in the set. Setting both <code>start</code>
2459             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
2460             * result set.
2461             * </p>
2462             *
2463             * @param  companyId the primary key of the company
2464             * @param  classNameIds the primary keys of the class names of the entities
2465             *         the groups are related to (optionally <code>null</code>)
2466             * @param  parentGroupId the primary key of the parent group
2467             * @param  name the group's name (optionally <code>null</code>)
2468             * @param  description the group's description (optionally
2469             *         <code>null</code>)
2470             * @param  params the finder params (optionally <code>null</code>). To
2471             *         include a user's organizations, inherited organizations, and user
2472             *         groups in the search, add an entry with key
2473             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
2474             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
2475             *         For more information see {@link
2476             *         com.liferay.portal.service.persistence.GroupFinder}.
2477             * @param  andOperator whether every field must match its keywords, or just
2478             *         one field.
2479             * @param  start the lower bound of the range of groups to return
2480             * @param  end the upper bound of the range of groups to return (not
2481             *         inclusive)
2482             * @param  obc the comparator to order the groups (optionally
2483             *         <code>null</code>)
2484             * @return the matching groups ordered by comparator <code>obc</code>
2485             */
2486            @Override
2487            public List<Group> search(
2488                    long companyId, long[] classNameIds, long parentGroupId, String name,
2489                    String description, LinkedHashMap<String, Object> params,
2490                    boolean andOperator, int start, int end, OrderByComparator<Group> obc) {
2491    
2492                    String[] names = getSearchNames(companyId, name);
2493                    String[] descriptions = CustomSQLUtil.keywords(description);
2494    
2495                    if (isUseComplexSQL(classNameIds)) {
2496                            return groupFinder.findByC_C_PG_N_D(
2497                                    companyId, classNameIds, parentGroupId, names, descriptions,
2498                                    params, andOperator, start, end, obc);
2499                    }
2500    
2501                    Collection<Group> groups = doSearch(
2502                            companyId, classNameIds, parentGroupId, names, descriptions, params,
2503                            andOperator);
2504    
2505                    return sort(groups, start, end, obc);
2506            }
2507    
2508            /**
2509             * Returns an ordered range of all the groups that match the class name IDs
2510             * and keywords, optionally including the user's inherited organization
2511             * groups and user groups. System and staged groups are not included.
2512             *
2513             * <p>
2514             * Useful when paginating results. Returns a maximum of <code>end -
2515             * start</code> instances. <code>start</code> and <code>end</code> are not
2516             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2517             * refers to the first result in the set. Setting both <code>start</code>
2518             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
2519             * result set.
2520             * </p>
2521             *
2522             * @param  companyId the primary key of the company
2523             * @param  classNameIds the primary keys of the class names of the entities
2524             *         the groups are related to (optionally <code>null</code>)
2525             * @param  keywords the keywords (space separated), which may occur in the
2526             *         sites's name, or description (optionally <code>null</code>)
2527             * @param  params the finder params (optionally <code>null</code>). To
2528             *         include a user's organizations, inherited organizations, and user
2529             *         groups in the search, add an entry with key
2530             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
2531             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
2532             *         For more information see {@link
2533             *         com.liferay.portal.service.persistence.GroupFinder}.
2534             * @param  start the lower bound of the range of groups to return
2535             * @param  end the upper bound of the range of groups to return (not
2536             *         inclusive)
2537             * @return the matching groups ordered by name
2538             */
2539            @Override
2540            public List<Group> search(
2541                    long companyId, long[] classNameIds, String keywords,
2542                    LinkedHashMap<String, Object> params, int start, int end) {
2543    
2544                    return search(
2545                            companyId, classNameIds, GroupConstants.ANY_PARENT_GROUP_ID,
2546                            keywords, params, start, end, null);
2547            }
2548    
2549            /**
2550             * Returns an ordered range of all the groups that match the class name IDs
2551             * and keywords, optionally including the user's inherited organization
2552             * groups and user groups. System and staged groups are not included.
2553             *
2554             * <p>
2555             * Useful when paginating results. Returns a maximum of <code>end -
2556             * start</code> instances. <code>start</code> and <code>end</code> are not
2557             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2558             * refers to the first result in the set. Setting both <code>start</code>
2559             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
2560             * result set.
2561             * </p>
2562             *
2563             * @param  companyId the primary key of the company
2564             * @param  classNameIds the primary keys of the class names of the entities
2565             *         the groups are related to (optionally <code>null</code>)
2566             * @param  keywords the keywords (space separated), which may occur in the
2567             *         sites's name, or description (optionally <code>null</code>)
2568             * @param  params the finder params (optionally <code>null</code>). To
2569             *         include a user's organizations, inherited organizations, and user
2570             *         groups in the search, add an entry with key
2571             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
2572             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
2573             *         For more information see {@link
2574             *         com.liferay.portal.service.persistence.GroupFinder}.
2575             * @param  start the lower bound of the range of groups to return
2576             * @param  end the upper bound of the range of groups to return (not
2577             *         inclusive)
2578             * @param  obc the comparator to order the groups (optionally
2579             *         <code>null</code>)
2580             * @return the matching groups ordered by comparator <code>obc</code>
2581             */
2582            @Override
2583            public List<Group> search(
2584                    long companyId, long[] classNameIds, String keywords,
2585                    LinkedHashMap<String, Object> params, int start, int end,
2586                    OrderByComparator<Group> obc) {
2587    
2588                    return search(
2589                            companyId, classNameIds, GroupConstants.ANY_PARENT_GROUP_ID,
2590                            keywords, params, start, end, obc);
2591            }
2592    
2593            /**
2594             * Returns an ordered range of all the groups that match the class name IDs,
2595             * name, and description, optionally including the user's inherited
2596             * organization groups and user groups. System and staged groups are not
2597             * included.
2598             *
2599             * <p>
2600             * Useful when paginating results. Returns a maximum of <code>end -
2601             * start</code> instances. <code>start</code> and <code>end</code> are not
2602             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2603             * refers to the first result in the set. Setting both <code>start</code>
2604             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
2605             * result set.
2606             * </p>
2607             *
2608             * @param  companyId the primary key of the company
2609             * @param  classNameIds the primary keys of the class names of the entities
2610             *         the groups are related to (optionally <code>null</code>)
2611             * @param  name the group's name (optionally <code>null</code>)
2612             * @param  description the group's description (optionally
2613             *         <code>null</code>)
2614             * @param  params the finder params (optionally <code>null</code>). To
2615             *         include a user's organizations, inherited organizations, and user
2616             *         groups in the search, add an entry with key
2617             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
2618             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
2619             *         For more information see {@link
2620             *         com.liferay.portal.service.persistence.GroupFinder}.
2621             * @param  andOperator whether every field must match its keywords, or just
2622             *         one field.
2623             * @param  start the lower bound of the range of groups to return
2624             * @param  end the upper bound of the range of groups to return (not
2625             *         inclusive)
2626             * @return the matching groups ordered by name
2627             */
2628            @Override
2629            public List<Group> search(
2630                    long companyId, long[] classNameIds, String name, String description,
2631                    LinkedHashMap<String, Object> params, boolean andOperator, int start,
2632                    int end) {
2633    
2634                    return search(
2635                            companyId, classNameIds, GroupConstants.ANY_PARENT_GROUP_ID, name,
2636                            description, params, andOperator, start, end, null);
2637            }
2638    
2639            /**
2640             * Returns an ordered range of all the groups that match the class name IDs,
2641             * name, and description, optionally including the user's inherited
2642             * organization groups and user groups. System and staged groups are not
2643             * included.
2644             *
2645             * <p>
2646             * Useful when paginating results. Returns a maximum of <code>end -
2647             * start</code> instances. <code>start</code> and <code>end</code> are not
2648             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2649             * refers to the first result in the set. Setting both <code>start</code>
2650             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
2651             * result set.
2652             * </p>
2653             *
2654             * @param  companyId the primary key of the company
2655             * @param  classNameIds the primary keys of the class names of the entities
2656             *         the groups are related to (optionally <code>null</code>)
2657             * @param  name the group's name (optionally <code>null</code>)
2658             * @param  description the group's description (optionally
2659             *         <code>null</code>)
2660             * @param  params the finder params (optionally <code>null</code>). To
2661             *         include a user's organizations, inherited organizations, and user
2662             *         groups in the search, add an entry with key
2663             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
2664             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
2665             *         For more information see {@link
2666             *         com.liferay.portal.service.persistence.GroupFinder}.
2667             * @param  andOperator whether every field must match its keywords, or just
2668             *         one field.
2669             * @param  start the lower bound of the range of groups to return
2670             * @param  end the upper bound of the range of groups to return (not
2671             *         inclusive)
2672             * @param  obc the comparator to order the groups (optionally
2673             *         <code>null</code>)
2674             * @return the matching groups ordered by comparator <code>obc</code>
2675             */
2676            @Override
2677            public List<Group> search(
2678                    long companyId, long[] classNameIds, String name, String description,
2679                    LinkedHashMap<String, Object> params, boolean andOperator, int start,
2680                    int end, OrderByComparator<Group> obc) {
2681    
2682                    return search(
2683                            companyId, classNameIds, GroupConstants.ANY_PARENT_GROUP_ID, name,
2684                            description, params, andOperator, start, end, obc);
2685            }
2686    
2687            /**
2688             * Returns an ordered range of all the groups that match the keywords,
2689             * optionally including the user's inherited organization groups and user
2690             * groups. System and staged groups are not included.
2691             *
2692             * <p>
2693             * Useful when paginating results. Returns a maximum of <code>end -
2694             * start</code> instances. <code>start</code> and <code>end</code> are not
2695             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2696             * refers to the first result in the set. Setting both <code>start</code>
2697             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
2698             * result set.
2699             * </p>
2700             *
2701             * @param  companyId the primary key of the company
2702             * @param  keywords the keywords (space separated), which may occur in the
2703             *         sites's name, or description (optionally <code>null</code>)
2704             * @param  params the finder params (optionally <code>null</code>). To
2705             *         include the user's inherited organizations and user groups in the
2706             *         search, add entries having &quot;usersGroups&quot; and
2707             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2708             *         information see {@link
2709             *         com.liferay.portal.service.persistence.GroupFinder}.
2710             * @param  start the lower bound of the range of groups to return
2711             * @param  end the upper bound of the range of groups to return (not
2712             *         inclusive)
2713             * @return the matching groups ordered by name
2714             */
2715            @Override
2716            @ThreadLocalCachable
2717            public List<Group> search(
2718                    long companyId, String keywords, LinkedHashMap<String, Object> params,
2719                    int start, int end) {
2720    
2721                    return search(
2722                            companyId, getClassNameIds(), GroupConstants.ANY_PARENT_GROUP_ID,
2723                            keywords, params, start, end, null);
2724            }
2725    
2726            /**
2727             * Returns an ordered range of all the groups that match the keywords,
2728             * optionally including the user's inherited organization groups and user
2729             * groups. System and staged groups are not included.
2730             *
2731             * <p>
2732             * Useful when paginating results. Returns a maximum of <code>end -
2733             * start</code> instances. <code>start</code> and <code>end</code> are not
2734             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2735             * refers to the first result in the set. Setting both <code>start</code>
2736             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
2737             * result set.
2738             * </p>
2739             *
2740             * @param  companyId the primary key of the company
2741             * @param  keywords the keywords (space separated), which may occur in the
2742             *         sites's name, or description (optionally <code>null</code>)
2743             * @param  params the finder params (optionally <code>null</code>). To
2744             *         include the user's inherited organizations and user groups in the
2745             *         search, add entries having &quot;usersGroups&quot; and
2746             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2747             *         information see {@link
2748             *         com.liferay.portal.service.persistence.GroupFinder}.
2749             * @param  start the lower bound of the range of groups to return
2750             * @param  end the upper bound of the range of groups to return (not
2751             *         inclusive)
2752             * @param  obc the comparator to order the groups (optionally
2753             *         <code>null</code>)
2754             * @return the matching groups ordered by comparator <code>obc</code>
2755             */
2756            @Override
2757            public List<Group> search(
2758                    long companyId, String keywords, LinkedHashMap<String, Object> params,
2759                    int start, int end, OrderByComparator<Group> obc) {
2760    
2761                    return search(
2762                            companyId, getClassNameIds(), GroupConstants.ANY_PARENT_GROUP_ID,
2763                            keywords, params, start, end, obc);
2764            }
2765    
2766            /**
2767             * Returns an ordered range of all the site groups and organization groups
2768             * that match the name and description, optionally including the user's
2769             * inherited organization groups and user groups. System and staged groups
2770             * are not included.
2771             *
2772             * <p>
2773             * Useful when paginating results. Returns a maximum of <code>end -
2774             * start</code> instances. <code>start</code> and <code>end</code> are not
2775             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2776             * refers to the first result in the set. Setting both <code>start</code>
2777             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
2778             * result set.
2779             * </p>
2780             *
2781             * @param  companyId the primary key of the company
2782             * @param  name the group's name (optionally <code>null</code>)
2783             * @param  description the group's description (optionally
2784             *         <code>null</code>)
2785             * @param  params the finder params (optionally <code>null</code>). To
2786             *         include the user's inherited organizations and user groups in the
2787             *         search, add entries having &quot;usersGroups&quot; and
2788             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2789             *         information see {@link
2790             *         com.liferay.portal.service.persistence.GroupFinder}.
2791             * @param  andOperator whether every field must match its keywords, or just
2792             *         one field.
2793             * @param  start the lower bound of the range of groups to return
2794             * @param  end the upper bound of the range of groups to return (not
2795             *         inclusive)
2796             * @return the matching groups ordered by name
2797             */
2798            @Override
2799            public List<Group> search(
2800                    long companyId, String name, String description,
2801                    LinkedHashMap<String, Object> params, boolean andOperator, int start,
2802                    int end) {
2803    
2804                    return search(
2805                            companyId, getClassNameIds(), GroupConstants.ANY_PARENT_GROUP_ID,
2806                            name, description, params, andOperator, start, end, null);
2807            }
2808    
2809            /**
2810             * Returns an ordered range of all the site groups and organization groups
2811             * that match the name and description, optionally including the user's
2812             * inherited organization groups and user groups. System and staged groups
2813             * are not included.
2814             *
2815             * <p>
2816             * Useful when paginating results. Returns a maximum of <code>end -
2817             * start</code> instances. <code>start</code> and <code>end</code> are not
2818             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2819             * refers to the first result in the set. Setting both <code>start</code>
2820             * and <code>end</code> to {@link QueryUtil#ALL_POS} will return the full
2821             * result set.
2822             * </p>
2823             *
2824             * @param  companyId the primary key of the company
2825             * @param  name the group's name (optionally <code>null</code>)
2826             * @param  description the group's description (optionally
2827             *         <code>null</code>)
2828             * @param  params the finder params (optionally <code>null</code>). To
2829             *         include the user's inherited organizations and user groups in the
2830             *         search, add entries having &quot;usersGroups&quot; and
2831             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2832             *         information see {@link
2833             *         com.liferay.portal.service.persistence.GroupFinder}.
2834             * @param  andOperator whether every field must match its keywords, or just
2835             *         one field.
2836             * @param  start the lower bound of the range of groups to return
2837             * @param  end the upper bound of the range of groups to return (not
2838             *         inclusive)
2839             * @param  obc the comparator to order the groups (optionally
2840             *         <code>null</code>)
2841             * @return the matching groups ordered by comparator <code>obc</code>
2842             */
2843            @Override
2844            public List<Group> search(
2845                    long companyId, String name, String description,
2846                    LinkedHashMap<String, Object> params, boolean andOperator, int start,
2847                    int end, OrderByComparator<Group> obc) {
2848    
2849                    return search(
2850                            companyId, getClassNameIds(), GroupConstants.ANY_PARENT_GROUP_ID,
2851                            name, description, params, andOperator, start, end, obc);
2852            }
2853    
2854            /**
2855             * Returns the number of groups belonging to the parent group that match the
2856             * keywords, optionally including the user's inherited organization groups
2857             * and user groups. System and staged groups are not included.
2858             *
2859             * @param  companyId the primary key of the company
2860             * @param  parentGroupId the primary key of the parent group
2861             * @param  keywords the keywords (space separated), which may occur in the
2862             *         sites's name, or description (optionally <code>null</code>)
2863             * @param  params the finder params (optionally <code>null</code>). To
2864             *         include the user's inherited organization groups and user groups
2865             *         in the search, add entries having &quot;usersGroups&quot; and
2866             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2867             *         information see {@link
2868             *         com.liferay.portal.service.persistence.GroupFinder}.
2869             * @return the number of matching groups
2870             */
2871            @Override
2872            @ThreadLocalCachable
2873            public int searchCount(
2874                    long companyId, long parentGroupId, String keywords,
2875                    LinkedHashMap<String, Object> params) {
2876    
2877                    return searchCount(
2878                            companyId, getClassNameIds(), parentGroupId, keywords, params);
2879            }
2880    
2881            /**
2882             * Returns the number of groups belonging to the parent group and immediate
2883             * organization groups that match the name and description, optionally
2884             * including the user's inherited organization groups and user groups.
2885             * System and staged groups are not included.
2886             *
2887             * @param  companyId the primary key of the company
2888             * @param  parentGroupId the primary key of the parent group
2889             * @param  name the group's name (optionally <code>null</code>)
2890             * @param  description the group's description (optionally
2891             *         <code>null</code>)
2892             * @param  params the finder params (optionally <code>null</code>). To
2893             *         include the user's inherited organization groups and user groups
2894             *         in the search, add entries having &quot;usersGroups&quot; and
2895             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2896             *         information see {@link
2897             *         com.liferay.portal.service.persistence.GroupFinder}.
2898             * @param  andOperator whether every field must match its keywords, or just
2899             *         one field.
2900             * @return the number of matching groups
2901             */
2902            @Override
2903            @ThreadLocalCachable
2904            public int searchCount(
2905                    long companyId, long parentGroupId, String name, String description,
2906                    LinkedHashMap<String, Object> params, boolean andOperator) {
2907    
2908                    return searchCount(
2909                            companyId, getClassNameIds(), parentGroupId, name, description,
2910                            params, andOperator);
2911            }
2912    
2913            /**
2914             * Returns the number of groups belonging to the parent group that match the
2915             * class name IDs, and keywords, optionally including the user's inherited
2916             * organization groups and user groups. System and staged groups are not
2917             * included.
2918             *
2919             * @param  companyId the primary key of the company
2920             * @param  classNameIds the primary keys of the class names of the entities
2921             *         the groups are related to (optionally <code>null</code>)
2922             * @param  parentGroupId the primary key of the parent group
2923             * @param  keywords the keywords (space separated), which may occur in the
2924             *         sites's name, or description (optionally <code>null</code>)
2925             * @param  params the finder params (optionally <code>null</code>). To
2926             *         include the user's inherited organization groups and user groups
2927             *         in the search, add entries having &quot;usersGroups&quot; and
2928             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2929             *         information see {@link
2930             *         com.liferay.portal.service.persistence.GroupFinder}.
2931             * @return the number of matching groups
2932             */
2933            @Override
2934            @ThreadLocalCachable
2935            public int searchCount(
2936                    long companyId, long[] classNameIds, long parentGroupId,
2937                    String keywords, LinkedHashMap<String, Object> params) {
2938    
2939                    String[] keywordsArray = getSearchNames(companyId, keywords);
2940    
2941                    boolean andOperator = false;
2942    
2943                    if (Validator.isNull(keywords)) {
2944                            andOperator = true;
2945                    }
2946    
2947                    if (isUseComplexSQL(classNameIds)) {
2948                            return groupFinder.countByC_C_PG_N_D(
2949                                    companyId, classNameIds, parentGroupId, keywordsArray,
2950                                    keywordsArray, params, andOperator);
2951                    }
2952    
2953                    Collection<Group> groups = doSearch(
2954                            companyId, classNameIds, parentGroupId, keywordsArray,
2955                            keywordsArray, params, andOperator);
2956    
2957                    return groups.size();
2958            }
2959    
2960            /**
2961             * Returns the number of groups belonging to the parent group that match the
2962             * class name IDs, name, and description, optionally including the user's
2963             * inherited organization groups and user groups. System and staged groups
2964             * are not included.
2965             *
2966             * @param  companyId the primary key of the company
2967             * @param  classNameIds the primary keys of the class names of the entities
2968             *         the groups are related to (optionally <code>null</code>)
2969             * @param  parentGroupId the primary key of the parent group
2970             * @param  name the group's name (optionally <code>null</code>)
2971             * @param  description the group's description (optionally
2972             *         <code>null</code>)
2973             * @param  params the finder params (optionally <code>null</code>). To
2974             *         include the user's inherited organization groups and user groups
2975             *         in the search, add entries having &quot;usersGroups&quot; and
2976             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2977             *         information see {@link
2978             *         com.liferay.portal.service.persistence.GroupFinder}.
2979             * @param  andOperator whether every field must match its keywords, or just
2980             *         one field.
2981             * @return the number of matching groups
2982             */
2983            @Override
2984            @ThreadLocalCachable
2985            public int searchCount(
2986                    long companyId, long[] classNameIds, long parentGroupId, String name,
2987                    String description, LinkedHashMap<String, Object> params,
2988                    boolean andOperator) {
2989    
2990                    String[] names = getSearchNames(companyId, name);
2991                    String[] descriptions = CustomSQLUtil.keywords(description);
2992    
2993                    if (isUseComplexSQL(classNameIds)) {
2994                            return groupFinder.countByC_C_PG_N_D(
2995                                    companyId, classNameIds, parentGroupId, names, descriptions,
2996                                    params, andOperator);
2997                    }
2998    
2999                    Collection<Group> groups = doSearch(
3000                            companyId, classNameIds, parentGroupId, names, descriptions, params,
3001                            andOperator);
3002    
3003                    return groups.size();
3004            }
3005    
3006            /**
3007             * Returns the number of groups that match the class name IDs, and keywords,
3008             * optionally including the user's inherited organization groups and user
3009             * groups. System and staged groups are not included.
3010             *
3011             * @param  companyId the primary key of the company
3012             * @param  classNameIds the primary keys of the class names of the entities
3013             *         the groups are related to (optionally <code>null</code>)
3014             * @param  keywords the keywords (space separated), which may occur in the
3015             *         sites's name, or description (optionally <code>null</code>)
3016             * @param  params the finder params (optionally <code>null</code>). To
3017             *         include the user's inherited organization groups and user groups
3018             *         in the search, add entries having &quot;usersGroups&quot; and
3019             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
3020             *         information see {@link
3021             *         com.liferay.portal.service.persistence.GroupFinder}.
3022             * @return the number of matching groups
3023             */
3024            @Override
3025            @ThreadLocalCachable
3026            public int searchCount(
3027                    long companyId, long[] classNameIds, String keywords,
3028                    LinkedHashMap<String, Object> params) {
3029    
3030                    return searchCount(
3031                            companyId, classNameIds, GroupConstants.ANY_PARENT_GROUP_ID,
3032                            keywords, params);
3033            }
3034    
3035            /**
3036             * Returns the number of groups that match the class name IDs, name, and
3037             * description, optionally including the user's inherited organization
3038             * groups and user groups. System and staged groups are not included.
3039             *
3040             * @param  companyId the primary key of the company
3041             * @param  classNameIds the primary keys of the class names of the entities
3042             *         the groups are related to (optionally <code>null</code>)
3043             * @param  name the group's name (optionally <code>null</code>)
3044             * @param  description the group's description (optionally
3045             *         <code>null</code>)
3046             * @param  params the finder params (optionally <code>null</code>). To
3047             *         include the user's inherited organization groups and user groups
3048             *         in the search, add entries having &quot;usersGroups&quot; and
3049             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
3050             *         information see {@link
3051             *         com.liferay.portal.service.persistence.GroupFinder}.
3052             * @param  andOperator whether every field must match its keywords, or just
3053             *         one field.
3054             * @return the number of matching groups
3055             */
3056            @Override
3057            @ThreadLocalCachable
3058            public int searchCount(
3059                    long companyId, long[] classNameIds, String name, String description,
3060                    LinkedHashMap<String, Object> params, boolean andOperator) {
3061    
3062                    return searchCount(
3063                            companyId, classNameIds, GroupConstants.ANY_PARENT_GROUP_ID, name,
3064                            description, params, andOperator);
3065            }
3066    
3067            /**
3068             * Returns the number of groups that match the keywords, optionally
3069             * including the user's inherited organization groups and user groups.
3070             * System and staged groups are not included.
3071             *
3072             * @param  companyId the primary key of the company
3073             * @param  keywords the keywords (space separated), which may occur in the
3074             *         sites's name, or description (optionally <code>null</code>)
3075             * @param  params the finder params (optionally <code>null</code>). To
3076             *         include the user's inherited organization groups and user groups
3077             *         in the search, add entries having &quot;usersGroups&quot; and
3078             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
3079             *         information see {@link
3080             *         com.liferay.portal.service.persistence.GroupFinder}.
3081             * @return the number of matching groups
3082             */
3083            @Override
3084            @ThreadLocalCachable
3085            public int searchCount(
3086                    long companyId, String keywords, LinkedHashMap<String, Object> params) {
3087    
3088                    return searchCount(
3089                            companyId, getClassNameIds(), GroupConstants.ANY_PARENT_GROUP_ID,
3090                            keywords, params);
3091            }
3092    
3093            /**
3094             * Returns the number of groups and immediate organization groups that match
3095             * the name and description, optionally including the user's inherited
3096             * organization groups and user groups. System and staged groups are not
3097             * included.
3098             *
3099             * @param  companyId the primary key of the company
3100             * @param  name the group's name (optionally <code>null</code>)
3101             * @param  description the group's description (optionally
3102             *         <code>null</code>)
3103             * @param  params the finder params (optionally <code>null</code>). To
3104             *         include the user's inherited organization groups and user groups
3105             *         in the search, add entries having &quot;usersGroups&quot; and
3106             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
3107             *         information see {@link
3108             *         com.liferay.portal.service.persistence.GroupFinder}.
3109             * @param  andOperator whether every field must match its keywords, or just
3110             *         one field.
3111             * @return the number of matching groups
3112             */
3113            @Override
3114            @ThreadLocalCachable
3115            public int searchCount(
3116                    long companyId, String name, String description,
3117                    LinkedHashMap<String, Object> params, boolean andOperator) {
3118    
3119                    return searchCount(
3120                            companyId, getClassNameIds(), GroupConstants.ANY_PARENT_GROUP_ID,
3121                            name, description, params, andOperator);
3122            }
3123    
3124            /**
3125             * Sets the groups associated with the role, removing and adding
3126             * associations as necessary.
3127             *
3128             * @param roleId the primary key of the role
3129             * @param groupIds the primary keys of the groups
3130             */
3131            @Override
3132            public void setRoleGroups(long roleId, long[] groupIds) {
3133                    rolePersistence.setGroups(roleId, groupIds);
3134    
3135                    PermissionCacheUtil.clearCache();
3136            }
3137    
3138            /**
3139             * Removes the groups from the role.
3140             *
3141             * @param roleId the primary key of the role
3142             * @param groupIds the primary keys of the groups
3143             */
3144            @Override
3145            public void unsetRoleGroups(long roleId, long[] groupIds) {
3146                    rolePersistence.removeGroups(roleId, groupIds);
3147    
3148                    PermissionCacheUtil.clearCache();
3149            }
3150    
3151            /**
3152             * Removes the user from the groups.
3153             *
3154             * @param userId the primary key of the user
3155             * @param groupIds the primary keys of the groups
3156             */
3157            @Override
3158            public void unsetUserGroups(long userId, long[] groupIds) {
3159                    userGroupRoleLocalService.deleteUserGroupRoles(userId, groupIds);
3160    
3161                    userPersistence.removeGroups(userId, groupIds);
3162    
3163                    PermissionCacheUtil.clearCache(userId);
3164            }
3165    
3166            /**
3167             * Updates the group's asset replacing categories and tag names.
3168             *
3169             * @param  userId the primary key of the user
3170             * @param  group the group
3171             * @param  assetCategoryIds the primary keys of the asset categories
3172             *         (optionally <code>null</code>)
3173             * @param  assetTagNames the asset tag names (optionally <code>null</code>)
3174             * @throws PortalException if a portal exception occurred
3175             */
3176            @Override
3177            public void updateAsset(
3178                            long userId, Group group, long[] assetCategoryIds,
3179                            String[] assetTagNames)
3180                    throws PortalException {
3181    
3182                    User user = userPersistence.findByPrimaryKey(userId);
3183    
3184                    Company company = companyPersistence.findByPrimaryKey(
3185                            user.getCompanyId());
3186    
3187                    Group companyGroup = company.getGroup();
3188    
3189                    assetEntryLocalService.updateEntry(
3190                            userId, companyGroup.getGroupId(), null, null,
3191                            Group.class.getName(), group.getGroupId(), null, 0,
3192                            assetCategoryIds, assetTagNames, false, null, null, null, null,
3193                            group.getDescriptiveName(), group.getDescription(), null, null,
3194                            null, 0, 0, null);
3195            }
3196    
3197            /**
3198             * Updates the group's friendly URL.
3199             *
3200             * @param  groupId the primary key of the group
3201             * @param  friendlyURL the group's new friendlyURL (optionally
3202             *         <code>null</code>)
3203             * @return the group
3204             * @throws PortalException if a portal exception occurred
3205             */
3206            @Override
3207            public Group updateFriendlyURL(long groupId, String friendlyURL)
3208                    throws PortalException {
3209    
3210                    Group group = groupPersistence.findByPrimaryKey(groupId);
3211    
3212                    if (group.isUser()) {
3213                            User user = userPersistence.findByPrimaryKey(group.getClassPK());
3214    
3215                            friendlyURL = StringPool.SLASH + user.getScreenName();
3216    
3217                            if (group.getFriendlyURL().equals(friendlyURL)) {
3218                                    return group;
3219                            }
3220                    }
3221    
3222                    friendlyURL = getFriendlyURL(
3223                            group.getCompanyId(), groupId, group.getClassNameId(),
3224                            group.getClassPK(), StringPool.BLANK, friendlyURL);
3225    
3226                    validateFriendlyURL(
3227                            group.getCompanyId(), group.getGroupId(), group.getClassNameId(),
3228                            group.getClassPK(), friendlyURL);
3229    
3230                    group.setFriendlyURL(friendlyURL);
3231    
3232                    groupPersistence.update(group);
3233    
3234                    return group;
3235            }
3236    
3237            @Override
3238            public Group updateGroup(
3239                            long groupId, long parentGroupId, Map<Locale, String> nameMap,
3240                            Map<Locale, String> descriptionMap, int type,
3241                            boolean manualMembership, int membershipRestriction,
3242                            String friendlyURL, boolean inheritContent, boolean active,
3243                            ServiceContext serviceContext)
3244                    throws PortalException {
3245    
3246                    Group group = groupPersistence.findByPrimaryKey(groupId);
3247    
3248                    String className = group.getClassName();
3249                    long classNameId = group.getClassNameId();
3250                    long classPK = group.getClassPK();
3251    
3252                    String groupKey = group.getGroupKey();
3253    
3254                    if ((nameMap != null) &&
3255                            Validator.isNotNull(nameMap.get(LocaleUtil.getDefault()))) {
3256    
3257                            groupKey = nameMap.get(LocaleUtil.getDefault());
3258                    }
3259    
3260                    friendlyURL = getFriendlyURL(
3261                            group.getCompanyId(), groupId, classNameId, classPK,
3262                            StringPool.BLANK, friendlyURL);
3263    
3264                    if ((classNameId <= 0) || className.equals(Group.class.getName())) {
3265                            validateGroupKey(
3266                                    group.getGroupId(), group.getCompanyId(), groupKey,
3267                                    group.isSite());
3268                    }
3269                    else if (className.equals(Organization.class.getName())) {
3270                            Organization organization =
3271                                    organizationPersistence.findByPrimaryKey(classPK);
3272    
3273                            groupKey = getOrgGroupName(organization.getName());
3274                    }
3275                    else if (!GroupConstants.USER_PERSONAL_SITE.equals(
3276                                            group.getGroupKey())) {
3277    
3278                            groupKey = String.valueOf(classPK);
3279                    }
3280    
3281                    if (PortalUtil.isSystemGroup(group.getGroupKey()) &&
3282                            !groupKey.equals(group.getGroupKey())) {
3283    
3284                            throw new RequiredGroupException.MustNotDeleteSystemGroup(
3285                                    group.getGroupId());
3286                    }
3287    
3288                    validateFriendlyURL(
3289                            group.getCompanyId(), group.getGroupId(), group.getClassNameId(),
3290                            group.getClassPK(), friendlyURL);
3291    
3292                    validateParentGroup(group.getGroupId(), parentGroupId);
3293    
3294                    group.setParentGroupId(parentGroupId);
3295                    group.setTreePath(group.buildTreePath());
3296                    group.setGroupKey(groupKey);
3297                    group.setNameMap(nameMap);
3298                    group.setDescriptionMap(descriptionMap);
3299                    group.setType(type);
3300                    group.setManualMembership(manualMembership);
3301                    group.setMembershipRestriction(membershipRestriction);
3302                    group.setFriendlyURL(friendlyURL);
3303                    group.setInheritContent(inheritContent);
3304                    group.setActive(active);
3305    
3306                    if ((serviceContext != null) && group.isSite()) {
3307                            group.setExpandoBridgeAttributes(serviceContext);
3308                    }
3309    
3310                    groupPersistence.update(group);
3311    
3312                    // Asset
3313    
3314                    if ((serviceContext == null) || !group.isSite()) {
3315                            return group;
3316                    }
3317    
3318                    User user = null;
3319    
3320                    user = userPersistence.fetchByPrimaryKey(group.getCreatorUserId());
3321    
3322                    if (user == null) {
3323                            user = userPersistence.fetchByPrimaryKey(
3324                                    serviceContext.getUserId());
3325                    }
3326    
3327                    if (user == null) {
3328                            user = userLocalService.getDefaultUser(group.getCompanyId());
3329                    }
3330    
3331                    updateAsset(
3332                            user.getUserId(), group, serviceContext.getAssetCategoryIds(),
3333                            serviceContext.getAssetTagNames());
3334    
3335                    return group;
3336            }
3337    
3338            /**
3339             * Updates the group.
3340             *
3341             * @param      groupId the primary key of the group
3342             * @param      parentGroupId the primary key of the parent group
3343             * @param      name the name's key
3344             * @param      description the group's new description (optionally
3345             *             <code>null</code>)
3346             * @param      type the group's new type. For more information see {@link
3347             *             GroupConstants}.
3348             * @param      manualMembership whether manual membership is allowed for the
3349             *             group
3350             * @param      membershipRestriction the group's membership restriction. For
3351             *             more information see {@link GroupConstants}.
3352             * @param      friendlyURL the group's new friendlyURL (optionally
3353             *             <code>null</code>)
3354             * @param      inheritContent whether to inherit content from the parent
3355             *             group
3356             * @param      active whether the group is active
3357             * @param      serviceContext the service context to be applied (optionally
3358             *             <code>null</code>). Can set asset category IDs and asset tag
3359             *             names for the group.
3360             * @return     the group
3361             * @throws     PortalException if a portal exception occurred
3362             * @deprecated As of 7.0.0, replaced by {@link #updateGroup(long, long, Map,
3363             *             Map, int, boolean, int, String, boolean, boolean,
3364             *             ServiceContext)}
3365             */
3366            @Deprecated
3367            @Override
3368            public Group updateGroup(
3369                            long groupId, long parentGroupId, String name, String description,
3370                            int type, boolean manualMembership, int membershipRestriction,
3371                            String friendlyURL, boolean inheritContent, boolean active,
3372                            ServiceContext serviceContext)
3373                    throws PortalException {
3374    
3375                    return updateGroup(
3376                            groupId, parentGroupId, getLocalizationMap(name),
3377                            getLocalizationMap(description), type, manualMembership,
3378                            membershipRestriction, friendlyURL, inheritContent, active,
3379                            serviceContext);
3380            }
3381    
3382            /**
3383             * Updates the group's type settings.
3384             *
3385             * @param  groupId the primary key of the group
3386             * @param  typeSettings the group's new type settings (optionally
3387             *         <code>null</code>)
3388             * @return the group
3389             * @throws PortalException if a portal exception occurred
3390             */
3391            @Override
3392            public Group updateGroup(long groupId, String typeSettings)
3393                    throws PortalException {
3394    
3395                    Group group = groupPersistence.findByPrimaryKey(groupId);
3396    
3397                    UnicodeProperties oldTypeSettingsProperties =
3398                            group.getTypeSettingsProperties();
3399    
3400                    UnicodeProperties typeSettingsProperties = new UnicodeProperties(true);
3401    
3402                    typeSettingsProperties.fastLoad(typeSettings);
3403    
3404                    String newLanguageIds = typeSettingsProperties.getProperty(
3405                            PropsKeys.LOCALES);
3406    
3407                    if (Validator.isNotNull(newLanguageIds)) {
3408                            String oldLanguageIds = oldTypeSettingsProperties.getProperty(
3409                                    PropsKeys.LOCALES, StringPool.BLANK);
3410    
3411                            String defaultLanguageId = typeSettingsProperties.getProperty(
3412                                    "languageId", LocaleUtil.toLanguageId(LocaleUtil.getDefault()));
3413    
3414                            validateLanguageIds(defaultLanguageId, newLanguageIds);
3415    
3416                            if (!Validator.equals(oldLanguageIds, newLanguageIds)) {
3417                                    LanguageUtil.resetAvailableGroupLocales(groupId);
3418                            }
3419                    }
3420    
3421                    group.setTypeSettings(typeSettings);
3422    
3423                    groupPersistence.update(group);
3424    
3425                    return group;
3426            }
3427    
3428            /**
3429             * Associates the group with a main site if the group is an organization.
3430             *
3431             * @param  groupId the primary key of the group
3432             * @param  site whether the group is to be associated with a main site
3433             * @return the group
3434             * @throws PortalException if a portal exception occurred
3435             */
3436            @Override
3437            public Group updateSite(long groupId, boolean site) throws PortalException {
3438                    Group group = groupPersistence.findByPrimaryKey(groupId);
3439    
3440                    if (!group.isOrganization()) {
3441                            return group;
3442                    }
3443    
3444                    group.setSite(site);
3445    
3446                    groupPersistence.update(group);
3447    
3448                    return group;
3449            }
3450    
3451            protected void addControlPanelLayouts(Group group) throws PortalException {
3452                    long defaultUserId = userLocalService.getDefaultUserId(
3453                            group.getCompanyId());
3454    
3455                    String friendlyURL = getFriendlyURL(
3456                            PropsValues.CONTROL_PANEL_LAYOUT_FRIENDLY_URL);
3457    
3458                    ServiceContext serviceContext = new ServiceContext();
3459    
3460                    serviceContext.setAttribute(
3461                            "layout.instanceable.allowed", Boolean.TRUE);
3462    
3463                    layoutLocalService.addLayout(
3464                            defaultUserId, group.getGroupId(), true,
3465                            LayoutConstants.DEFAULT_PARENT_LAYOUT_ID,
3466                            PropsValues.CONTROL_PANEL_LAYOUT_NAME, StringPool.BLANK,
3467                            StringPool.BLANK, LayoutConstants.TYPE_CONTROL_PANEL, false,
3468                            friendlyURL, serviceContext);
3469            }
3470    
3471            protected void addDefaultGuestPublicLayoutByProperties(Group group)
3472                    throws PortalException {
3473    
3474                    List<Portlet> portlets = portletLocalService.getPortlets(
3475                            group.getCompanyId());
3476    
3477                    if (portlets.isEmpty()) {
3478    
3479                            // LPS-38457
3480    
3481                            return;
3482                    }
3483    
3484                    long defaultUserId = userLocalService.getDefaultUserId(
3485                            group.getCompanyId());
3486                    String friendlyURL = getFriendlyURL(
3487                            PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_FRIENDLY_URL);
3488    
3489                    ServiceContext serviceContext = new ServiceContext();
3490    
3491                    Layout layout = layoutLocalService.addLayout(
3492                            defaultUserId, group.getGroupId(), false,
3493                            LayoutConstants.DEFAULT_PARENT_LAYOUT_ID,
3494                            PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_NAME, StringPool.BLANK,
3495                            StringPool.BLANK, LayoutConstants.TYPE_PORTLET, false, friendlyURL,
3496                            serviceContext);
3497    
3498                    LayoutTypePortlet layoutTypePortlet =
3499                            (LayoutTypePortlet)layout.getLayoutType();
3500    
3501                    layoutTypePortlet.setLayoutTemplateId(
3502                            0, PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_TEMPLATE_ID, false);
3503    
3504                    LayoutTemplate layoutTemplate = layoutTypePortlet.getLayoutTemplate();
3505    
3506                    for (String columnId : layoutTemplate.getColumns()) {
3507                            String keyPrefix = PropsKeys.DEFAULT_GUEST_PUBLIC_LAYOUT_PREFIX;
3508    
3509                            String portletIds = PropsUtil.get(keyPrefix.concat(columnId));
3510    
3511                            layoutTypePortlet.addPortletIds(
3512                                    0, StringUtil.split(portletIds), columnId, false);
3513                    }
3514    
3515                    layoutLocalService.updateLayout(
3516                            layout.getGroupId(), layout.isPrivateLayout(), layout.getLayoutId(),
3517                            layout.getTypeSettings());
3518    
3519                    boolean updateLayoutSet = false;
3520    
3521                    LayoutSet layoutSet = layout.getLayoutSet();
3522    
3523                    if (Validator.isNotNull(
3524                                    PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_REGULAR_THEME_ID)) {
3525    
3526                            layoutSet.setThemeId(
3527                                    PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_REGULAR_THEME_ID);
3528    
3529                            updateLayoutSet = true;
3530                    }
3531    
3532                    if (Validator.isNotNull(
3533                                    PropsValues.
3534                                            DEFAULT_GUEST_PUBLIC_LAYOUT_REGULAR_COLOR_SCHEME_ID)) {
3535    
3536                            layoutSet.setColorSchemeId(
3537                                    PropsValues.
3538                                            DEFAULT_GUEST_PUBLIC_LAYOUT_REGULAR_COLOR_SCHEME_ID);
3539    
3540                            updateLayoutSet = true;
3541                    }
3542    
3543                    if (Validator.isNotNull(
3544                                    PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_WAP_THEME_ID)) {
3545    
3546                            layoutSet.setWapThemeId(
3547                                    PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_WAP_THEME_ID);
3548    
3549                            updateLayoutSet = true;
3550                    }
3551    
3552                    if (Validator.isNotNull(
3553                                    PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_WAP_COLOR_SCHEME_ID)) {
3554    
3555                            layoutSet.setWapColorSchemeId(
3556                                    PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_WAP_COLOR_SCHEME_ID);
3557    
3558                            updateLayoutSet = true;
3559                    }
3560    
3561                    if (updateLayoutSet) {
3562                            layoutSetLocalService.updateLayoutSet(layoutSet);
3563                    }
3564            }
3565    
3566            protected void addDefaultGuestPublicLayouts(Group group)
3567                    throws PortalException {
3568    
3569                    if (publicLARFile != null) {
3570                            addDefaultGuestPublicLayoutsByLAR(group, publicLARFile);
3571                    }
3572                    else {
3573                            addDefaultGuestPublicLayoutByProperties(group);
3574                    }
3575            }
3576    
3577            protected void addDefaultGuestPublicLayoutsByLAR(Group group, File larFile)
3578                    throws PortalException {
3579    
3580                    User defaultUser = userLocalService.getDefaultUser(
3581                            group.getCompanyId());
3582    
3583                    Map<String, String[]> parameterMap = new HashMap<>();
3584    
3585                    parameterMap.put(
3586                            PortletDataHandlerKeys.PERMISSIONS,
3587                            new String[] {Boolean.TRUE.toString()});
3588                    parameterMap.put(
3589                            PortletDataHandlerKeys.PORTLET_CONFIGURATION,
3590                            new String[] {Boolean.TRUE.toString()});
3591                    parameterMap.put(
3592                            PortletDataHandlerKeys.PORTLET_DATA,
3593                            new String[] {Boolean.TRUE.toString()});
3594                    parameterMap.put(
3595                            PortletDataHandlerKeys.PORTLET_DATA_CONTROL_DEFAULT,
3596                            new String[] {Boolean.TRUE.toString()});
3597    
3598                    Map<String, Serializable> importLayoutSettingsMap =
3599                            ExportImportConfigurationSettingsMapFactory.
3600                                    buildImportLayoutSettingsMap(
3601                                            defaultUser, group.getGroupId(), false, null, parameterMap);
3602    
3603                    ExportImportConfiguration exportImportConfiguration =
3604                            exportImportConfigurationLocalService.
3605                                    addDraftExportImportConfiguration(
3606                                            defaultUser.getUserId(),
3607                                            ExportImportConfigurationConstants.TYPE_IMPORT_LAYOUT,
3608                                            importLayoutSettingsMap);
3609    
3610                    exportImportLocalService.importLayouts(
3611                            exportImportConfiguration, larFile);
3612            }
3613    
3614            protected void addPortletDefaultData(Group group) throws PortalException {
3615                    PortletDataContext portletDataContext =
3616                            PortletDataContextFactoryUtil.createPreparePortletDataContext(
3617                                    group.getCompanyId(), group.getGroupId(), null, null);
3618    
3619                    List<PortletDataHandler> portletDataHandlers = getPortletDataHandlers(
3620                            group);
3621    
3622                    for (PortletDataHandler portletDataHandler : portletDataHandlers) {
3623                            try {
3624                                    portletDataHandler.addDefaultData(
3625                                            portletDataContext, portletDataHandler.getPortletId(),
3626                                            null);
3627                            }
3628                            catch (Exception e) {
3629                                    _log.error(
3630                                            "Unable to add default data for portlet " +
3631                                                    portletDataHandler.getPortletId() + " in group " +
3632                                                            group.getGroupId());
3633    
3634                                    if (portletDataHandler.isRollbackOnException()) {
3635                                            throw new SystemException(e);
3636                                    }
3637                            }
3638                    }
3639            }
3640    
3641            protected void deletePortletData(Group group) throws PortalException {
3642                    PortletDataContext portletDataContext =
3643                            PortletDataContextFactoryUtil.createPreparePortletDataContext(
3644                                    group.getCompanyId(), group.getGroupId(), null, null);
3645    
3646                    List<PortletDataHandler> portletDataHandlers = getPortletDataHandlers(
3647                            group);
3648    
3649                    for (PortletDataHandler portletDataHandler : portletDataHandlers) {
3650                            try {
3651                                    portletDataHandler.deleteData(
3652                                            portletDataContext, portletDataHandler.getPortletId(),
3653                                            null);
3654                            }
3655                            catch (Exception e) {
3656                                    _log.error(
3657                                            "Unable to delete data for portlet " +
3658                                                    portletDataHandler.getPortletId() + " in group " +
3659                                                            group.getGroupId());
3660    
3661                                    if (portletDataHandler.isRollbackOnException()) {
3662                                            throw new SystemException(e);
3663                                    }
3664                            }
3665                    }
3666            }
3667    
3668            protected Collection<Group> doSearch(
3669                    long companyId, long[] classNameIds, long parentGroupId, String[] names,
3670                    String[] descriptions, LinkedHashMap<String, Object> params,
3671                    boolean andOperator) {
3672    
3673                    boolean parentGroupIdEquals = true;
3674    
3675                    if (parentGroupId == GroupConstants.ANY_PARENT_GROUP_ID) {
3676                            parentGroupIdEquals = false;
3677                    }
3678    
3679                    params = new LinkedHashMap<>(params);
3680    
3681                    Boolean active = (Boolean)params.remove("active");
3682                    List<Long> excludedGroupIds = (List<Long>)params.remove(
3683                            "excludedGroupIds");
3684                    List<Group> groupsTree = (List<Group>)params.remove("groupsTree");
3685                    Boolean manualMembership = (Boolean)params.remove("manualMembership");
3686                    Integer membershipRestriction = (Integer)params.remove(
3687                            "membershipRestriction");
3688                    Boolean site = (Boolean)params.remove("site");
3689                    List<Integer> types = (List<Integer>)params.remove("types");
3690    
3691                    Collection<Group> groups = new HashSet<>();
3692    
3693                    Long userId = (Long)params.remove("usersGroups");
3694    
3695                    for (long classNameId : classNameIds) {
3696                            groups.addAll(groupPersistence.findByC_C(companyId, classNameId));
3697                    }
3698    
3699                    Iterator<Group> iterator = groups.iterator();
3700    
3701                    while (iterator.hasNext()) {
3702                            Group group = iterator.next();
3703    
3704                            // Filter by live group ID
3705    
3706                            long liveGroupId = group.getLiveGroupId();
3707    
3708                            if (liveGroupId != 0) {
3709                                    iterator.remove();
3710    
3711                                    continue;
3712                            }
3713    
3714                            // Filter by parent group ID
3715    
3716                            long groupParentGroupId = group.getParentGroupId();
3717    
3718                            if ((parentGroupIdEquals &&
3719                                     (groupParentGroupId != parentGroupId)) ||
3720                                    (!parentGroupIdEquals &&
3721                                     (groupParentGroupId == parentGroupId))) {
3722    
3723                                    iterator.remove();
3724    
3725                                    continue;
3726                            }
3727    
3728                            // Filter by name and description
3729    
3730                            String groupKey = group.getGroupKey();
3731    
3732                            if (groupKey.equals(GroupConstants.CONTROL_PANEL)) {
3733                                    iterator.remove();
3734    
3735                                    continue;
3736                            }
3737    
3738                            boolean containsName = matches(group.getNameCurrentValue(), names);
3739                            boolean containsDescription = matches(
3740                                    group.getDescriptionCurrentValue(), descriptions);
3741    
3742                            if ((andOperator && (!containsName || !containsDescription)) ||
3743                                    (!andOperator && !containsName && !containsDescription)) {
3744    
3745                                    iterator.remove();
3746    
3747                                    continue;
3748                            }
3749    
3750                            // Filter by active
3751    
3752                            if (active != null) {
3753                                    if (active != group.isActive()) {
3754                                            iterator.remove();
3755    
3756                                            continue;
3757                                    }
3758                            }
3759    
3760                            // Filter by excluded group IDs
3761    
3762                            if ((excludedGroupIds != null) &&
3763                                    excludedGroupIds.contains(group.getGroupId())) {
3764    
3765                                    iterator.remove();
3766    
3767                                    continue;
3768                            }
3769    
3770                            // Filter by groups tree
3771    
3772                            if (groupsTree != null) {
3773                                    String treePath = group.getTreePath();
3774    
3775                                    boolean matched = false;
3776    
3777                                    for (Group groupTree : groupsTree) {
3778                                            String groupTreePath = StringUtil.quote(
3779                                                    String.valueOf(groupTree.getGroupId()),
3780                                                    StringPool.SLASH);
3781    
3782                                            if (treePath.contains(groupTreePath)) {
3783                                                    matched = true;
3784    
3785                                                    break;
3786                                            }
3787                                    }
3788    
3789                                    if (!matched) {
3790                                            iterator.remove();
3791    
3792                                            continue;
3793                                    }
3794                            }
3795    
3796                            // Filter by manual membership
3797    
3798                            if ((manualMembership != null) &&
3799                                    (manualMembership != group.isManualMembership())) {
3800    
3801                                    iterator.remove();
3802    
3803                                    continue;
3804                            }
3805    
3806                            // Filter by membership restriction
3807    
3808                            if ((membershipRestriction != null) &&
3809                                    (membershipRestriction != group.getMembershipRestriction())) {
3810    
3811                                    iterator.remove();
3812    
3813                                    continue;
3814                            }
3815    
3816                            // Filter by site
3817    
3818                            if (site != null) {
3819                                    if (site != group.isSite()) {
3820                                            iterator.remove();
3821    
3822                                            continue;
3823                                    }
3824                            }
3825    
3826                            // Filter by type and types
3827    
3828                            int type = group.getType();
3829    
3830                            if (type == 4) {
3831                                    iterator.remove();
3832    
3833                                    continue;
3834                            }
3835    
3836                            if ((types != null) && !types.contains(type)) {
3837                                    iterator.remove();
3838    
3839                                    continue;
3840                            }
3841                    }
3842    
3843                    // Join by role permissions
3844    
3845                    RolePermissions rolePermissions = (RolePermissions)params.remove(
3846                            "rolePermissions");
3847    
3848                    if (rolePermissions != null) {
3849                            ResourceAction resourceAction =
3850                                    resourceActionLocalService.fetchResourceAction(
3851                                            rolePermissions.getName(), rolePermissions.getActionId());
3852    
3853                            if (resourceAction != null) {
3854                                    Set<Group> rolePermissionsGroups = new HashSet<>();
3855    
3856                                    if (resourceBlockLocalService.isSupported(
3857                                                    rolePermissions.getName())) {
3858    
3859                                            List<ResourceTypePermission> resourceTypePermissions =
3860                                                    resourceTypePermissionPersistence.findByRoleId(
3861                                                            rolePermissions.getRoleId());
3862    
3863                                            for (ResourceTypePermission resourceTypePermission :
3864                                                            resourceTypePermissions) {
3865    
3866                                                    if ((resourceTypePermission.getCompanyId() ==
3867                                                                    companyId) &&
3868                                                            Validator.equals(
3869                                                                    rolePermissions.getName(),
3870                                                                    resourceTypePermission.getName()) &&
3871                                                            resourceTypePermission.hasAction(resourceAction)) {
3872    
3873                                                            Group group = groupPersistence.fetchByPrimaryKey(
3874                                                                    resourceTypePermission.getGroupId());
3875    
3876                                                            if (group != null) {
3877                                                                    rolePermissionsGroups.add(group);
3878                                                            }
3879                                                    }
3880                                            }
3881                                    }
3882                                    else {
3883                                            List<ResourcePermission> resourcePermissions =
3884                                                    resourcePermissionPersistence.findByC_N_S(
3885                                                            companyId, rolePermissions.getName(),
3886                                                            rolePermissions.getScope());
3887    
3888                                            for (ResourcePermission resourcePermission :
3889                                                            resourcePermissions) {
3890    
3891                                                    if ((resourcePermission.getRoleId() ==
3892                                                                    rolePermissions.getRoleId()) &&
3893                                                            resourcePermission.hasAction(
3894                                                                    resourceAction)) {
3895    
3896                                                            Group group = groupPersistence.fetchByPrimaryKey(
3897                                                                    GetterUtil.getLong(
3898                                                                            resourcePermission.getPrimKey()));
3899    
3900                                                            if (group != null) {
3901                                                                    rolePermissionsGroups.add(group);
3902                                                            }
3903                                                    }
3904                                            }
3905                                    }
3906    
3907                                    groups.retainAll(rolePermissionsGroups);
3908                            }
3909                    }
3910    
3911                    // Join by Groups_Roles
3912    
3913                    Long roleId = (Long)params.remove("groupsRoles");
3914    
3915                    if (roleId != null) {
3916                            groups.retainAll(rolePersistence.getGroups(roleId));
3917                    }
3918    
3919                    if (userId == null) {
3920                            return groups;
3921                    }
3922    
3923                    // Join by Users_Groups
3924    
3925                    Set<Group> joinedGroups = new HashSet<>(
3926                            userPersistence.getGroups(userId));
3927    
3928                    boolean inherit = GetterUtil.getBoolean(params.remove("inherit"), true);
3929    
3930                    if (inherit) {
3931    
3932                            // Join by Users_Orgs
3933    
3934                            long[] organizationIds = userPersistence.getOrganizationPrimaryKeys(
3935                                    userId);
3936    
3937                            for (long organizationId : organizationIds) {
3938                                    for (Group group : groups) {
3939                                            if (organizationId == group.getClassPK()) {
3940                                                    joinedGroups.add(group);
3941                                            }
3942                                    }
3943                            }
3944    
3945                            // Join by Groups_Orgs and Users_Orgs
3946    
3947                            for (long organizationId : organizationIds) {
3948                                    joinedGroups.addAll(
3949                                            organizationPersistence.getGroups(organizationId));
3950                            }
3951    
3952                            // Join by Groups_UserGroups and Users_UserGroups
3953    
3954                            long[] userGroupIds = userPersistence.getUserGroupPrimaryKeys(
3955                                    userId);
3956    
3957                            for (long userGroupId : userGroupIds) {
3958                                    joinedGroups.addAll(
3959                                            userGroupPersistence.getGroups(userGroupId));
3960                            }
3961                    }
3962    
3963                    if (_log.isDebugEnabled() && !params.isEmpty()) {
3964                            _log.debug("Unprocessed parameters " + MapUtil.toString(params));
3965                    }
3966    
3967                    if (joinedGroups.size() > groups.size()) {
3968                            groups.retainAll(joinedGroups);
3969    
3970                            return groups;
3971                    }
3972                    else {
3973                            joinedGroups.retainAll(groups);
3974    
3975                            return joinedGroups;
3976                    }
3977            }
3978    
3979            protected long[] getClassNameIds() {
3980                    if (_classNameIds == null) {
3981                            _classNameIds = new long[] {
3982                                    classNameLocalService.getClassNameId(Group.class),
3983                                    classNameLocalService.getClassNameId(Organization.class)
3984                            };
3985                    }
3986    
3987                    return _classNameIds;
3988            }
3989    
3990            protected String getFriendlyURL(
3991                            long companyId, long groupId, long classNameId, long classPK,
3992                            String friendlyName, String friendlyURL)
3993                    throws PortalException {
3994    
3995                    friendlyURL = getFriendlyURL(friendlyURL);
3996    
3997                    if (Validator.isNotNull(friendlyURL)) {
3998                            return friendlyURL;
3999                    }
4000    
4001                    friendlyURL = StringPool.SLASH + getFriendlyURL(friendlyName);
4002    
4003                    String originalFriendlyURL = friendlyURL;
4004    
4005                    for (int i = 1;; i++) {
4006                            try {
4007                                    validateFriendlyURL(
4008                                            companyId, groupId, classNameId, classPK, friendlyURL);
4009    
4010                                    break;
4011                            }
4012                            catch (GroupFriendlyURLException gfurle) {
4013                                    int type = gfurle.getType();
4014    
4015                                    if (type == GroupFriendlyURLException.DUPLICATE) {
4016                                            friendlyURL = originalFriendlyURL + i;
4017                                    }
4018                                    else {
4019                                            friendlyURL = StringPool.SLASH + classPK;
4020    
4021                                            break;
4022                                    }
4023                            }
4024                    }
4025    
4026                    return friendlyURL;
4027            }
4028    
4029            protected String getFriendlyURL(String friendlyURL) {
4030                    return FriendlyURLNormalizerUtil.normalize(friendlyURL);
4031            }
4032    
4033            protected String getOrgGroupName(String name) {
4034                    return name + ORGANIZATION_NAME_SUFFIX;
4035            }
4036    
4037            protected List<PortletDataHandler> getPortletDataHandlers(Group group) {
4038                    List<Portlet> portlets = portletLocalService.getPortlets(
4039                            group.getCompanyId());
4040    
4041                    List<PortletDataHandler> portletDataHandlers = new ArrayList<>(
4042                            portlets.size());
4043    
4044                    for (Portlet portlet : portlets) {
4045                            if (!portlet.isActive()) {
4046                                    continue;
4047                            }
4048    
4049                            PortletDataHandler portletDataHandler =
4050                                    portlet.getPortletDataHandlerInstance();
4051    
4052                            if ((portletDataHandler != null) &&
4053                                    !portletDataHandler.isDataPortalLevel()) {
4054    
4055                                    portletDataHandlers.add(portletDataHandler);
4056                            }
4057                    }
4058    
4059                    return portletDataHandlers;
4060            }
4061    
4062            protected String[] getSearchNames(long companyId, String name) {
4063                    if (Validator.isNull(name)) {
4064                            return new String[] {null};
4065                    }
4066    
4067                    Company company = companyPersistence.fetchByPrimaryKey(companyId);
4068    
4069                    if (company == null) {
4070                            return CustomSQLUtil.keywords(name);
4071                    }
4072    
4073                    Account account = accountPersistence.fetchByPrimaryKey(
4074                            company.getAccountId());
4075    
4076                    if (account == null) {
4077                            return CustomSQLUtil.keywords(name);
4078                    }
4079    
4080                    String companyName = account.getName();
4081    
4082                    if (StringUtil.wildcardMatches(
4083                                    companyName, name, CharPool.UNDERLINE, CharPool.PERCENT,
4084                                    CharPool.BACK_SLASH, false)) {
4085    
4086                            String[] searchNames = CustomSQLUtil.keywords(name);
4087    
4088                            String guestName = StringUtil.quote(
4089                                    StringUtil.toLowerCase(GroupConstants.GUEST),
4090                                    StringPool.PERCENT);
4091    
4092                            return ArrayUtil.append(searchNames, guestName);
4093                    }
4094    
4095                    return CustomSQLUtil.keywords(name);
4096            }
4097    
4098            protected void initImportLARFile() {
4099                    String publicLARFileName = PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUTS_LAR;
4100    
4101                    if (_log.isDebugEnabled()) {
4102                            _log.debug("Reading public LAR file " + publicLARFileName);
4103                    }
4104    
4105                    if (Validator.isNotNull(publicLARFileName)) {
4106                            publicLARFile = new File(publicLARFileName);
4107    
4108                            if (!publicLARFile.exists()) {
4109                                    _log.error(
4110                                            "Public LAR file " + publicLARFile + " does not exist");
4111    
4112                                    publicLARFile = null;
4113                            }
4114                            else {
4115                                    if (_log.isDebugEnabled()) {
4116                                            _log.debug("Using public LAR file " + publicLARFileName);
4117                                    }
4118                            }
4119                    }
4120            }
4121    
4122            protected void initUserPersonalSitePermissions(Group group)
4123                    throws PortalException {
4124    
4125                    // User role
4126    
4127                    Role role = roleLocalService.getRole(
4128                            group.getCompanyId(), RoleConstants.USER);
4129    
4130                    setRolePermissions(
4131                            group, role, Layout.class.getName(),
4132                            new String[] {ActionKeys.VIEW});
4133    
4134                    setRolePermissions(
4135                            group, role, "com.liferay.portlet.blogs",
4136                            new String[] {
4137                                    ActionKeys.ADD_ENTRY, ActionKeys.PERMISSIONS,
4138                                    ActionKeys.SUBSCRIBE
4139                            });
4140    
4141                    // Power User role
4142    
4143                    role = roleLocalService.getRole(
4144                            group.getCompanyId(), RoleConstants.POWER_USER);
4145    
4146                    List<Portlet> portlets = portletLocalService.getPortlets(
4147                            group.getCompanyId(), false, false);
4148    
4149                    for (Portlet portlet : portlets) {
4150                            List<String> actions =
4151                                    ResourceActionsUtil.getPortletResourceActions(
4152                                            portlet.getPortletId());
4153    
4154                            String controlPanelEntryCategory = GetterUtil.getString(
4155                                    portlet.getControlPanelEntryCategory());
4156    
4157                            if (actions.contains(ActionKeys.ACCESS_IN_CONTROL_PANEL) &&
4158                                    controlPanelEntryCategory.startsWith(
4159                                            PortletCategoryKeys.SITE_ADMINISTRATION)) {
4160    
4161                                    setRolePermissions(
4162                                            group, role, portlet.getPortletId(),
4163                                            new String[] {ActionKeys.ACCESS_IN_CONTROL_PANEL});
4164                            }
4165                    }
4166    
4167                    setRolePermissions(
4168                            group, role, Group.class.getName(),
4169                            new String[] {
4170                                    ActionKeys.MANAGE_LAYOUTS, ActionKeys.VIEW_SITE_ADMINISTRATION
4171                            });
4172    
4173                    setRolePermissions(group, role, "com.liferay.portlet.asset");
4174                    setRolePermissions(group, role, "com.liferay.portlet.blogs");
4175                    setRolePermissions(group, role, "com.liferay.portlet.bookmarks");
4176                    setRolePermissions(group, role, "com.liferay.portlet.documentlibrary");
4177                    setRolePermissions(group, role, "com.liferay.portlet.imagegallery");
4178                    setRolePermissions(group, role, "com.liferay.portlet.journal");
4179                    setRolePermissions(group, role, "com.liferay.portlet.messageboards");
4180                    setRolePermissions(group, role, "com.liferay.portlet.wiki");
4181            }
4182    
4183            protected boolean isParentGroup(long parentGroupId, long groupId)
4184                    throws PortalException {
4185    
4186                    // Return true if parentGroupId is among the parent groups of groupId
4187    
4188                    if (groupId == GroupConstants.DEFAULT_PARENT_GROUP_ID) {
4189                            return false;
4190                    }
4191    
4192                    Group group = groupPersistence.findByPrimaryKey(groupId);
4193    
4194                    String treePath = group.getTreePath();
4195    
4196                    if (treePath.contains(
4197                                    StringPool.SLASH + parentGroupId + StringPool.SLASH)) {
4198    
4199                            return true;
4200                    }
4201                    else {
4202                            return false;
4203                    }
4204            }
4205    
4206            protected boolean isStaging(ServiceContext serviceContext) {
4207                    if (serviceContext != null) {
4208                            return ParamUtil.getBoolean(serviceContext, "staging");
4209                    }
4210    
4211                    return false;
4212            }
4213    
4214            protected boolean isUseComplexSQL(long[] classNameIds) {
4215                    if (ArrayUtil.isEmpty(classNameIds)) {
4216                            return true;
4217                    }
4218    
4219                    if (_complexSQLClassNameIds == null) {
4220                            String[] complexSQLClassNames =
4221                                    PropsValues.GROUPS_COMPLEX_SQL_CLASS_NAMES;
4222    
4223                            long[] complexSQLClassNameIds =
4224                                    new long[complexSQLClassNames.length];
4225    
4226                            for (int i = 0; i < complexSQLClassNames.length; i++) {
4227                                    String complexSQLClassName = complexSQLClassNames[i];
4228    
4229                                    complexSQLClassNameIds[i] =
4230                                            classNameLocalService.getClassNameId(complexSQLClassName);
4231                            }
4232    
4233                            _complexSQLClassNameIds = complexSQLClassNameIds;
4234                    }
4235    
4236                    for (long classNameId : classNameIds) {
4237                            if (ArrayUtil.contains(_complexSQLClassNameIds, classNameId)) {
4238                                    return true;
4239                            }
4240                    }
4241    
4242                    return false;
4243            }
4244    
4245            protected boolean matches(String s, String[] keywords) {
4246                    if ((keywords == null) ||
4247                            ((keywords.length == 1) && (keywords[0] == null))) {
4248    
4249                            return true;
4250                    }
4251    
4252                    for (String keyword : keywords) {
4253                            if (StringUtil.wildcardMatches(
4254                                            s, keyword, CharPool.UNDERLINE, CharPool.PERCENT,
4255                                            CharPool.BACK_SLASH, false)) {
4256    
4257                                    return true;
4258                            }
4259                    }
4260    
4261                    return false;
4262            }
4263    
4264            protected void setCompanyPermissions(
4265                            Role role, String name, String[] actionIds)
4266                    throws PortalException {
4267    
4268                    if (resourceBlockLocalService.isSupported(name)) {
4269                            resourceBlockLocalService.setCompanyScopePermissions(
4270                                    role.getCompanyId(), name, role.getRoleId(),
4271                                    Arrays.asList(actionIds));
4272                    }
4273                    else {
4274                            resourcePermissionLocalService.setResourcePermissions(
4275                                    role.getCompanyId(), name, ResourceConstants.SCOPE_COMPANY,
4276                                    String.valueOf(role.getCompanyId()), role.getRoleId(),
4277                                    actionIds);
4278                    }
4279            }
4280    
4281            protected void setRolePermissions(Group group, Role role, String name)
4282                    throws PortalException {
4283    
4284                    List<String> actions = ResourceActionsUtil.getModelResourceActions(
4285                            name);
4286    
4287                    setRolePermissions(
4288                            group, role, name, actions.toArray(new String[actions.size()]));
4289            }
4290    
4291            protected void setRolePermissions(
4292                            Group group, Role role, String name, String[] actionIds)
4293                    throws PortalException {
4294    
4295                    if (resourceBlockLocalService.isSupported(name)) {
4296                            resourceBlockLocalService.setGroupScopePermissions(
4297                                    role.getCompanyId(), group.getGroupId(), name, role.getRoleId(),
4298                                    Arrays.asList(actionIds));
4299                    }
4300                    else {
4301                            resourcePermissionLocalService.setResourcePermissions(
4302                                    group.getCompanyId(), name, ResourceConstants.SCOPE_GROUP,
4303                                    String.valueOf(group.getGroupId()), role.getRoleId(),
4304                                    actionIds);
4305                    }
4306            }
4307    
4308            protected List<Group> sort(
4309                    Collection<Group> groups, int start, int end,
4310                    OrderByComparator<Group> obc) {
4311    
4312                    if (obc == null) {
4313                            obc = new GroupNameComparator(true);
4314                    }
4315    
4316                    List<Group> groupList = null;
4317    
4318                    if (groups instanceof List) {
4319                            groupList = (List<Group>)groups;
4320                    }
4321                    else {
4322                            groupList = new ArrayList<>(groups);
4323                    }
4324    
4325                    Collections.sort(groupList, obc);
4326    
4327                    return Collections.unmodifiableList(
4328                            ListUtil.subList(groupList, start, end));
4329            }
4330    
4331            protected void unscheduleStaging(Group group) {
4332                    try {
4333    
4334                            // Remote publishing
4335    
4336                            String groupName = StagingUtil.getSchedulerGroupName(
4337                                    DestinationNames.LAYOUTS_REMOTE_PUBLISHER, group.getGroupId());
4338    
4339                            SchedulerEngineHelperUtil.delete(groupName, StorageType.PERSISTED);
4340    
4341                            long liveGroupId = 0;
4342                            long stagingGroupId = 0;
4343    
4344                            if (group.isStagingGroup()) {
4345                                    liveGroupId = group.getLiveGroupId();
4346    
4347                                    stagingGroupId = group.getGroupId();
4348                            }
4349                            else if (group.hasStagingGroup()) {
4350                                    liveGroupId = group.getGroupId();
4351    
4352                                    stagingGroupId = group.getStagingGroup().getGroupId();
4353                            }
4354    
4355                            if ((liveGroupId != 0) && (stagingGroupId != 0)) {
4356    
4357                                    // Publish to live
4358    
4359                                    groupName = StagingUtil.getSchedulerGroupName(
4360                                            DestinationNames.LAYOUTS_LOCAL_PUBLISHER, liveGroupId);
4361    
4362                                    SchedulerEngineHelperUtil.delete(
4363                                            groupName, StorageType.PERSISTED);
4364    
4365                                    // Copy from live
4366    
4367                                    groupName = StagingUtil.getSchedulerGroupName(
4368                                            DestinationNames.LAYOUTS_LOCAL_PUBLISHER, stagingGroupId);
4369    
4370                                    SchedulerEngineHelperUtil.delete(
4371                                            groupName, StorageType.PERSISTED);
4372                            }
4373                    }
4374                    catch (Exception e) {
4375                            _log.error(
4376                                    "Unable to unschedule events for group: " + group.getGroupId());
4377                    }
4378            }
4379    
4380            protected void validateFriendlyURL(
4381                            long companyId, long groupId, long classNameId, long classPK,
4382                            String friendlyURL)
4383                    throws PortalException {
4384    
4385                    Company company = companyPersistence.findByPrimaryKey(companyId);
4386    
4387                    if (company.isSystem()) {
4388                            return;
4389                    }
4390    
4391                    if (Validator.isNull(friendlyURL)) {
4392                            return;
4393                    }
4394    
4395                    int exceptionType = LayoutImpl.validateFriendlyURL(friendlyURL);
4396    
4397                    if (exceptionType != -1) {
4398                            throw new GroupFriendlyURLException(exceptionType);
4399                    }
4400    
4401                    Group group = groupPersistence.fetchByC_F(companyId, friendlyURL);
4402    
4403                    if ((group != null) && (group.getGroupId() != groupId)) {
4404                            GroupFriendlyURLException gfurle = new GroupFriendlyURLException(
4405                                    GroupFriendlyURLException.DUPLICATE);
4406    
4407                            gfurle.setDuplicateClassPK(group.getGroupId());
4408                            gfurle.setDuplicateClassName(Group.class.getName());
4409    
4410                            throw gfurle;
4411                    }
4412    
4413                    String groupIdFriendlyURL = friendlyURL.substring(1);
4414    
4415                    if (Validator.isNumber(groupIdFriendlyURL)) {
4416                            long groupClassNameId = classNameLocalService.getClassNameId(
4417                                    Group.class);
4418    
4419                            if (((classNameId != groupClassNameId) &&
4420                                     !groupIdFriendlyURL.equals(String.valueOf(classPK)) &&
4421                                     !PropsValues.USERS_SCREEN_NAME_ALLOW_NUMERIC) ||
4422                                    ((classNameId == groupClassNameId) &&
4423                                     !groupIdFriendlyURL.equals(String.valueOf(groupId)))) {
4424    
4425                                    GroupFriendlyURLException gfurle =
4426                                            new GroupFriendlyURLException(
4427                                                    GroupFriendlyURLException.POSSIBLE_DUPLICATE);
4428    
4429                                    gfurle.setKeywordConflict(groupIdFriendlyURL);
4430    
4431                                    throw gfurle;
4432                            }
4433                    }
4434    
4435                    String screenName = friendlyURL.substring(1);
4436    
4437                    User user = userPersistence.fetchByC_SN(companyId, screenName);
4438    
4439                    if (user != null) {
4440                            long userClassNameId = classNameLocalService.getClassNameId(
4441                                    User.class);
4442    
4443                            if ((classNameId == userClassNameId) &&
4444                                    (classPK == user.getUserId())) {
4445                            }
4446                            else {
4447                                    GroupFriendlyURLException gfurle =
4448                                            new GroupFriendlyURLException(
4449                                                    GroupFriendlyURLException.DUPLICATE);
4450    
4451                                    gfurle.setDuplicateClassPK(user.getUserId());
4452                                    gfurle.setDuplicateClassName(User.class.getName());
4453    
4454                                    throw gfurle;
4455                            }
4456                    }
4457    
4458                    if (StringUtil.count(friendlyURL, StringPool.SLASH) > 1) {
4459                            throw new GroupFriendlyURLException(
4460                                    GroupFriendlyURLException.TOO_DEEP);
4461                    }
4462            }
4463    
4464            protected void validateGroupKey(
4465                            long groupId, long companyId, String groupKey, boolean site)
4466                    throws PortalException {
4467    
4468                    if (Validator.isNull(groupKey) || Validator.isNumber(groupKey) ||
4469                            groupKey.contains(StringPool.STAR) ||
4470                            groupKey.contains(ORGANIZATION_NAME_SUFFIX)) {
4471    
4472                            throw new GroupKeyException();
4473                    }
4474    
4475                    try {
4476                            Group group = groupFinder.findByC_GK(companyId, groupKey);
4477    
4478                            if ((groupId <= 0) || (group.getGroupId() != groupId)) {
4479                                    throw new DuplicateGroupException("{groupId=" + groupId + "}");
4480                            }
4481                    }
4482                    catch (NoSuchGroupException nsge) {
4483                    }
4484    
4485                    if (site) {
4486                            Company company = companyLocalService.getCompany(companyId);
4487    
4488                            if (groupKey.equals(company.getName())) {
4489                                    throw new DuplicateGroupException();
4490                            }
4491                    }
4492            }
4493    
4494            protected void validateInheritContent(
4495                            long parentGroupId, boolean inheritContent)
4496                    throws GroupInheritContentException {
4497    
4498                    if (!inheritContent) {
4499                            return;
4500                    }
4501    
4502                    if (parentGroupId == GroupConstants.DEFAULT_PARENT_GROUP_ID) {
4503                            throw new GroupInheritContentException();
4504                    }
4505    
4506                    Group parentGroup = groupPersistence.fetchByPrimaryKey(parentGroupId);
4507    
4508                    if (parentGroup.isInheritContent()) {
4509                            throw new GroupInheritContentException();
4510                    }
4511            }
4512    
4513            protected void validateLanguageIds(
4514                            String defaultLanguageId, String languageIds)
4515                    throws PortalException {
4516    
4517                    String[] languageIdsArray = StringUtil.split(languageIds);
4518    
4519                    for (String languageId : languageIdsArray) {
4520                            if (!LanguageUtil.isAvailableLocale(
4521                                            LocaleUtil.fromLanguageId(languageId))) {
4522    
4523                                    LocaleException le = new LocaleException(
4524                                            LocaleException.TYPE_DISPLAY_SETTINGS);
4525    
4526                                    le.setSourceAvailableLocales(
4527                                            LanguageUtil.getAvailableLocales());
4528                                    le.setTargetAvailableLocales(
4529                                            Arrays.asList(
4530                                                    LocaleUtil.fromLanguageIds(languageIdsArray)));
4531    
4532                                    throw le;
4533                            }
4534                    }
4535    
4536                    if (!ArrayUtil.contains(languageIdsArray, defaultLanguageId)) {
4537                            LocaleException le = new LocaleException(
4538                                    LocaleException.TYPE_DEFAULT);
4539    
4540                            le.setSourceAvailableLocales(LanguageUtil.getAvailableLocales());
4541                            le.setTargetAvailableLocales(
4542                                    Arrays.asList(LocaleUtil.fromLanguageIds(languageIdsArray)));
4543    
4544                            throw le;
4545                    }
4546            }
4547    
4548            protected void validateParentGroup(long groupId, long parentGroupId)
4549                    throws PortalException {
4550    
4551                    if (parentGroupId == GroupConstants.DEFAULT_PARENT_GROUP_ID) {
4552                            return;
4553                    }
4554    
4555                    if (groupId == parentGroupId) {
4556                            throw new GroupParentException.MustNotBeOwnParent(groupId);
4557                    }
4558    
4559                    Group group = groupPersistence.fetchByPrimaryKey(groupId);
4560    
4561                    if (group == null) {
4562                            return;
4563                    }
4564    
4565                    if ((groupId > 0) &&
4566                            (parentGroupId != GroupConstants.DEFAULT_PARENT_GROUP_ID)) {
4567    
4568                            // Prevent circular groupal references
4569    
4570                            if (isParentGroup(groupId, parentGroupId)) {
4571                                    throw new GroupParentException.MustNotHaveChildParent(
4572                                            groupId, parentGroupId);
4573                            }
4574                    }
4575    
4576                    Group parentGroup = groupPersistence.findByPrimaryKey(parentGroupId);
4577    
4578                    if (group.isStagingGroup()) {
4579                            long stagingGroupId = parentGroup.getStagingGroup().getGroupId();
4580    
4581                            if (groupId == stagingGroupId) {
4582                                    throw new GroupParentException.MustNotHaveStagingParent(
4583                                            groupId, stagingGroupId);
4584                            }
4585                    }
4586            }
4587    
4588            protected File publicLARFile;
4589    
4590            private static final Log _log = LogFactoryUtil.getLog(
4591                    GroupLocalServiceImpl.class);
4592    
4593            private volatile long[] _classNameIds;
4594            private volatile long[] _complexSQLClassNameIds;
4595            private final Map<String, Group> _systemGroupsMap = new HashMap<>();
4596    
4597    }