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