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