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