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