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