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