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