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