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