001    /**
002     * Copyright (c) 2000-2012 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.NoSuchGroupException;
021    import com.liferay.portal.NoSuchLayoutSetException;
022    import com.liferay.portal.NoSuchUserException;
023    import com.liferay.portal.RequiredGroupException;
024    import com.liferay.portal.kernel.cache.ThreadLocalCachable;
025    import com.liferay.portal.kernel.dao.orm.QueryUtil;
026    import com.liferay.portal.kernel.exception.PortalException;
027    import com.liferay.portal.kernel.exception.SystemException;
028    import com.liferay.portal.kernel.language.LanguageUtil;
029    import com.liferay.portal.kernel.lar.PortletDataContext;
030    import com.liferay.portal.kernel.lar.PortletDataHandler;
031    import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
032    import com.liferay.portal.kernel.log.Log;
033    import com.liferay.portal.kernel.log.LogFactoryUtil;
034    import com.liferay.portal.kernel.messaging.DestinationNames;
035    import com.liferay.portal.kernel.scheduler.SchedulerEngineHelperUtil;
036    import com.liferay.portal.kernel.scheduler.StorageType;
037    import com.liferay.portal.kernel.spring.aop.Skip;
038    import com.liferay.portal.kernel.staging.StagingUtil;
039    import com.liferay.portal.kernel.transaction.Propagation;
040    import com.liferay.portal.kernel.transaction.Transactional;
041    import com.liferay.portal.kernel.util.FileUtil;
042    import com.liferay.portal.kernel.util.FriendlyURLNormalizerUtil;
043    import com.liferay.portal.kernel.util.GetterUtil;
044    import com.liferay.portal.kernel.util.OrderByComparator;
045    import com.liferay.portal.kernel.util.ParamUtil;
046    import com.liferay.portal.kernel.util.PropsKeys;
047    import com.liferay.portal.kernel.util.StringPool;
048    import com.liferay.portal.kernel.util.StringUtil;
049    import com.liferay.portal.kernel.util.UniqueList;
050    import com.liferay.portal.kernel.util.Validator;
051    import com.liferay.portal.lar.PortletDataContextImpl;
052    import com.liferay.portal.model.Account;
053    import com.liferay.portal.model.Company;
054    import com.liferay.portal.model.Group;
055    import com.liferay.portal.model.GroupConstants;
056    import com.liferay.portal.model.Layout;
057    import com.liferay.portal.model.LayoutConstants;
058    import com.liferay.portal.model.LayoutPrototype;
059    import com.liferay.portal.model.LayoutSet;
060    import com.liferay.portal.model.LayoutSetPrototype;
061    import com.liferay.portal.model.LayoutTypePortlet;
062    import com.liferay.portal.model.Organization;
063    import com.liferay.portal.model.Portlet;
064    import com.liferay.portal.model.ResourceConstants;
065    import com.liferay.portal.model.ResourcePermission;
066    import com.liferay.portal.model.Role;
067    import com.liferay.portal.model.RoleConstants;
068    import com.liferay.portal.model.User;
069    import com.liferay.portal.model.UserGroup;
070    import com.liferay.portal.model.UserPersonalSite;
071    import com.liferay.portal.model.impl.LayoutImpl;
072    import com.liferay.portal.security.permission.ActionKeys;
073    import com.liferay.portal.security.permission.PermissionCacheUtil;
074    import com.liferay.portal.security.permission.ResourceActionsUtil;
075    import com.liferay.portal.service.ServiceContext;
076    import com.liferay.portal.service.base.GroupLocalServiceBaseImpl;
077    import com.liferay.portal.theme.ThemeLoader;
078    import com.liferay.portal.theme.ThemeLoaderFactory;
079    import com.liferay.portal.util.PortalUtil;
080    import com.liferay.portal.util.PortletCategoryKeys;
081    import com.liferay.portal.util.PortletKeys;
082    import com.liferay.portal.util.PropsUtil;
083    import com.liferay.portal.util.PropsValues;
084    import com.liferay.portal.util.comparator.GroupNameComparator;
085    import com.liferay.portlet.blogs.model.BlogsEntry;
086    import com.liferay.portlet.journal.model.JournalArticle;
087    
088    import java.io.File;
089    
090    import java.util.ArrayList;
091    import java.util.Arrays;
092    import java.util.HashMap;
093    import java.util.HashSet;
094    import java.util.LinkedHashMap;
095    import java.util.List;
096    import java.util.Locale;
097    import java.util.Map;
098    
099    /**
100     * The group local service is responsible for accessing, creating, modifying and
101     * deleting groups.
102     *
103     * <p>
104     * Groups are mostly used in Liferay as a resource container for permissioning
105     * and content scoping purposes as described in {@link
106     * com.liferay.portal.model.impl.GroupImpl}.
107     * </p>
108     *
109     * <p>
110     * Groups are also the entity to which LayoutSets are generally associated.
111     * Since LayoutSets are the parent entities of Layouts (i.e. pages), no entity
112     * can have associated pages without also having an associated Group. This
113     * relationship can be depicted as ... Layout -> LayoutSet -> Group[type] [->
114     * Entity]. Note, the Entity part is optional.
115     * </p>
116     *
117     * <p>
118     * Group has a "type" definition that is typically identified by two fields of
119     * the entity - <code>String className</code>, and <code>int type </code>.
120     * </p>
121     *
122     * <p>
123     * The <code>className</code> field helps create the group's association with
124     * other entities (e.g. Organization, User, Company, UserGroup, ... etc.). The
125     * value of <code>className</code> is the full name of the entity's class and
126     * the primary key of the associated entity instance. A site has
127     * <code>className="Group"</code> and has no associated entity.
128     * </p>
129     *
130     * <p>
131     * The <code>type</code> field helps distinguish between a group used strictly
132     * for scoping and a group that also has pages (in which case the type is
133     * <code>SITE</code>). For a list of types, see {@link
134     * com.liferay.portal.model.GroupConstants}.
135     * </p>
136     *
137     * <p>
138     * Here is a listing of how Group is related to some portal entities ...
139     * </p>
140     *
141     * <ul>
142     * <li>
143     * Site is a Group with <code>className="Group"</code>
144     * </li>
145     * <li>
146     * Company has 1 Group (this is the global scope, but never has pages)
147     * </li>
148     * <li>
149     * User has 1 Group (pages are optional based on the behavior configuration for
150     * personal pages)
151     * </li>
152     * <li>
153     * Layout Template (<code>LayoutPrototype</code>) has 1 Group which uses only 1
154     * of it's 2 LayoutSets to store a single page which can later be used to
155     * derive a single page in any Site
156     * </li>
157     * <li>
158     * Site Template (<code>LayoutSetPrototype</code>) has 1 Group which uses only
159     * 1 of it's 2 LayoutSets to store many pages which can later be used to derive
160     * entire Sites or pulled into an existing Site
161     * </li>
162     * <li>
163     * Organization has 1 Group, but can also be associated to a Site at any point
164     * in it's life cycle in order to support having pages
165     * </li>
166     * <li>
167     * UserGroup has 1 Group that can have pages in both of the group's LayoutSets
168     * which are later inherited by users assigned to the UserGroup
169     * </li>
170     * </ul>
171     *
172     * @author Brian Wing Shun Chan
173     * @author Alexander Chow
174     * @author Bruno Farache
175     * @author Wesley Gong
176     */
177    public class GroupLocalServiceImpl extends GroupLocalServiceBaseImpl {
178    
179            public static final String ORGANIZATION_NAME_SUFFIX = " LFR_ORGANIZATION";
180    
181            /**
182             * Constructs a group local service.
183             */
184            public GroupLocalServiceImpl() {
185                    initImportLARFile();
186            }
187    
188            /**
189             * Adds a group.
190             *
191             * @param  userId the primary key of the group's creator/owner
192             * @param  parentGroupId the primary key of the parent group
193             * @param  className the entity's class name
194             * @param  classPK the primary key of the entity's instance
195             * @param  liveGroupId the primary key of the live group
196             * @param  name the entity's name
197             * @param  description the group's description (optionally
198             *         <code>null</code>)
199             * @param  type the group's type. For more information see {@link
200             *         com.liferay.portal.model.GroupConstants}
201             * @param  friendlyURL the group's friendlyURL (optionally
202             *         <code>null</code>)
203             * @param  site whether the group is to be associated with a main site
204             * @param  active whether the group is active
205             * @param  serviceContext the service context to be applied (optionally
206             *         <code>null</code>). Can set asset category IDs and asset tag
207             *         names for the group, and whether the group is for staging.
208             * @return the group
209             * @throws PortalException if a creator could not be found, if the group's
210             *         information was invalid, if a layout could not be found, or if a
211             *         valid friendly URL could not be created for the group
212             * @throws SystemException if a system exception occurred
213             */
214            public Group addGroup(
215                            long userId, long parentGroupId, String className, long classPK,
216                            long liveGroupId, String name, String description, int type,
217                            String friendlyURL, boolean site, boolean active,
218                            ServiceContext serviceContext)
219                    throws PortalException, SystemException {
220    
221                    // Group
222    
223                    User user = userPersistence.findByPrimaryKey(userId);
224                    className = GetterUtil.getString(className);
225                    long classNameId = PortalUtil.getClassNameId(className);
226                    String friendlyName = name;
227    
228                    long groupId = 0;
229    
230                    while (true) {
231                            groupId = counterLocalService.increment();
232    
233                            User screenNameUser = userPersistence.fetchByC_SN(
234                                    user.getCompanyId(), String.valueOf(groupId));
235    
236                            if (screenNameUser == null) {
237                                    break;
238                            }
239                    }
240    
241                    boolean staging = isStaging(serviceContext);
242    
243                    long groupClassNameId = PortalUtil.getClassNameId(Group.class);
244    
245                    if ((classNameId <= 0) || className.equals(Group.class.getName())) {
246                            className = Group.class.getName();
247                            classNameId = groupClassNameId;
248                            classPK = groupId;
249                    }
250                    else if (className.equals(Organization.class.getName())) {
251                            name = getOrgGroupName(name);
252                    }
253                    else if (!GroupConstants.USER_PERSONAL_SITE.equals(name)) {
254                            name = String.valueOf(classPK);
255                    }
256    
257                    if (className.equals(Organization.class.getName()) && staging) {
258                            classPK = liveGroupId;
259                    }
260    
261                    if (className.equals(Layout.class.getName())) {
262                            Layout layout = layoutLocalService.getLayout(classPK);
263    
264                            parentGroupId = layout.getGroupId();
265                    }
266    
267                    friendlyURL = getFriendlyURL(
268                            user.getCompanyId(), groupId, classNameId, classPK, friendlyName,
269                            friendlyURL);
270    
271                    if (staging) {
272                            name = name.concat(" (Staging)");
273                            friendlyURL = friendlyURL.concat("-staging");
274                    }
275    
276                    if (className.equals(Group.class.getName())) {
277                            if (!site && (liveGroupId == 0) &&
278                                    !name.equals(GroupConstants.CONTROL_PANEL)) {
279    
280                                    throw new IllegalArgumentException();
281                            }
282                    }
283                    else if (!className.equals(Organization.class.getName()) &&
284                                     className.startsWith("com.liferay.portal.model.")) {
285    
286                            if (site) {
287                                    throw new IllegalArgumentException();
288                            }
289                    }
290    
291                    if ((classNameId <= 0) || className.equals(Group.class.getName())) {
292                            validateName(groupId, user.getCompanyId(), name, site);
293                    }
294    
295                    validateFriendlyURL(
296                            user.getCompanyId(), groupId, classNameId, classPK, friendlyURL);
297    
298                    Group group = groupPersistence.create(groupId);
299    
300                    group.setCompanyId(user.getCompanyId());
301                    group.setCreatorUserId(userId);
302                    group.setClassNameId(classNameId);
303                    group.setClassPK(classPK);
304                    group.setParentGroupId(parentGroupId);
305                    group.setLiveGroupId(liveGroupId);
306                    group.setName(name);
307                    group.setDescription(description);
308                    group.setType(type);
309                    group.setFriendlyURL(friendlyURL);
310                    group.setSite(site);
311                    group.setActive(active);
312    
313                    if ((serviceContext != null) && (classNameId == groupClassNameId) &&
314                            !user.isDefaultUser()) {
315    
316                            group.setExpandoBridgeAttributes(serviceContext);
317                    }
318    
319                    groupPersistence.update(group);
320    
321                    // Layout sets
322    
323                    layoutSetLocalService.addLayoutSet(groupId, true);
324    
325                    layoutSetLocalService.addLayoutSet(groupId, false);
326    
327                    if ((classNameId == groupClassNameId) && !user.isDefaultUser()) {
328    
329                            // Resources
330    
331                            resourceLocalService.addResources(
332                                    group.getCompanyId(), 0, 0, Group.class.getName(),
333                                    group.getGroupId(), false, false, false);
334    
335                            // Site roles
336    
337                            Role role = roleLocalService.getRole(
338                                    group.getCompanyId(), RoleConstants.SITE_OWNER);
339    
340                            userGroupRoleLocalService.addUserGroupRoles(
341                                    userId, groupId, new long[] {role.getRoleId()});
342    
343                            // User
344    
345                            userLocalService.addGroupUsers(
346                                    group.getGroupId(), new long[] {userId});
347    
348                            // Asset
349    
350                            if (serviceContext != null) {
351                                    updateAsset(
352                                            userId, group, serviceContext.getAssetCategoryIds(),
353                                            serviceContext.getAssetTagNames());
354                            }
355                    }
356                    else if (className.equals(Organization.class.getName()) &&
357                                     !user.isDefaultUser()) {
358    
359                            // Resources
360    
361                            resourceLocalService.addResources(
362                                    group.getCompanyId(), 0, 0, Group.class.getName(),
363                                    group.getGroupId(), false, false, false);
364                    }
365    
366                    return group;
367            }
368    
369            /**
370             * Adds the group using the default live group.
371             *
372             * @param      userId the primary key of the group's creator/owner
373             * @param      parentGroupId the primary key of the parent group
374             * @param      className the entity's class name
375             * @param      classPK the primary key of the entity's instance
376             * @param      name the entity's name
377             * @param      description the group's description (optionally
378             *             <code>null</code>)
379             * @param      type the group's type. For more information see {@link
380             *             com.liferay.portal.model.GroupConstants}
381             * @param      friendlyURL the group's friendlyURL
382             * @param      site whether the group is to be associated with a main site
383             * @param      active whether the group is active
384             * @param      serviceContext the service context to be applied (optionally
385             *             <code>null</code>). Can set asset category IDs and asset tag
386             *             names for the group, and whether the group is for staging.
387             * @return     the group
388             * @throws     PortalException if a creator could not be found, if the
389             *             group's information was invalid, if a layout could not be
390             *             found, or if a valid friendly URL could not be created for
391             *             the group
392             * @throws     SystemException if a system exception occurred
393             * @deprecated {@link #addGroup(long, long, String, long, long, String,
394             *             String, int, String, boolean, boolean, ServiceContext)}
395             */
396            public Group addGroup(
397                            long userId, long parentGroupId, String className, long classPK,
398                            String name, String description, int type, String friendlyURL,
399                            boolean site, boolean active, ServiceContext serviceContext)
400                    throws PortalException, SystemException {
401    
402                    return addGroup(
403                            userId, parentGroupId, className, classPK,
404                            GroupConstants.DEFAULT_LIVE_GROUP_ID, name, description, type,
405                            friendlyURL, site, active, serviceContext);
406            }
407    
408            /**
409             * Adds the groups to the role.
410             *
411             * @param  roleId the primary key of the role
412             * @param  groupIds the primary keys of the groups
413             * @throws SystemException if a system exception occurred
414             */
415            public void addRoleGroups(long roleId, long[] groupIds)
416                    throws SystemException {
417    
418                    rolePersistence.addGroups(roleId, groupIds);
419    
420                    PermissionCacheUtil.clearCache();
421            }
422    
423            /**
424             * Adds the user to the groups.
425             *
426             * @param  userId the primary key of the user
427             * @param  groupIds the primary keys of the groups
428             * @throws SystemException if a system exception occurred
429             */
430            public void addUserGroups(long userId, long[] groupIds)
431                    throws SystemException {
432    
433                    userPersistence.addGroups(userId, groupIds);
434    
435                    PermissionCacheUtil.clearCache();
436            }
437    
438            /**
439             * Adds a company group if it does not exist. This method is typically used
440             * when a virtual host is added.
441             *
442             * @param  companyId the primary key of the company
443             * @throws PortalException if a default user for the company could not be
444             *         found, if the group's information was invalid, if a layout could
445             *         not be found, or if a valid friendly URL could not be created for
446             *         the group
447             * @throws SystemException if a system exception occurred
448             */
449            @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
450            public void checkCompanyGroup(long companyId)
451                    throws PortalException, SystemException {
452    
453                    long classNameId = PortalUtil.getClassNameId(Company.class);
454    
455                    int count = groupPersistence.countByC_C_C(
456                            companyId, classNameId, companyId);
457    
458                    if (count == 0) {
459                            long defaultUserId = userLocalService.getDefaultUserId(companyId);
460    
461                            groupLocalService.addGroup(
462                                    defaultUserId, GroupConstants.DEFAULT_PARENT_GROUP_ID,
463                                    Company.class.getName(), companyId,
464                                    GroupConstants.DEFAULT_LIVE_GROUP_ID, GroupConstants.GLOBAL,
465                                    null, 0, GroupConstants.GLOBAL_FRIENDLY_URL, false, true, null);
466                    }
467            }
468    
469            /**
470             * Creates systems groups and other related data needed by the system on the
471             * very first startup. Also takes care of creating the Control Panel groups
472             * and layouts.
473             *
474             * @param  companyId the primary key of the company
475             * @throws PortalException if a new system group could not be created
476             * @throws SystemException if a system exception occurred
477             */
478            @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
479            public void checkSystemGroups(long companyId)
480                    throws PortalException, SystemException {
481    
482                    String companyIdHexString = StringUtil.toHexString(companyId);
483    
484                    for (Group group : groupFinder.findBySystem(companyId)) {
485                            _systemGroupsMap.put(
486                                    companyIdHexString.concat(group.getName()), group);
487                    }
488    
489                    long defaultUserId = userLocalService.getDefaultUserId(companyId);
490    
491                    String[] systemGroups = PortalUtil.getSystemGroups();
492    
493                    for (String name : systemGroups) {
494                            String groupCacheKey = companyIdHexString.concat(name);
495    
496                            Group group = _systemGroupsMap.get(groupCacheKey);
497    
498                            if (group == null) {
499                                    group = groupPersistence.fetchByC_N(companyId, name);
500                            }
501    
502                            if (group == null) {
503                                    String className = null;
504                                    long classPK = 0;
505                                    int type = GroupConstants.TYPE_SITE_OPEN;
506                                    String friendlyURL = null;
507                                    boolean site = true;
508    
509                                    if (name.equals(GroupConstants.CONTROL_PANEL)) {
510                                            type = GroupConstants.TYPE_SITE_PRIVATE;
511                                            friendlyURL = GroupConstants.CONTROL_PANEL_FRIENDLY_URL;
512                                            site = false;
513                                    }
514                                    else if (name.equals(GroupConstants.GUEST)) {
515                                            friendlyURL = "/guest";
516                                    }
517                                    else if (name.equals(GroupConstants.USER_PERSONAL_SITE)) {
518                                            className = UserPersonalSite.class.getName();
519                                            classPK = defaultUserId;
520                                            type = GroupConstants.TYPE_SITE_PRIVATE;
521                                            friendlyURL =
522                                                    GroupConstants.USER_PERSONAL_SITE_FRIENDLY_URL;
523                                            site = false;
524                                    }
525    
526                                    group = groupLocalService.addGroup(
527                                            defaultUserId, GroupConstants.DEFAULT_PARENT_GROUP_ID,
528                                            className, classPK, GroupConstants.DEFAULT_LIVE_GROUP_ID,
529                                            name, null, type, friendlyURL, site, true, null);
530    
531                                    if (name.equals(GroupConstants.USER_PERSONAL_SITE)) {
532                                            initUserPersonalSitePermissions(group);
533                                    }
534                            }
535    
536                            if (group.isControlPanel()) {
537                                    LayoutSet layoutSet = layoutSetLocalService.getLayoutSet(
538                                            group.getGroupId(), true);
539    
540                                    if (layoutSet.getPageCount() == 0) {
541                                            addControlPanelLayouts(group);
542                                    }
543                            }
544    
545                            if (group.getName().equals(GroupConstants.GUEST)) {
546                                    LayoutSet layoutSet = layoutSetLocalService.getLayoutSet(
547                                            group.getGroupId(), false);
548    
549                                    if (layoutSet.getPageCount() == 0) {
550                                            addDefaultGuestPublicLayouts(group);
551                                    }
552                            }
553    
554                            _systemGroupsMap.put(groupCacheKey, group);
555                    }
556            }
557    
558            /**
559             * Deletes the group and its associated data.
560             *
561             * <p>
562             * The group is unstaged and its assets and resources including layouts,
563             * membership requests, subscriptions, teams, blogs, bookmarks, calendar
564             * events, image gallery, journals, message boards, polls, shopping related
565             * entities, software catalog, and wikis are also deleted.
566             * </p>
567             *
568             * @param  group the group
569             * @return the deleted group
570             * @throws PortalException if the group was a system group, or if the user
571             *         did not have permission to delete the group or its assets or its
572             *         resources
573             * @throws SystemException if a system exception occurred
574             */
575            @Override
576            public Group deleteGroup(Group group)
577                    throws PortalException, SystemException {
578    
579                    if (PortalUtil.isSystemGroup(group.getName())) {
580                            throw new RequiredGroupException(
581                                    String.valueOf(group.getGroupId()),
582                                    RequiredGroupException.SYSTEM_GROUP);
583                    }
584    
585                    if (groupPersistence.countByC_P_S(
586                                    group.getCompanyId(), group.getGroupId(), true) > 0) {
587    
588                            throw new RequiredGroupException(
589                                    String.valueOf(group.getGroupId()),
590                                    RequiredGroupException.PARENT_GROUP);
591                    }
592    
593                    // Layout set branches
594    
595                    layoutSetBranchLocalService.deleteLayoutSetBranches(
596                            group.getGroupId(), true, true);
597    
598                    layoutSetBranchLocalService.deleteLayoutSetBranches(
599                            group.getGroupId(), false, true);
600    
601                    // Layout sets
602    
603                    ServiceContext serviceContext = new ServiceContext();
604    
605                    try {
606                            layoutSetLocalService.deleteLayoutSet(
607                                    group.getGroupId(), true, serviceContext);
608                    }
609                    catch (NoSuchLayoutSetException nslse) {
610                    }
611    
612                    try {
613                            layoutSetLocalService.deleteLayoutSet(
614                                    group.getGroupId(), false, serviceContext);
615                    }
616                    catch (NoSuchLayoutSetException nslse) {
617                    }
618    
619                    // Group roles
620    
621                    userGroupRoleLocalService.deleteUserGroupRolesByGroupId(
622                            group.getGroupId());
623    
624                    // User group roles
625    
626                    userGroupGroupRoleLocalService.deleteUserGroupGroupRolesByGroupId(
627                            group.getGroupId());
628    
629                    // Membership requests
630    
631                    membershipRequestLocalService.deleteMembershipRequests(
632                            group.getGroupId());
633    
634                    // Subscriptions
635    
636                    subscriptionLocalService.deleteSubscriptions(
637                            group.getCompanyId(), BlogsEntry.class.getName(),
638                            group.getGroupId());
639                    subscriptionLocalService.deleteSubscriptions(
640                            group.getCompanyId(), JournalArticle.class.getName(),
641                            group.getGroupId());
642    
643                    // Teams
644    
645                    teamLocalService.deleteTeams(group.getGroupId());
646    
647                    // Staging
648    
649                    unscheduleStaging(group);
650    
651                    if (group.hasStagingGroup()) {
652                            try {
653                                    StagingUtil.disableStaging(group, serviceContext);
654                            }
655                            catch (Exception e) {
656                                    _log.error(
657                                            "Unable to disable staging for group " +
658                                                    group.getGroupId());
659                            }
660                    }
661    
662                    // Themes
663    
664                    ThemeLoader themeLoader = ThemeLoaderFactory.getDefaultThemeLoader();
665    
666                    if (themeLoader != null) {
667                            String themePath =
668                                    themeLoader.getFileStorage() + StringPool.SLASH +
669                                            group.getGroupId();
670    
671                            FileUtil.deltree(themePath + "-private");
672                            FileUtil.deltree(themePath + "-public");
673                    }
674    
675                    // Portlet data
676    
677                    deletePortletData(group);
678    
679                    // Asset
680    
681                    if (group.isRegularSite()) {
682                            assetEntryLocalService.deleteEntry(
683                                    Group.class.getName(), group.getGroupId());
684                    }
685    
686                    assetVocabularyLocalService.deleteVocabularies(group.getGroupId());
687    
688                    // Shopping
689    
690                    shoppingCartLocalService.deleteGroupCarts(group.getGroupId());
691                    shoppingCategoryLocalService.deleteCategories(group.getGroupId());
692                    shoppingCouponLocalService.deleteCoupons(group.getGroupId());
693                    shoppingOrderLocalService.deleteOrders(group.getGroupId());
694    
695                    // Social
696    
697                    socialActivitySettingLocalService.deleteActivitySettings(
698                            group.getGroupId());
699    
700                    // Software catalog
701    
702                    scFrameworkVersionLocalService.deleteFrameworkVersions(
703                            group.getGroupId());
704                    scProductEntryLocalService.deleteProductEntries(group.getGroupId());
705    
706                    // Resources
707    
708                    List<ResourcePermission> resourcePermissions =
709                            resourcePermissionPersistence.findByC_P(
710                                    group.getCompanyId(), String.valueOf(group.getGroupId()));
711    
712                    for (ResourcePermission resourcePermission : resourcePermissions) {
713                            resourcePermissionLocalService.deleteResourcePermission(
714                                    resourcePermission);
715                    }
716    
717                    if (!group.isStagingGroup() &&
718                            (group.isOrganization() || group.isRegularSite())) {
719    
720                            resourceLocalService.deleteResource(
721                                    group.getCompanyId(), Group.class.getName(),
722                                    ResourceConstants.SCOPE_INDIVIDUAL, group.getGroupId());
723                    }
724    
725                    // Group
726    
727                    if (!group.isStagingGroup() && group.isOrganization() &&
728                            group.isSite()) {
729    
730                            group.setSite(false);
731    
732                            groupPersistence.update(group);
733                    }
734                    else {
735                            groupPersistence.remove(group);
736                    }
737    
738                    // Permission cache
739    
740                    PermissionCacheUtil.clearCache();
741    
742                    return group;
743            }
744    
745            /**
746             * Deletes the group and its associated data.
747             *
748             * <p>
749             * The group is unstaged and its assets and resources including layouts,
750             * membership requests, subscriptions, teams, blogs, bookmarks, calendar
751             * events, image gallery, journals, message boards, polls, shopping related
752             * entities, software catalog, and wikis are also deleted.
753             * </p>
754             *
755             * @param  groupId the primary key of the group
756             * @return the deleted group
757             * @throws PortalException if a group with the primary key could not be
758             *         found, if the group was a system group, or if the user did not
759             *         have permission to delete the group, its assets, or its resources
760             * @throws SystemException if a system exception occurred
761             */
762            @Override
763            public Group deleteGroup(long groupId)
764                    throws PortalException, SystemException {
765    
766                    Group group = groupPersistence.findByPrimaryKey(groupId);
767    
768                    return deleteGroup(group);
769            }
770    
771            /**
772             * Returns the group with the matching friendly URL.
773             *
774             * @param  companyId the primary key of the company
775             * @param  friendlyURL the friendly URL
776             * @return the group with the friendly URL, or <code>null</code> if a
777             *         matching group could not be found
778             * @throws SystemException if a system exception occurred
779             */
780            public Group fetchFriendlyURLGroup(long companyId, String friendlyURL)
781                    throws SystemException {
782    
783                    if (Validator.isNull(friendlyURL)) {
784                            return null;
785                    }
786    
787                    friendlyURL = getFriendlyURL(friendlyURL);
788    
789                    return groupPersistence.fetchByC_F(companyId, friendlyURL);
790            }
791    
792            /**
793             * Returns the group with the matching group name by first searching the
794             * system groups and then using the finder cache.
795             *
796             * @param  companyId the primary key of the company
797             * @param  name the group's name
798             * @return the group with the name and associated company, or
799             *         <code>null</code> if a matching group could not be found
800             * @throws SystemException if a system exception occurred
801             */
802            @Skip
803            public Group fetchGroup(long companyId, String name)
804                    throws SystemException {
805    
806                    Group group = _systemGroupsMap.get(
807                            StringUtil.toHexString(companyId).concat(name));
808    
809                    if (group != null) {
810                            return group;
811                    }
812    
813                    return groupLocalService.loadFetchGroup(companyId, name);
814            }
815    
816            /**
817             * Returns the company group.
818             *
819             * @param  companyId the primary key of the company
820             * @return the group associated with the company
821             * @throws PortalException if a matching group could not be found
822             * @throws SystemException if a system exception occurred
823             */
824            public Group getCompanyGroup(long companyId)
825                    throws PortalException, SystemException {
826    
827                    long classNameId = PortalUtil.getClassNameId(Company.class);
828    
829                    return groupPersistence.findByC_C_C(companyId, classNameId, companyId);
830            }
831    
832            /**
833             * Returns a range of all the groups associated with the company.
834             *
835             * <p>
836             * Useful when paginating results. Returns a maximum of <code>end -
837             * start</code> instances. <code>start</code> and <code>end</code> are not
838             * primary keys, they are indexes in the result set. Thus, <code>0</code>
839             * refers to the first result in the set. Setting both <code>start</code>
840             * and <code>end</code> to {@link
841             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
842             * result set.
843             * </p>
844             *
845             * @param  companyId the primary key of the company
846             * @param  start the lower bound of the range of groups to return
847             * @param  end the upper bound of the range of groups to return (not
848             *         inclusive)
849             * @return the range of groups associated with the company
850             * @throws SystemException if a system exception occurred
851             */
852            public List<Group> getCompanyGroups(long companyId, int start, int end)
853                    throws SystemException {
854    
855                    return groupPersistence.findByCompanyId(companyId, start, end);
856            }
857    
858            /**
859             * Returns the number of groups associated with the company.
860             *
861             * @param  companyId the primary key of the company
862             * @return the number of groups associated with the company
863             * @throws SystemException if a system exception occurred
864             */
865            public int getCompanyGroupsCount(long companyId) throws SystemException {
866                    return groupPersistence.countByCompanyId(companyId);
867            }
868    
869            /**
870             * Returns the group with the matching friendly URL.
871             *
872             * @param  companyId the primary key of the company
873             * @param  friendlyURL the group's friendlyURL
874             * @return the group with the friendly URL
875             * @throws PortalException if a matching group could not be found, or if the
876             *         friendly URL was invalid
877             * @throws SystemException if a system exception occurred
878             */
879            public Group getFriendlyURLGroup(long companyId, String friendlyURL)
880                    throws PortalException, SystemException {
881    
882                    if (Validator.isNull(friendlyURL)) {
883                            throw new NoSuchGroupException();
884                    }
885    
886                    friendlyURL = getFriendlyURL(friendlyURL);
887    
888                    return groupPersistence.findByC_F(companyId, friendlyURL);
889            }
890    
891            /**
892             * Returns the group with the matching primary key.
893             *
894             * @param  groupId the primary key of the group
895             * @return the group with the primary key
896             * @throws PortalException if a group with the primary key could not be
897             *         found
898             * @throws SystemException if a system exception occurred
899             */
900            @Override
901            @ThreadLocalCachable
902            public Group getGroup(long groupId)
903                    throws PortalException, SystemException {
904    
905                    return groupPersistence.findByPrimaryKey(groupId);
906            }
907    
908            /**
909             * Returns the group with the matching group name.
910             *
911             * @param  companyId the primary key of the company
912             * @param  name the group's name
913             * @return the group with the name
914             * @throws PortalException if a matching group could not be found
915             * @throws SystemException if a system exception occurred
916             */
917            @Skip
918            public Group getGroup(long companyId, String name)
919                    throws PortalException, SystemException {
920    
921                    Group group = _systemGroupsMap.get(
922                            StringUtil.toHexString(companyId).concat(name));
923    
924                    if (group != null) {
925                            return group;
926                    }
927    
928                    return groupLocalService.loadGetGroup(companyId, name);
929            }
930    
931            public String getGroupDescriptiveName(Group group, Locale locale)
932                    throws PortalException, SystemException {
933    
934                    String name = group.getName();
935    
936                    if (group.isCompany()) {
937                            name = LanguageUtil.get(locale, "global");
938                    }
939                    else if (group.isControlPanel()) {
940                            name = LanguageUtil.get(locale, "control-panel");
941                    }
942                    else if (group.isLayout()) {
943                            Layout layout = layoutLocalService.getLayout(group.getClassPK());
944    
945                            name = layout.getName(locale);
946                    }
947                    else if (group.isLayoutPrototype()) {
948                            LayoutPrototype layoutPrototype =
949                                    layoutPrototypeLocalService.getLayoutPrototype(
950                                            group.getClassPK());
951    
952                            name = layoutPrototype.getName(locale);
953                    }
954                    else if (group.isLayoutSetPrototype()) {
955                            LayoutSetPrototype layoutSetPrototype =
956                                    layoutSetPrototypePersistence.findByPrimaryKey(
957                                            group.getClassPK());
958    
959                            name = layoutSetPrototype.getName(locale);
960                    }
961                    else if (group.isOrganization()) {
962                            long organizationId = group.getOrganizationId();
963    
964                            Organization organization =
965                                    organizationPersistence.findByPrimaryKey(organizationId);
966    
967                            name = organization.getName();
968    
969                            Group organizationGroup = organization.getGroup();
970    
971                            if (organizationGroup.isStaged() && group.isStagingGroup()) {
972                                    name = name + " (" + LanguageUtil.get(locale, "staging") + ")";
973                            }
974                    }
975                    else if (group.isUser()) {
976                            long userId = group.getClassPK();
977    
978                            User user = userPersistence.findByPrimaryKey(userId);
979    
980                            name = user.getFullName();
981                    }
982                    else if (group.isUserGroup()) {
983                            long userGroupId = group.getClassPK();
984    
985                            UserGroup userGroup = userGroupPersistence.findByPrimaryKey(
986                                    userGroupId);
987    
988                            name = userGroup.getName();
989                    }
990                    else if (group.isUserPersonalSite()) {
991                            name = LanguageUtil.get(locale, "user-personal-site");
992                    }
993                    else if (name.equals(GroupConstants.GUEST)) {
994                            Company company = companyPersistence.findByPrimaryKey(
995                                    group.getCompanyId());
996    
997                            Account account = company.getAccount();
998    
999                            name = account.getName();
1000                    }
1001    
1002                    return name;
1003            }
1004    
1005            public String getGroupDescriptiveName(long groupId, Locale locale)
1006                    throws PortalException, SystemException {
1007    
1008                    Group group = groupPersistence.findByPrimaryKey(groupId);
1009    
1010                    return getGroupDescriptiveName(group, locale);
1011            }
1012    
1013            /**
1014             * Returns all the sites that are children of the parent group.
1015             *
1016             * @param  companyId the primary key of the company
1017             * @param  parentGroupId the primary key of the parent group
1018             * @param  site whether the group is to be associated with a main site
1019             * @return the matching groups, or <code>null</code> if no matches were
1020             *         found
1021             * @throws SystemException if a system exception occurred
1022             */
1023            public List<Group> getGroups(
1024                            long companyId, long parentGroupId, boolean site)
1025                    throws SystemException {
1026    
1027                    if (parentGroupId == GroupConstants.ANY_PARENT_GROUP_ID) {
1028                            return groupPersistence.findByC_S(companyId, site);
1029                    }
1030    
1031                    return groupPersistence.findByC_P_S(companyId, parentGroupId, site);
1032            }
1033    
1034            /**
1035             * Returns the groups with the matching primary keys.
1036             *
1037             * @param  groupIds the primary keys of the groups
1038             * @return the groups with the primary keys
1039             * @throws PortalException if any one of the groups could not be found
1040             * @throws SystemException if a system exception occurred
1041             */
1042            public List<Group> getGroups(long[] groupIds)
1043                    throws PortalException, SystemException {
1044    
1045                    List<Group> groups = new ArrayList<Group>(groupIds.length);
1046    
1047                    for (long groupId : groupIds) {
1048                            Group group = getGroup(groupId);
1049    
1050                            groups.add(group);
1051                    }
1052    
1053                    return groups;
1054            }
1055    
1056            /**
1057             * Returns the group associated with the layout.
1058             *
1059             * @param  companyId the primary key of the company
1060             * @param  plid the primary key of the layout
1061             * @return the group associated with the layout
1062             * @throws PortalException if a matching group could not be found
1063             * @throws SystemException if a system exception occurred
1064             */
1065            public Group getLayoutGroup(long companyId, long plid)
1066                    throws PortalException, SystemException {
1067    
1068                    long classNameId = PortalUtil.getClassNameId(Layout.class);
1069    
1070                    return groupPersistence.findByC_C_C(companyId, classNameId, plid);
1071            }
1072    
1073            /**
1074             * Returns the group associated with the layout prototype.
1075             *
1076             * @param  companyId the primary key of the company
1077             * @param  layoutPrototypeId the primary key of the layout prototype
1078             * @return the group associated with the layout prototype
1079             * @throws PortalException if a matching group could not be found
1080             * @throws SystemException if a system exception occurred
1081             */
1082            public Group getLayoutPrototypeGroup(long companyId, long layoutPrototypeId)
1083                    throws PortalException, SystemException {
1084    
1085                    long classNameId = PortalUtil.getClassNameId(LayoutPrototype.class);
1086    
1087                    return groupPersistence.findByC_C_C(
1088                            companyId, classNameId, layoutPrototypeId);
1089            }
1090    
1091            /**
1092             * Returns the group associated with the layout set prototype.
1093             *
1094             * @param  companyId the primary key of the company
1095             * @param  layoutSetPrototypeId the primary key of the layout set prototype
1096             * @return the group associated with the layout set prototype
1097             * @throws PortalException if a matching group could not be found
1098             * @throws SystemException if a system exception occurred
1099             */
1100            public Group getLayoutSetPrototypeGroup(
1101                            long companyId, long layoutSetPrototypeId)
1102                    throws PortalException, SystemException {
1103    
1104                    long classNameId = PortalUtil.getClassNameId(LayoutSetPrototype.class);
1105    
1106                    return groupPersistence.findByC_C_C(
1107                            companyId, classNameId, layoutSetPrototypeId);
1108            }
1109    
1110            /**
1111             * Returns a range of all groups that are children of the parent group and
1112             * that have at least one layout.
1113             *
1114             * <p>
1115             * Useful when paginating results. Returns a maximum of <code>end -
1116             * start</code> instances. <code>start</code> and <code>end</code> are not
1117             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1118             * refers to the first result in the set. Setting both <code>start</code>
1119             * and <code>end</code> to {@link
1120             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1121             * result set.
1122             * </p>
1123             *
1124             * @param  companyId the primary key of the company
1125             * @param  parentGroupId the primary key of the parent group
1126             * @param  site whether the group is to be associated with a main site
1127             * @param  start the lower bound of the range of groups to return
1128             * @param  end the upper bound of the range of groups to return (not
1129             *         inclusive)
1130             * @return the range of matching groups
1131             * @throws SystemException if a system exception occurred
1132             */
1133            public List<Group> getLayoutsGroups(
1134                            long companyId, long parentGroupId, boolean site, int start,
1135                            int end)
1136                    throws SystemException {
1137    
1138                    return groupFinder.findByLayouts(
1139                            companyId, parentGroupId, site, start, end);
1140            }
1141    
1142            /**
1143             * Returns the number of groups that are children or the parent group and
1144             * that have at least one layout
1145             *
1146             * @param  companyId the primary key of the company
1147             * @param  parentGroupId the primary key of the parent group
1148             * @param  site whether the group is to be associated with a main site
1149             * @return the number of matching groups
1150             * @throws SystemException if a system exception occurred
1151             */
1152            public int getLayoutsGroupsCount(
1153                            long companyId, long parentGroupId, boolean site)
1154                    throws SystemException {
1155    
1156                    return groupFinder.countByLayouts(companyId, parentGroupId, site);
1157            }
1158    
1159            /**
1160             * Returns all live groups.
1161             *
1162             * @return all live groups
1163             * @throws SystemException if a system exception occurred
1164             */
1165            public List<Group> getLiveGroups() throws SystemException {
1166                    return groupFinder.findByLiveGroups();
1167            }
1168    
1169            /**
1170             * Returns a range of all non-system groups of a specified type (className)
1171             * that have no layouts.
1172             *
1173             * <p>
1174             * Useful when paginating results. Returns a maximum of <code>end -
1175             * start</code> instances. <code>start</code> and <code>end</code> are not
1176             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1177             * refers to the first result in the set. Setting both <code>start</code>
1178             * and <code>end</code> to {@link
1179             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1180             * result set.
1181             * </p>
1182             *
1183             * @param  className the entity's class name
1184             * @param  privateLayout whether to include groups with private layout sets
1185             *         or non-private layout sets
1186             * @param  start the lower bound of the range of groups to return
1187             * @param  end the upper bound of the range of groups to return (not
1188             *         inclusive)
1189             * @return the range of matching groups
1190             * @throws SystemException if a system exception occurred
1191             */
1192            public List<Group> getNoLayoutsGroups(
1193                            String className, boolean privateLayout, int start, int end)
1194                    throws SystemException {
1195    
1196                    long classNameId = PortalUtil.getClassNameId(className);
1197    
1198                    return groupFinder.findByNoLayouts(
1199                            classNameId, privateLayout, start, end);
1200            }
1201    
1202            /**
1203             * Returns all non-system groups having <code>null</code> or empty friendly
1204             * URLs.
1205             *
1206             * @return the non-system groups having <code>null</code> or empty friendly
1207             *         URLs
1208             * @throws SystemException if a system exception occurred
1209             */
1210            public List<Group> getNullFriendlyURLGroups() throws SystemException {
1211                    return groupFinder.findByNullFriendlyURL();
1212            }
1213    
1214            /**
1215             * Returns the specified organization group.
1216             *
1217             * @param  companyId the primary key of the company
1218             * @param  organizationId the primary key of the organization
1219             * @return the group associated with the organization
1220             * @throws PortalException if a matching group could not be found
1221             * @throws SystemException if a system exception occurred
1222             */
1223            public Group getOrganizationGroup(long companyId, long organizationId)
1224                    throws PortalException, SystemException {
1225    
1226                    long classNameId = PortalUtil.getClassNameId(Organization.class);
1227    
1228                    return groupPersistence.findByC_C_C(
1229                            companyId, classNameId, organizationId);
1230            }
1231    
1232            /**
1233             * Returns the specified organization groups.
1234             *
1235             * @param  organizations the organizations
1236             * @return the groups associated with the organizations
1237             */
1238            public List<Group> getOrganizationsGroups(
1239                    List<Organization> organizations) {
1240    
1241                    List<Group> organizationGroups = new ArrayList<Group>();
1242    
1243                    for (int i = 0; i < organizations.size(); i++) {
1244                            Organization organization = organizations.get(i);
1245    
1246                            Group group = organization.getGroup();
1247    
1248                            organizationGroups.add(group);
1249                    }
1250    
1251                    return organizationGroups;
1252            }
1253    
1254            /**
1255             * Returns all the groups related to the organizations.
1256             *
1257             * @param  organizations the organizations
1258             * @return the groups related to the organizations
1259             * @throws SystemException if a system exception occurred
1260             */
1261            public List<Group> getOrganizationsRelatedGroups(
1262                            List<Organization> organizations)
1263                    throws SystemException {
1264    
1265                    List<Group> organizationGroups = new ArrayList<Group>();
1266    
1267                    for (int i = 0; i < organizations.size(); i++) {
1268                            Organization organization = organizations.get(i);
1269    
1270                            List<Group> groups = organizationPersistence.getGroups(
1271                                    organization.getOrganizationId());
1272    
1273                            organizationGroups.addAll(groups);
1274                    }
1275    
1276                    return organizationGroups;
1277            }
1278    
1279            /**
1280             * Returns all the groups associated with the role.
1281             *
1282             * @param  roleId the primary key of the role
1283             * @return the groups associated with the role
1284             * @throws SystemException if a system exception occurred
1285             */
1286            public List<Group> getRoleGroups(long roleId) throws SystemException {
1287                    return rolePersistence.getGroups(roleId);
1288            }
1289    
1290            /**
1291             * Returns the staging group.
1292             *
1293             * @param  liveGroupId the primary key of the live group
1294             * @return the staging group
1295             * @throws PortalException if a matching staging group could not be found
1296             * @throws SystemException if a system exception occurred
1297             */
1298            public Group getStagingGroup(long liveGroupId)
1299                    throws PortalException, SystemException {
1300    
1301                    return groupPersistence.findByLiveGroupId(liveGroupId);
1302            }
1303    
1304            /**
1305             * Returns the group associated with the user.
1306             *
1307             * @param  companyId the primary key of the company
1308             * @param  userId the primary key of the user
1309             * @return the group associated with the user
1310             * @throws PortalException if a matching group could not be found
1311             * @throws SystemException if a system exception occurred
1312             */
1313            public Group getUserGroup(long companyId, long userId)
1314                    throws PortalException, SystemException {
1315    
1316                    long classNameId = PortalUtil.getClassNameId(User.class);
1317    
1318                    return groupPersistence.findByC_C_C(companyId, classNameId, userId);
1319            }
1320    
1321            /**
1322             * Returns the specified "user group" group. That is, the group that
1323             * represents the {@link com.liferay.portal.model.UserGroup} entity.
1324             *
1325             * @param  companyId the primary key of the company
1326             * @param  userGroupId the primary key of the user group
1327             * @return the group associated with the user group
1328             * @throws PortalException if a matching group could not be found
1329             * @throws SystemException if a system exception occurred
1330             */
1331            public Group getUserGroupGroup(long companyId, long userGroupId)
1332                    throws PortalException, SystemException {
1333    
1334                    long classNameId = PortalUtil.getClassNameId(UserGroup.class);
1335    
1336                    return groupPersistence.findByC_C_C(
1337                            companyId, classNameId, userGroupId);
1338            }
1339    
1340            /**
1341             * Returns all the user's site groups and immediate organization groups.
1342             * System and staged groups are not included.
1343             *
1344             * @param  userId the primary key of the user
1345             * @return the user's groups and organization groups
1346             * @throws PortalException if a user with the primary key could not be found
1347             * @throws SystemException if a system exception occurred
1348             */
1349            public List<Group> getUserGroups(long userId)
1350                    throws PortalException, SystemException {
1351    
1352                    return getUserGroups(userId, false);
1353            }
1354    
1355            /**
1356             * Returns all the user's site groups and immediate organization groups,
1357             * optionally including the user's inherited organization groups and user
1358             * groups. System and staged groups are not included.
1359             *
1360             * @param  userId the primary key of the user
1361             * @param  inherit whether to include the user's inherited organization
1362             *         groups and user groups
1363             * @return the user's groups and immediate organization groups
1364             * @throws PortalException if a user with the primary key could not be found
1365             * @throws SystemException if a system exception occurred
1366             */
1367            public List<Group> getUserGroups(long userId, boolean inherit)
1368                    throws PortalException, SystemException {
1369    
1370                    return getUserGroups(
1371                            userId, inherit, QueryUtil.ALL_POS, QueryUtil.ALL_POS);
1372            }
1373    
1374            /**
1375             * Returns an ordered range of all the user's site groups and immediate
1376             * organization groups, optionally including the user's inherited
1377             * organization groups and user groups. System and staged groups are not
1378             * included.
1379             *
1380             * <p>
1381             * Useful when paginating results. Returns a maximum of <code>end -
1382             * start</code> instances. <code>start</code> and <code>end</code> are not
1383             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1384             * refers to the first result in the set. Setting both <code>start</code>
1385             * and <code>end</code> to {@link
1386             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1387             * result set.
1388             * </p>
1389             *
1390             * @param  userId the primary key of the user
1391             * @param  inherit whether to include the user's inherited organization
1392             *         groups and user groups
1393             * @param  start the lower bound of the range of groups to return
1394             * @param  end the upper bound of the range of groups to return (not
1395             *         inclusive)
1396             * @return the range of the user's groups and immediate organization groups
1397             *         ordered by name
1398             * @throws PortalException if a user with the primary key could not be found
1399             * @throws SystemException if a system exception occurred
1400             */
1401            public List<Group> getUserGroups(
1402                            long userId, boolean inherit, int start, int end)
1403                    throws PortalException, SystemException {
1404    
1405                    if (inherit) {
1406                            User user = userPersistence.findByPrimaryKey(userId);
1407    
1408                            LinkedHashMap<String, Object> groupParams =
1409                                    new LinkedHashMap<String, Object>();
1410    
1411                            groupParams.put("usersGroups", new Long(userId));
1412    
1413                            return search(
1414                                    user.getCompanyId(), null, null, groupParams, start, end);
1415                    }
1416                    else {
1417                            return userPersistence.getGroups(userId, start, end);
1418                    }
1419            }
1420    
1421            /**
1422             * Returns an ordered range of all the user's site groups and immediate
1423             * organization groups. System and staged groups are not included.
1424             *
1425             * <p>
1426             * Useful when paginating results. Returns a maximum of <code>end -
1427             * start</code> instances. <code>start</code> and <code>end</code> are not
1428             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1429             * refers to the first result in the set. Setting both <code>start</code>
1430             * and <code>end</code> to {@link
1431             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1432             * result set.
1433             * </p>
1434             *
1435             * @param  userId the primary key of the user
1436             * @param  start the lower bound of the range of groups to return
1437             * @param  end the upper bound of the range of groups to return (not
1438             *         inclusive)
1439             * @return the range of the user's groups and organization groups ordered by
1440             *         name
1441             * @throws PortalException if a user with the primary key could not be found
1442             * @throws SystemException if a system exception occurred
1443             */
1444            public List<Group> getUserGroups(long userId, int start, int end)
1445                    throws PortalException, SystemException {
1446    
1447                    return getUserGroups(userId, false, start, end);
1448            }
1449    
1450            /**
1451             * Returns the groups associated with the user groups.
1452             *
1453             * @param  userGroups the user groups
1454             * @return the groups associated with the user groups
1455             * @throws PortalException if any one of the user group's group could not be
1456             *         found
1457             * @throws SystemException if a system exception occurred
1458             */
1459            public List<Group> getUserGroupsGroups(List<UserGroup> userGroups)
1460                    throws PortalException, SystemException {
1461    
1462                    List<Group> userGroupGroups = new ArrayList<Group>();
1463    
1464                    for (int i = 0; i < userGroups.size(); i++) {
1465                            UserGroup userGroup = userGroups.get(i);
1466    
1467                            Group group = userGroup.getGroup();
1468    
1469                            userGroupGroups.add(group);
1470                    }
1471    
1472                    return userGroupGroups;
1473            }
1474    
1475            /**
1476             * Returns all the groups related to the user groups.
1477             *
1478             * @param  userGroups the user groups
1479             * @return the groups related to the user groups
1480             * @throws SystemException if a system exception occurred
1481             */
1482            public List<Group> getUserGroupsRelatedGroups(List<UserGroup> userGroups)
1483                    throws SystemException {
1484    
1485                    List<Group> userGroupGroups = new ArrayList<Group>();
1486    
1487                    for (int i = 0; i < userGroups.size(); i++) {
1488                            UserGroup userGroup = userGroups.get(i);
1489    
1490                            List<Group> groups = userGroupPersistence.getGroups(
1491                                    userGroup.getUserGroupId());
1492    
1493                            userGroupGroups.addAll(groups);
1494                    }
1495    
1496                    return userGroupGroups;
1497            }
1498    
1499            /**
1500             * Returns the range of all groups associated with the user's organization
1501             * groups, including the ancestors of the organization groups, unless portal
1502             * property <code>organizations.membership.strict</code> is set to
1503             * <code>true</code>.
1504             *
1505             * <p>
1506             * Useful when paginating results. Returns a maximum of <code>end -
1507             * start</code> instances. <code>start</code> and <code>end</code> are not
1508             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1509             * refers to the first result in the set. Setting both <code>start</code>
1510             * and <code>end</code> to {@link
1511             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1512             * result set.
1513             * </p>
1514             *
1515             * @param  userId the primary key of the user
1516             * @param  start the lower bound of the range of groups to consider
1517             * @param  end the upper bound of the range of groups to consider (not
1518             *         inclusive)
1519             * @return the range of groups associated with the user's organization
1520             *         groups
1521             * @throws PortalException if a user with the primary key could not be found
1522             *         or if another portal exception occurred
1523             * @throws SystemException if a system exception occurred
1524             */
1525            public List<Group> getUserOrganizationsGroups(
1526                            long userId, int start, int end)
1527                    throws PortalException, SystemException {
1528    
1529                    List<Group> userOrgsGroups = new UniqueList<Group>();
1530    
1531                    List<Organization> userOrgs =
1532                            organizationLocalService.getUserOrganizations(userId, start, end);
1533    
1534                    for (Organization organization : userOrgs) {
1535                            userOrgsGroups.add(0, organization.getGroup());
1536    
1537                            if (!PropsValues.ORGANIZATIONS_MEMBERSHIP_STRICT) {
1538                                    for (Organization ancestorOrganization :
1539                                                    organization.getAncestors()) {
1540    
1541                                            userOrgsGroups.add(0, ancestorOrganization.getGroup());
1542                                    }
1543                            }
1544                    }
1545    
1546                    return userOrgsGroups;
1547            }
1548    
1549            /**
1550             * Returns <code>true</code> if the group is associated with the role.
1551             *
1552             * @param  roleId the primary key of the role
1553             * @param  groupId the primary key of the group
1554             * @return <code>true</code> if the group is associated with the role;
1555             *         <code>false</code> otherwise
1556             * @throws SystemException if a system exception occurred
1557             */
1558            public boolean hasRoleGroup(long roleId, long groupId)
1559                    throws SystemException {
1560    
1561                    return rolePersistence.containsGroup(roleId, groupId);
1562            }
1563    
1564            /**
1565             * Returns <code>true</code> if the live group has a staging group.
1566             *
1567             * @param  liveGroupId the primary key of the live group
1568             * @return <code>true</code> if the live group has a staging group;
1569             *         <code>false</code> otherwise
1570             * @throws SystemException if a system exception occurred
1571             */
1572            public boolean hasStagingGroup(long liveGroupId) throws SystemException {
1573                    if (groupPersistence.fetchByLiveGroupId(liveGroupId) != null) {
1574                            return true;
1575                    }
1576                    else {
1577                            return false;
1578                    }
1579            }
1580    
1581            /**
1582             * Returns <code>true</code> if the user is immediately associated with the
1583             * group, or associated with the group via the user's organizations,
1584             * inherited organizations, or user groups.
1585             *
1586             * @param  userId the primary key of the user
1587             * @param  groupId the primary key of the group
1588             * @return <code>true</code> if the user is associated with the group;
1589             *         <code>false</code> otherwise
1590             * @throws SystemException if a system exception occurred
1591             */
1592            public boolean hasUserGroup(long userId, long groupId)
1593                    throws SystemException {
1594    
1595                    return hasUserGroup(userId, groupId, true);
1596            }
1597    
1598            /**
1599             * Returns <code>true</code> if the user is immediately associated with the
1600             * group, or optionally if the user is associated with the group via the
1601             * user's organizations, inherited organizations, or user groups.
1602             *
1603             * @param  userId the primary key of the user
1604             * @param  groupId the primary key of the group
1605             * @param  inherit whether to include organization groups and user groups to
1606             *         which the user belongs in the determination
1607             * @return <code>true</code> if the user is associated with the group;
1608             *         <code>false</code> otherwise
1609             * @throws SystemException if a system exception occurred
1610             */
1611            public boolean hasUserGroup(long userId, long groupId, boolean inherit)
1612                    throws SystemException {
1613    
1614                    if (groupFinder.countByG_U(groupId, userId, inherit) > 0) {
1615                            return true;
1616                    }
1617                    else {
1618                            return false;
1619                    }
1620            }
1621    
1622            /**
1623             * Returns the group with the matching group name by first searching the
1624             * system groups and then using the finder cache.
1625             *
1626             * @param  companyId the primary key of the company
1627             * @param  name the group's name
1628             * @return the group with the name and associated company, or
1629             *         <code>null</code> if a matching group could not be found
1630             * @throws SystemException if a system exception occurred
1631             */
1632            public Group loadFetchGroup(long companyId, String name)
1633                    throws SystemException {
1634    
1635                    return groupPersistence.fetchByC_N(companyId, name);
1636            }
1637    
1638            /**
1639             * Returns the group with the matching group name.
1640             *
1641             * @param  companyId the primary key of the company
1642             * @param  name the group's name
1643             * @return the group with the name and associated company
1644             * @throws PortalException if a matching group could not be found
1645             * @throws SystemException if a system exception occurred
1646             */
1647            public Group loadGetGroup(long companyId, String name)
1648                    throws PortalException, SystemException {
1649    
1650                    return groupPersistence.findByC_N(companyId, name);
1651            }
1652    
1653            /**
1654             * Returns an ordered range of all the company's groups, optionally
1655             * including the user's inherited organization groups and user groups.
1656             * System and staged groups are not included.
1657             *
1658             * <p>
1659             * Useful when paginating results. Returns a maximum of <code>end -
1660             * start</code> instances. <code>start</code> and <code>end</code> are not
1661             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1662             * refers to the first result in the set. Setting both <code>start</code>
1663             * and <code>end</code> to {@link
1664             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1665             * result set.
1666             * </p>
1667             *
1668             * @param  companyId the primary key of the company
1669             * @param  params the finder params (optionally <code>null</code>). To
1670             *         include a user's organizations, inherited organizations, and user
1671             *         groups in the search, add an entry with key
1672             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
1673             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
1674             *         For more information see {@link
1675             *         com.liferay.portal.service.persistence.GroupFinder}
1676             * @param  start the lower bound of the range of groups to return
1677             * @param  end the upper bound of the range of groups to return (not
1678             *         inclusive)
1679             * @return the matching groups ordered by name
1680             * @throws SystemException if a system exception occurred
1681             */
1682            public List<Group> search(
1683                            long companyId, LinkedHashMap<String, Object> params, int start,
1684                            int end)
1685                    throws SystemException {
1686    
1687                    return groupFinder.findByCompanyId(
1688                            companyId, params, start, end, new GroupNameComparator(true));
1689            }
1690    
1691            /**
1692             * Returns an ordered range of all the groups belonging to the parent group
1693             * that match the keywords, optionally including the user's inherited
1694             * organization groups and user groups. System and staged groups are not
1695             * included.
1696             *
1697             * <p>
1698             * Useful when paginating results. Returns a maximum of <code>end -
1699             * start</code> instances. <code>start</code> and <code>end</code> are not
1700             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1701             * refers to the first result in the set. Setting both <code>start</code>
1702             * and <code>end</code> to {@link
1703             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1704             * result set.
1705             * </p>
1706             *
1707             * @param  companyId the primary key of the company
1708             * @param  parentGroupId the primary key of the parent group
1709             * @param  keywords the keywords (space separated), which may occur in the
1710             *         sites's name, or description (optionally <code>null</code>)
1711             * @param  params the finder params (optionally <code>null</code>). To
1712             *         include the user's inherited organizations and user groups in the
1713             *         search, add entries having &quot;usersGroups&quot; and
1714             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
1715             *         information see {@link
1716             *         com.liferay.portal.service.persistence.GroupFinder}
1717             * @param  start the lower bound of the range of groups to return
1718             * @param  end the upper bound of the range of groups to return (not
1719             *         inclusive)
1720             * @return the matching groups ordered by name
1721             * @throws SystemException if a system exception occurred
1722             */
1723            public List<Group> search(
1724                            long companyId, long parentGroupId, String keywords,
1725                            LinkedHashMap<String, Object> params, int start, int end)
1726                    throws SystemException {
1727    
1728                    return search(
1729                            companyId, parentGroupId, keywords, params, start, end, null);
1730            }
1731    
1732            /**
1733             * Returns an ordered range of all the groups belonging to the parent group
1734             * that match the keywords, optionally including the user's inherited
1735             * organization groups and user groups. System and staged groups are not
1736             * included.
1737             *
1738             * <p>
1739             * Useful when paginating results. Returns a maximum of <code>end -
1740             * start</code> instances. <code>start</code> and <code>end</code> are not
1741             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1742             * refers to the first result in the set. Setting both <code>start</code>
1743             * and <code>end</code> to {@link
1744             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1745             * result set.
1746             * </p>
1747             *
1748             * @param  companyId the primary key of the company
1749             * @param  parentGroupId the primary key of the parent group
1750             * @param  keywords the keywords (space separated), which may occur in the
1751             *         sites's name, or description (optionally <code>null</code>)
1752             * @param  params the finder params (optionally <code>null</code>). To
1753             *         include the user's inherited organizations and user groups in the
1754             *         search, add entries having &quot;usersGroups&quot; and
1755             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
1756             *         information see {@link
1757             *         com.liferay.portal.service.persistence.GroupFinder}
1758             * @param  start the lower bound of the range of groups to return
1759             * @param  end the upper bound of the range of groups to return (not
1760             *         inclusive)
1761             * @param  obc the comparator to order the groups (optionally
1762             *         <code>null</code>)
1763             * @return the matching groups ordered by comparator <code>obc</code>
1764             * @throws SystemException if a system exception occurred
1765             */
1766            public List<Group> search(
1767                            long companyId, long parentGroupId, String keywords,
1768                            LinkedHashMap<String, Object> params, int start, int end,
1769                            OrderByComparator obc)
1770                    throws SystemException {
1771    
1772                    String parentGroupIdComparator = StringPool.EQUAL;
1773    
1774                    if (parentGroupId == GroupConstants.ANY_PARENT_GROUP_ID) {
1775                            parentGroupIdComparator = StringPool.NOT_EQUAL;
1776                    }
1777    
1778                    if (obc == null) {
1779                            obc = new GroupNameComparator(true);
1780                    }
1781    
1782                    return groupFinder.findByKeywords(
1783                            companyId, parentGroupId, parentGroupIdComparator, keywords, params,
1784                            start, end, obc);
1785            }
1786    
1787            /**
1788             * Returns an ordered range of all the site groups belonging to the parent
1789             * group and organization groups that match the name and description,
1790             * optionally including the user's inherited organization groups and user
1791             * groups. System and staged groups are not included.
1792             *
1793             * <p>
1794             * Useful when paginating results. Returns a maximum of <code>end -
1795             * start</code> instances. <code>start</code> and <code>end</code> are not
1796             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1797             * refers to the first result in the set. Setting both <code>start</code>
1798             * and <code>end</code> to {@link
1799             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1800             * result set.
1801             * </p>
1802             *
1803             * @param  companyId the primary key of the company
1804             * @param  parentGroupId the primary key of the parent group
1805             * @param  name the group's name (optionally <code>null</code>)
1806             * @param  description the group's description (optionally
1807             *         <code>null</code>)
1808             * @param  params the finder params (optionally <code>null</code>). To
1809             *         include the user's inherited organizations and user groups in the
1810             *         search, add entries having &quot;usersGroups&quot; and
1811             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
1812             *         information see {@link
1813             *         com.liferay.portal.service.persistence.GroupFinder}
1814             * @param  andOperator whether every field must match its keywords, or just
1815             *         one field.
1816             * @param  start the lower bound of the range of groups to return
1817             * @param  end the upper bound of the range of groups to return (not
1818             *         inclusive)
1819             * @return the matching groups ordered by name
1820             * @throws SystemException if a system exception occurred
1821             */
1822            public List<Group> search(
1823                            long companyId, long parentGroupId, String name, String description,
1824                            LinkedHashMap<String, Object> params, boolean andOperator,
1825                            int start, int end)
1826                    throws SystemException {
1827    
1828                    return search(
1829                            companyId, parentGroupId, name, description, params, andOperator,
1830                            start, end, null);
1831            }
1832    
1833            /**
1834             * Returns an ordered range of all the site groups belonging to the parent
1835             * group and organization groups that match the name and description,
1836             * optionally including the user's inherited organization groups and user
1837             * groups. System and staged groups are not included.
1838             *
1839             * <p>
1840             * Useful when paginating results. Returns a maximum of <code>end -
1841             * start</code> instances. <code>start</code> and <code>end</code> are not
1842             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1843             * refers to the first result in the set. Setting both <code>start</code>
1844             * and <code>end</code> to {@link
1845             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1846             * result set.
1847             * </p>
1848             *
1849             * @param  companyId the primary key of the company
1850             * @param  parentGroupId the primary key of the parent group
1851             * @param  name the group's name (optionally <code>null</code>)
1852             * @param  description the group's description (optionally
1853             *         <code>null</code>)
1854             * @param  params the finder params (optionally <code>null</code>). To
1855             *         include the user's inherited organizations and user groups in the
1856             *         search, add entries having &quot;usersGroups&quot; and
1857             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
1858             *         information see {@link
1859             *         com.liferay.portal.service.persistence.GroupFinder}
1860             * @param  andOperator whether every field must match its keywords, or just
1861             *         one field.
1862             * @param  start the lower bound of the range of groups to return
1863             * @param  end the upper bound of the range of groups to return (not
1864             *         inclusive)
1865             * @param  obc the comparator to order the groups (optionally
1866             *         <code>null</code>)
1867             * @return the matching groups ordered by comparator <code>obc</code>
1868             * @throws SystemException if a system exception occurred
1869             */
1870            public List<Group> search(
1871                            long companyId, long parentGroupId, String name, String description,
1872                            LinkedHashMap<String, Object> params, boolean andOperator,
1873                            int start, int end, OrderByComparator obc)
1874                    throws SystemException {
1875    
1876                    String parentGroupIdComparator = StringPool.EQUAL;
1877    
1878                    if (parentGroupId == GroupConstants.ANY_PARENT_GROUP_ID) {
1879                            parentGroupIdComparator = StringPool.NOT_EQUAL;
1880                    }
1881    
1882                    if (obc == null) {
1883                            obc = new GroupNameComparator(true);
1884                    }
1885    
1886                    String realName = getRealName(companyId, name);
1887    
1888                    return groupFinder.findByC_PG_N_D(
1889                            companyId, parentGroupId, parentGroupIdComparator, name, realName,
1890                            description, params, andOperator, start, end, obc);
1891            }
1892    
1893            /**
1894             * Returns an ordered range of all the groups belonging to the parent group
1895             * that match the class name IDs and keywords, optionally including the
1896             * user's inherited organization groups and user groups. System and staged
1897             * groups are not included.
1898             *
1899             * <p>
1900             * Useful when paginating results. Returns a maximum of <code>end -
1901             * start</code> instances. <code>start</code> and <code>end</code> are not
1902             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1903             * refers to the first result in the set. Setting both <code>start</code>
1904             * and <code>end</code> to {@link
1905             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1906             * result set.
1907             * </p>
1908             *
1909             * @param  companyId the primary key of the company
1910             * @param  classNameIds the class names of entities to include in the search
1911             *         (optionally <code>null</code>)
1912             * @param  parentGroupId the primary key of the parent group
1913             * @param  keywords the keywords (space separated), which may occur in the
1914             *         sites's name, or description (optionally <code>null</code>)
1915             * @param  params the finder params (optionally <code>null</code>). To
1916             *         include a user's organizations, inherited organizations, and user
1917             *         groups in the search, add an entry with key
1918             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
1919             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
1920             *         For more information see {@link
1921             *         com.liferay.portal.service.persistence.GroupFinder}
1922             * @param  start the lower bound of the range of groups to return
1923             * @param  end the upper bound of the range of groups to return (not
1924             *         inclusive)
1925             * @return the matching groups ordered by name
1926             * @throws SystemException if a system exception occurred
1927             */
1928            public List<Group> search(
1929                            long companyId, long[] classNameIds, long parentGroupId,
1930                            String keywords, LinkedHashMap<String, Object> params, int start,
1931                            int end)
1932                    throws SystemException {
1933    
1934                    return search(
1935                            companyId, classNameIds, parentGroupId, keywords, params, start,
1936                            end, null);
1937            }
1938    
1939            /**
1940             * Returns an ordered range of all the groups belonging to the parent group
1941             * that match the class name IDs and keywords, optionally including the
1942             * user's inherited organization groups and user groups. System and staged
1943             * groups are not included.
1944             *
1945             * <p>
1946             * Useful when paginating results. Returns a maximum of <code>end -
1947             * start</code> instances. <code>start</code> and <code>end</code> are not
1948             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1949             * refers to the first result in the set. Setting both <code>start</code>
1950             * and <code>end</code> to {@link
1951             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1952             * result set.
1953             * </p>
1954             *
1955             * @param  companyId the primary key of the company
1956             * @param  classNameIds the group's class name IDs (optionally
1957             *         <code>null</code>)
1958             * @param  parentGroupId the primary key of the parent group
1959             * @param  keywords the keywords (space separated), which may occur in the
1960             *         sites's name, or description (optionally <code>null</code>)
1961             * @param  params the finder params (optionally <code>null</code>). To
1962             *         include a user's organizations, inherited organizations, and user
1963             *         groups in the search, add an entry with key
1964             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
1965             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
1966             *         For more information see {@link
1967             *         com.liferay.portal.service.persistence.GroupFinder}
1968             * @param  start the lower bound of the range of groups to return
1969             * @param  end the upper bound of the range of groups to return (not
1970             *         inclusive)
1971             * @param  obc the comparator to order the groups (optionally
1972             *         <code>null</code>)
1973             * @return the matching groups ordered by comparator <code>obc</code>
1974             * @throws SystemException if a system exception occurred
1975             */
1976            public List<Group> search(
1977                            long companyId, long[] classNameIds, long parentGroupId,
1978                            String keywords, LinkedHashMap<String, Object> params, int start,
1979                            int end, OrderByComparator obc)
1980                    throws SystemException {
1981    
1982                    String parentGroupIdComparator = StringPool.EQUAL;
1983    
1984                    if (parentGroupId == GroupConstants.ANY_PARENT_GROUP_ID) {
1985                            parentGroupIdComparator = StringPool.NOT_EQUAL;
1986                    }
1987    
1988                    if (obc == null) {
1989                            obc = new GroupNameComparator(true);
1990                    }
1991    
1992                    return groupFinder.findByKeywords(
1993                            companyId, classNameIds, parentGroupId, parentGroupIdComparator,
1994                            keywords, params, start, end, obc);
1995            }
1996    
1997            /**
1998             * Returns an ordered range of all the groups belonging to the parent group
1999             * that match the class name IDs, name, and description, optionally
2000             * including the user's inherited organization groups and user groups.
2001             * System and staged groups are not included.
2002             *
2003             * <p>
2004             * Useful when paginating results. Returns a maximum of <code>end -
2005             * start</code> instances. <code>start</code> and <code>end</code> are not
2006             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2007             * refers to the first result in the set. Setting both <code>start</code>
2008             * and <code>end</code> to {@link
2009             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2010             * result set.
2011             * </p>
2012             *
2013             * @param  companyId the primary key of the company
2014             * @param  classNameIds the class names of entities to include in the search
2015             *         (optionally <code>null</code>)
2016             * @param  parentGroupId the primary key of the parent group
2017             * @param  name the group's name (optionally <code>null</code>)
2018             * @param  description the group's description (optionally
2019             *         <code>null</code>)
2020             * @param  params the finder params (optionally <code>null</code>). To
2021             *         include a user's organizations, inherited organizations, and user
2022             *         groups in the search, add an entry with key
2023             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
2024             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
2025             *         For more information see {@link
2026             *         com.liferay.portal.service.persistence.GroupFinder}
2027             * @param  andOperator whether every field must match its keywords, or just
2028             *         one field.
2029             * @param  start the lower bound of the range of groups to return
2030             * @param  end the upper bound of the range of groups to return (not
2031             *         inclusive)
2032             * @return the matching groups ordered by name
2033             * @throws SystemException if a system exception occurred
2034             */
2035            public List<Group> search(
2036                            long companyId, long[] classNameIds, long parentGroupId,
2037                            String name, String description,
2038                            LinkedHashMap<String, Object> params, boolean andOperator,
2039                            int start, int end)
2040                    throws SystemException {
2041    
2042                    return search(
2043                            companyId, classNameIds, parentGroupId, name, description, params,
2044                            andOperator, start, end, null);
2045            }
2046    
2047            /**
2048             * Returns an ordered range of all the groups belonging to the parent group
2049             * that match the class name IDs, name, and description, optionally
2050             * including the user's inherited organization groups and user groups.
2051             * System and staged groups are not included.
2052             *
2053             * <p>
2054             * Useful when paginating results. Returns a maximum of <code>end -
2055             * start</code> instances. <code>start</code> and <code>end</code> are not
2056             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2057             * refers to the first result in the set. Setting both <code>start</code>
2058             * and <code>end</code> to {@link
2059             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2060             * result set.
2061             * </p>
2062             *
2063             * @param  companyId the primary key of the company
2064             * @param  classNameIds the group's class name IDs (optionally
2065             *         <code>null</code>)
2066             * @param  parentGroupId the primary key of the parent group
2067             * @param  name the group's name (optionally <code>null</code>)
2068             * @param  description the group's description (optionally
2069             *         <code>null</code>)
2070             * @param  params the finder params (optionally <code>null</code>). To
2071             *         include a user's organizations, inherited organizations, and user
2072             *         groups in the search, add an entry with key
2073             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
2074             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
2075             *         For more information see {@link
2076             *         com.liferay.portal.service.persistence.GroupFinder}
2077             * @param  andOperator whether every field must match its keywords, or just
2078             *         one field.
2079             * @param  start the lower bound of the range of groups to return
2080             * @param  end the upper bound of the range of groups to return (not
2081             *         inclusive)
2082             * @param  obc the comparator to order the groups (optionally
2083             *         <code>null</code>)
2084             * @return the matching groups ordered by comparator <code>obc</code>
2085             * @throws SystemException if a system exception occurred
2086             */
2087            public List<Group> search(
2088                            long companyId, long[] classNameIds, long parentGroupId,
2089                            String name, String description,
2090                            LinkedHashMap<String, Object> params, boolean andOperator,
2091                            int start, int end, OrderByComparator obc)
2092                    throws SystemException {
2093    
2094                    String parentGroupIdComparator = StringPool.EQUAL;
2095    
2096                    if (parentGroupId == GroupConstants.ANY_PARENT_GROUP_ID) {
2097                            parentGroupIdComparator = StringPool.NOT_EQUAL;
2098                    }
2099    
2100                    if (obc == null) {
2101                            obc = new GroupNameComparator(true);
2102                    }
2103    
2104                    String realName = getRealName(companyId, name);
2105    
2106                    return groupFinder.findByC_C_PG_N_D(
2107                            companyId, classNameIds, parentGroupId, parentGroupIdComparator,
2108                            name, realName, description, params, andOperator, start, end, obc);
2109            }
2110    
2111            /**
2112             * Returns an ordered range of all the groups that match the class name IDs
2113             * and keywords, optionally including the user's inherited organization
2114             * groups and user groups. System and staged groups are not included.
2115             *
2116             * <p>
2117             * Useful when paginating results. Returns a maximum of <code>end -
2118             * start</code> instances. <code>start</code> and <code>end</code> are not
2119             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2120             * refers to the first result in the set. Setting both <code>start</code>
2121             * and <code>end</code> to {@link
2122             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2123             * result set.
2124             * </p>
2125             *
2126             * @param  companyId the primary key of the company
2127             * @param  classNameIds the class names of entities to include in the search
2128             *         (optionally <code>null</code>)
2129             * @param  keywords the keywords (space separated), which may occur in the
2130             *         sites's name, or description (optionally <code>null</code>)
2131             * @param  params the finder params (optionally <code>null</code>). To
2132             *         include a user's organizations, inherited organizations, and user
2133             *         groups in the search, add an entry with key
2134             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
2135             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
2136             *         For more information see {@link
2137             *         com.liferay.portal.service.persistence.GroupFinder}
2138             * @param  start the lower bound of the range of groups to return
2139             * @param  end the upper bound of the range of groups to return (not
2140             *         inclusive)
2141             * @return the matching groups ordered by name
2142             * @throws SystemException if a system exception occurred
2143             */
2144            public List<Group> search(
2145                            long companyId, long[] classNameIds, String keywords,
2146                            LinkedHashMap<String, Object> params, int start, int end)
2147                    throws SystemException {
2148    
2149                    return search(
2150                            companyId, classNameIds, keywords, params, start, end, null);
2151            }
2152    
2153            /**
2154             * Returns an ordered range of all the groups that match the class name IDs
2155             * and keywords, optionally including the user's inherited organization
2156             * groups and user groups. System and staged groups are not included.
2157             *
2158             * <p>
2159             * Useful when paginating results. Returns a maximum of <code>end -
2160             * start</code> instances. <code>start</code> and <code>end</code> are not
2161             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2162             * refers to the first result in the set. Setting both <code>start</code>
2163             * and <code>end</code> to {@link
2164             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2165             * result set.
2166             * </p>
2167             *
2168             * @param  companyId the primary key of the company
2169             * @param  classNameIds the group's class name IDs (optionally
2170             *         <code>null</code>)
2171             * @param  keywords the keywords (space separated), which may occur in the
2172             *         sites's name, or description (optionally <code>null</code>)
2173             * @param  params the finder params (optionally <code>null</code>). To
2174             *         include a user's organizations, inherited organizations, and user
2175             *         groups in the search, add an entry with key
2176             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
2177             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
2178             *         For more information see {@link
2179             *         com.liferay.portal.service.persistence.GroupFinder}
2180             * @param  start the lower bound of the range of groups to return
2181             * @param  end the upper bound of the range of groups to return (not
2182             *         inclusive)
2183             * @param  obc the comparator to order the groups (optionally
2184             *         <code>null</code>)
2185             * @return the matching groups ordered by comparator <code>obc</code>
2186             * @throws SystemException if a system exception occurred
2187             */
2188            public List<Group> search(
2189                            long companyId, long[] classNameIds, String keywords,
2190                            LinkedHashMap<String, Object> params, int start, int end,
2191                            OrderByComparator obc)
2192                    throws SystemException {
2193    
2194                    if (obc == null) {
2195                            obc = new GroupNameComparator(true);
2196                    }
2197    
2198                    return groupFinder.findByKeywords(
2199                            companyId, classNameIds, keywords, params, start, end, obc);
2200            }
2201    
2202            /**
2203             * Returns an ordered range of all the groups that match the class name IDs,
2204             * name, and description, optionally including the user's inherited
2205             * organization groups and user groups. System and staged groups are not
2206             * included.
2207             *
2208             * <p>
2209             * Useful when paginating results. Returns a maximum of <code>end -
2210             * start</code> instances. <code>start</code> and <code>end</code> are not
2211             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2212             * refers to the first result in the set. Setting both <code>start</code>
2213             * and <code>end</code> to {@link
2214             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2215             * result set.
2216             * </p>
2217             *
2218             * @param  companyId the primary key of the company
2219             * @param  classNameIds the class names of entities to include in the search
2220             *         (optionally <code>null</code>)
2221             * @param  name the group's name (optionally <code>null</code>)
2222             * @param  description the group's description (optionally
2223             *         <code>null</code>)
2224             * @param  params the finder params (optionally <code>null</code>). To
2225             *         include a user's organizations, inherited organizations, and user
2226             *         groups in the search, add an entry with key
2227             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
2228             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
2229             *         For more information see {@link
2230             *         com.liferay.portal.service.persistence.GroupFinder}
2231             * @param  andOperator whether every field must match its keywords, or just
2232             *         one field.
2233             * @param  start the lower bound of the range of groups to return
2234             * @param  end the upper bound of the range of groups to return (not
2235             *         inclusive)
2236             * @return the matching groups ordered by name
2237             * @throws SystemException if a system exception occurred
2238             */
2239            public List<Group> search(
2240                            long companyId, long[] classNameIds, String name,
2241                            String description, LinkedHashMap<String, Object> params,
2242                            boolean andOperator, int start, int end)
2243                    throws SystemException {
2244    
2245                    return search(
2246                            companyId, classNameIds, name, description, params, andOperator,
2247                            start, end, null);
2248            }
2249    
2250            /**
2251             * Returns an ordered range of all the groups that match the class name IDs,
2252             * name, and description, optionally including the user's inherited
2253             * organization groups and user groups. System and staged groups are not
2254             * included.
2255             *
2256             * <p>
2257             * Useful when paginating results. Returns a maximum of <code>end -
2258             * start</code> instances. <code>start</code> and <code>end</code> are not
2259             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2260             * refers to the first result in the set. Setting both <code>start</code>
2261             * and <code>end</code> to {@link
2262             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2263             * result set.
2264             * </p>
2265             *
2266             * @param  companyId the primary key of the company
2267             * @param  classNameIds the group's class name IDs (optionally
2268             *         <code>null</code>)
2269             * @param  name the group's name (optionally <code>null</code>)
2270             * @param  description the group's description (optionally
2271             *         <code>null</code>)
2272             * @param  params the finder params (optionally <code>null</code>). To
2273             *         include a user's organizations, inherited organizations, and user
2274             *         groups in the search, add an entry with key
2275             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
2276             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
2277             *         For more information see {@link
2278             *         com.liferay.portal.service.persistence.GroupFinder}
2279             * @param  andOperator whether every field must match its keywords, or just
2280             *         one field.
2281             * @param  start the lower bound of the range of groups to return
2282             * @param  end the upper bound of the range of groups to return (not
2283             *         inclusive)
2284             * @param  obc the comparator to order the groups (optionally
2285             *         <code>null</code>)
2286             * @return the matching groups ordered by comparator <code>obc</code>
2287             * @throws SystemException if a system exception occurred
2288             */
2289            public List<Group> search(
2290                            long companyId, long[] classNameIds, String name,
2291                            String description, LinkedHashMap<String, Object> params,
2292                            boolean andOperator, int start, int end, OrderByComparator obc)
2293                    throws SystemException {
2294    
2295                    if (obc == null) {
2296                            obc = new GroupNameComparator(true);
2297                    }
2298    
2299                    String realName = getRealName(companyId, name);
2300    
2301                    return groupFinder.findByC_C_N_D(
2302                            companyId, classNameIds, name, realName, description, params,
2303                            andOperator, start, end, obc);
2304            }
2305    
2306            /**
2307             * Returns an ordered range of all the groups that match the keywords,
2308             * optionally including the user's inherited organization groups and user
2309             * groups. System and staged groups are not included.
2310             *
2311             * <p>
2312             * Useful when paginating results. Returns a maximum of <code>end -
2313             * start</code> instances. <code>start</code> and <code>end</code> are not
2314             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2315             * refers to the first result in the set. Setting both <code>start</code>
2316             * and <code>end</code> to {@link
2317             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2318             * result set.
2319             * </p>
2320             *
2321             * @param  companyId the primary key of the company
2322             * @param  keywords the keywords (space separated), which may occur in the
2323             *         sites's name, or description (optionally <code>null</code>)
2324             * @param  params the finder params (optionally <code>null</code>). To
2325             *         include the user's inherited organizations and user groups in the
2326             *         search, add entries having &quot;usersGroups&quot; and
2327             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2328             *         information see {@link
2329             *         com.liferay.portal.service.persistence.GroupFinder}
2330             * @param  start the lower bound of the range of groups to return
2331             * @param  end the upper bound of the range of groups to return (not
2332             *         inclusive)
2333             * @return the matching groups ordered by name
2334             * @throws SystemException if a system exception occurred
2335             */
2336            public List<Group> search(
2337                            long companyId, String keywords,
2338                            LinkedHashMap<String, Object> params, int start, int end)
2339                    throws SystemException {
2340    
2341                    return search(companyId, keywords, params, start, end, null);
2342            }
2343    
2344            /**
2345             * Returns an ordered range of all the groups that match the keywords,
2346             * optionally including the user's inherited organization groups and user
2347             * groups. System and staged groups are not included.
2348             *
2349             * <p>
2350             * Useful when paginating results. Returns a maximum of <code>end -
2351             * start</code> instances. <code>start</code> and <code>end</code> are not
2352             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2353             * refers to the first result in the set. Setting both <code>start</code>
2354             * and <code>end</code> to {@link
2355             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2356             * result set.
2357             * </p>
2358             *
2359             * @param  companyId the primary key of the company
2360             * @param  keywords the keywords (space separated), which may occur in the
2361             *         sites's name, or description (optionally <code>null</code>)
2362             * @param  params the finder params (optionally <code>null</code>). To
2363             *         include the user's inherited organizations and user groups in the
2364             *         search, add entries having &quot;usersGroups&quot; and
2365             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2366             *         information see {@link
2367             *         com.liferay.portal.service.persistence.GroupFinder}
2368             * @param  start the lower bound of the range of groups to return
2369             * @param  end the upper bound of the range of groups to return (not
2370             *         inclusive)
2371             * @param  obc the comparator to order the groups (optionally
2372             *         <code>null</code>)
2373             * @return the matching groups ordered by comparator <code>obc</code>
2374             * @throws SystemException if a system exception occurred
2375             */
2376            public List<Group> search(
2377                            long companyId, String keywords,
2378                            LinkedHashMap<String, Object> params, int start, int end,
2379                            OrderByComparator obc)
2380                    throws SystemException {
2381    
2382                    if (obc == null) {
2383                            obc = new GroupNameComparator(true);
2384                    }
2385    
2386                    return groupFinder.findByKeywords(
2387                            companyId, keywords, params, start, end, obc);
2388            }
2389    
2390            /**
2391             * Returns an ordered range of all the site groups and organization groups
2392             * that match the name and description, optionally including the user's
2393             * inherited organization groups and user groups. System and staged groups
2394             * are not included.
2395             *
2396             * <p>
2397             * Useful when paginating results. Returns a maximum of <code>end -
2398             * start</code> instances. <code>start</code> and <code>end</code> are not
2399             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2400             * refers to the first result in the set. Setting both <code>start</code>
2401             * and <code>end</code> to {@link
2402             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2403             * result set.
2404             * </p>
2405             *
2406             * @param  companyId the primary key of the company
2407             * @param  name the group's name (optionally <code>null</code>)
2408             * @param  description the group's description (optionally
2409             *         <code>null</code>)
2410             * @param  params the finder params (optionally <code>null</code>). To
2411             *         include the user's inherited organizations and user groups in the
2412             *         search, add entries having &quot;usersGroups&quot; and
2413             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2414             *         information see {@link
2415             *         com.liferay.portal.service.persistence.GroupFinder}
2416             * @param  andOperator whether every field must match its keywords, or just
2417             *         one field.
2418             * @param  start the lower bound of the range of groups to return
2419             * @param  end the upper bound of the range of groups to return (not
2420             *         inclusive)
2421             * @return the matching groups ordered by name
2422             * @throws SystemException if a system exception occurred
2423             */
2424            public List<Group> search(
2425                            long companyId, String name, String description,
2426                            LinkedHashMap<String, Object> params, boolean andOperator,
2427                            int start, int end)
2428                    throws SystemException {
2429    
2430                    return search(
2431                            companyId, name, description, params, andOperator, start, end,
2432                            null);
2433            }
2434    
2435            /**
2436             * Returns an ordered range of all the site groups and organization groups
2437             * that match the name and description, optionally including the user's
2438             * inherited organization groups and user groups. System and staged groups
2439             * are not included.
2440             *
2441             * <p>
2442             * Useful when paginating results. Returns a maximum of <code>end -
2443             * start</code> instances. <code>start</code> and <code>end</code> are not
2444             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2445             * refers to the first result in the set. Setting both <code>start</code>
2446             * and <code>end</code> to {@link
2447             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2448             * result set.
2449             * </p>
2450             *
2451             * @param  companyId the primary key of the company
2452             * @param  name the group's name (optionally <code>null</code>)
2453             * @param  description the group's description (optionally
2454             *         <code>null</code>)
2455             * @param  params the finder params (optionally <code>null</code>). To
2456             *         include the user's inherited organizations and user groups in the
2457             *         search, add entries having &quot;usersGroups&quot; and
2458             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2459             *         information see {@link
2460             *         com.liferay.portal.service.persistence.GroupFinder}
2461             * @param  andOperator whether every field must match its keywords, or just
2462             *         one field.
2463             * @param  start the lower bound of the range of groups to return
2464             * @param  end the upper bound of the range of groups to return (not
2465             *         inclusive)
2466             * @param  obc the comparator to order the groups (optionally
2467             *         <code>null</code>)
2468             * @return the matching groups ordered by comparator <code>obc</code>
2469             * @throws SystemException if a system exception occurred
2470             */
2471            public List<Group> search(
2472                            long companyId, String name, String description,
2473                            LinkedHashMap<String, Object> params, boolean andOperator,
2474                            int start, int end, OrderByComparator obc)
2475                    throws SystemException {
2476    
2477                    if (obc == null) {
2478                            obc = new GroupNameComparator(true);
2479                    }
2480    
2481                    String realName = getRealName(companyId, name);
2482    
2483                    return groupFinder.findByC_N_D(
2484                            companyId, name, realName, description, params, andOperator, start,
2485                            end, obc);
2486            }
2487    
2488            /**
2489             * Returns the number of groups belonging to the parent group that match the
2490             * keywords, optionally including the user's inherited organization groups
2491             * and user groups. System and staged groups are not included.
2492             *
2493             * @param  companyId the primary key of the company
2494             * @param  parentGroupId the primary key of the parent group
2495             * @param  keywords the keywords (space separated), which may occur in the
2496             *         sites's name, or description (optionally <code>null</code>)
2497             * @param  params the finder params (optionally <code>null</code>). To
2498             *         include the user's inherited organization groups and user groups
2499             *         in the search, add entries having &quot;usersGroups&quot; and
2500             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2501             *         information see {@link
2502             *         com.liferay.portal.service.persistence.GroupFinder}
2503             * @return the number of matching groups
2504             * @throws SystemException if a system exception occurred
2505             */
2506            @ThreadLocalCachable
2507            public int searchCount(
2508                            long companyId, long parentGroupId, String keywords,
2509                            LinkedHashMap<String, Object> params)
2510                    throws SystemException {
2511    
2512                    String parentGroupIdComparator = StringPool.EQUAL;
2513    
2514                    if (parentGroupId == GroupConstants.ANY_PARENT_GROUP_ID) {
2515                            parentGroupIdComparator = StringPool.NOT_EQUAL;
2516                    }
2517    
2518                    return groupFinder.countByKeywords(
2519                            companyId, parentGroupId, parentGroupIdComparator, keywords,
2520                            params);
2521            }
2522    
2523            /**
2524             * Returns the number of groups belonging to the parent group and immediate
2525             * organization groups that match the name and description, optionally
2526             * including the user's inherited organization groups and user groups.
2527             * System and staged groups are not included.
2528             *
2529             * @param  companyId the primary key of the company
2530             * @param  parentGroupId the primary key of the parent group
2531             * @param  name the group's name (optionally <code>null</code>)
2532             * @param  description the group's description (optionally
2533             *         <code>null</code>)
2534             * @param  params the finder params (optionally <code>null</code>). To
2535             *         include the user's inherited organization groups and user groups
2536             *         in the search, add entries having &quot;usersGroups&quot; and
2537             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2538             *         information see {@link
2539             *         com.liferay.portal.service.persistence.GroupFinder}
2540             * @param  andOperator whether every field must match its keywords, or just
2541             *         one field.
2542             * @return the number of matching groups
2543             * @throws SystemException if a system exception occurred
2544             */
2545            @ThreadLocalCachable
2546            public int searchCount(
2547                            long companyId, long parentGroupId, String name, String description,
2548                            LinkedHashMap<String, Object> params, boolean andOperator)
2549                    throws SystemException {
2550    
2551                    String parentGroupIdComparator = StringPool.EQUAL;
2552    
2553                    if (parentGroupId == GroupConstants.ANY_PARENT_GROUP_ID) {
2554                            parentGroupIdComparator = StringPool.NOT_EQUAL;
2555                    }
2556    
2557                    String realName = getRealName(companyId, name);
2558    
2559                    return groupFinder.countByC_PG_N_D(
2560                            companyId, parentGroupId, parentGroupIdComparator, name, realName,
2561                            description, params, andOperator);
2562            }
2563    
2564            /**
2565             * Returns the number of groups belonging to the parent group that match the
2566             * class name IDs, and keywords, optionally including the user's inherited
2567             * organization groups and user groups. System and staged groups are not
2568             * included.
2569             *
2570             * @param  companyId the primary key of the company
2571             * @param  classNameIds the class names of entities to include in the search
2572             *         (optionally <code>null</code>)
2573             * @param  parentGroupId the primary key of the parent group
2574             * @param  keywords the keywords (space separated), which may occur in the
2575             *         sites's name, or description (optionally <code>null</code>)
2576             * @param  params the finder params (optionally <code>null</code>). To
2577             *         include the user's inherited organization groups and user groups
2578             *         in the search, add entries having &quot;usersGroups&quot; and
2579             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2580             *         information see {@link
2581             *         com.liferay.portal.service.persistence.GroupFinder}
2582             * @return the number of matching groups
2583             * @throws SystemException if a system exception occurred
2584             */
2585            @ThreadLocalCachable
2586            public int searchCount(
2587                            long companyId, long[] classNameIds, long parentGroupId,
2588                            String keywords, LinkedHashMap<String, Object> params)
2589                    throws SystemException {
2590    
2591                    String parentGroupIdComparator = StringPool.EQUAL;
2592    
2593                    if (parentGroupId == GroupConstants.ANY_PARENT_GROUP_ID) {
2594                            parentGroupIdComparator = StringPool.NOT_EQUAL;
2595                    }
2596    
2597                    return groupFinder.countByKeywords(
2598                            companyId, classNameIds, parentGroupId, parentGroupIdComparator,
2599                            keywords, params);
2600            }
2601    
2602            /**
2603             * Returns the number of groups belonging to the parent group that match the
2604             * class name IDs, name, and description, optionally including the user's
2605             * inherited organization groups and user groups. System and staged groups
2606             * are not included.
2607             *
2608             * @param  companyId the primary key of the company
2609             * @param  classNameIds the class names of entities to include in the search
2610             *         (optionally <code>null</code>)
2611             * @param  parentGroupId the primary key of the parent group
2612             * @param  name the group's name (optionally <code>null</code>)
2613             * @param  description the group's description (optionally
2614             *         <code>null</code>)
2615             * @param  params the finder params (optionally <code>null</code>). To
2616             *         include the user's inherited organization groups and user groups
2617             *         in the search, add entries having &quot;usersGroups&quot; and
2618             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2619             *         information see {@link
2620             *         com.liferay.portal.service.persistence.GroupFinder}
2621             * @param  andOperator whether every field must match its keywords, or just
2622             *         one field.
2623             * @return the number of matching groups
2624             * @throws SystemException if a system exception occurred
2625             */
2626            @ThreadLocalCachable
2627            public int searchCount(
2628                            long companyId, long[] classNameIds, long parentGroupId,
2629                            String name, String description,
2630                            LinkedHashMap<String, Object> params, boolean andOperator)
2631                    throws SystemException {
2632    
2633                    String parentGroupIdComparator = StringPool.EQUAL;
2634    
2635                    if (parentGroupId == GroupConstants.ANY_PARENT_GROUP_ID) {
2636                            parentGroupIdComparator = StringPool.NOT_EQUAL;
2637                    }
2638    
2639                    String realName = getRealName(companyId, name);
2640    
2641                    return groupFinder.countByC_C_PG_N_D(
2642                            companyId, classNameIds, parentGroupId, parentGroupIdComparator,
2643                            name, realName, description, params, andOperator);
2644            }
2645    
2646            /**
2647             * Returns the number of groups that match the class name IDs, and keywords,
2648             * optionally including the user's inherited organization groups and user
2649             * groups. System and staged groups are not included.
2650             *
2651             * @param  companyId the primary key of the company
2652             * @param  classNameIds the class names of entities to include in the search
2653             *         (optionally <code>null</code>)
2654             * @param  keywords the keywords (space separated), which may occur in the
2655             *         sites's name, or description (optionally <code>null</code>)
2656             * @param  params the finder params (optionally <code>null</code>). To
2657             *         include the user's inherited organization groups and user groups
2658             *         in the search, add entries having &quot;usersGroups&quot; and
2659             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2660             *         information see {@link
2661             *         com.liferay.portal.service.persistence.GroupFinder}
2662             * @return the number of matching groups
2663             * @throws SystemException if a system exception occurred
2664             */
2665            @ThreadLocalCachable
2666            public int searchCount(
2667                            long companyId, long[] classNameIds, String keywords,
2668                            LinkedHashMap<String, Object> params)
2669                    throws SystemException {
2670    
2671                    return groupFinder.countByKeywords(
2672                            companyId, classNameIds, keywords, params);
2673            }
2674    
2675            /**
2676             * Returns the number of groups that match the class name IDs, name, and
2677             * description, optionally including the user's inherited organization
2678             * groups and user groups. System and staged groups are not included.
2679             *
2680             * @param  companyId the primary key of the company
2681             * @param  classNameIds the class names of entities to include in the search
2682             *         (optionally <code>null</code>)
2683             * @param  name the group's name (optionally <code>null</code>)
2684             * @param  description the group's description (optionally
2685             *         <code>null</code>)
2686             * @param  params the finder params (optionally <code>null</code>). To
2687             *         include the user's inherited organization groups and user groups
2688             *         in the search, add entries having &quot;usersGroups&quot; and
2689             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2690             *         information see {@link
2691             *         com.liferay.portal.service.persistence.GroupFinder}
2692             * @param  andOperator whether every field must match its keywords, or just
2693             *         one field.
2694             * @return the number of matching groups
2695             * @throws SystemException if a system exception occurred
2696             */
2697            @ThreadLocalCachable
2698            public int searchCount(
2699                            long companyId, long[] classNameIds, String name,
2700                            String description, LinkedHashMap<String, Object> params,
2701                            boolean andOperator)
2702                    throws SystemException {
2703    
2704                    String realName = getRealName(companyId, name);
2705    
2706                    return groupFinder.countByC_C_N_D(
2707                            companyId, classNameIds, name, realName, description, params,
2708                            andOperator);
2709            }
2710    
2711            /**
2712             * Returns the number of groups that match the keywords, optionally
2713             * including the user's inherited organization groups and user groups.
2714             * System and staged groups are not included.
2715             *
2716             * @param  companyId the primary key of the company
2717             * @param  keywords the keywords (space separated), which may occur in the
2718             *         sites's name, or description (optionally <code>null</code>)
2719             * @param  params the finder params (optionally <code>null</code>). To
2720             *         include the user's inherited organization groups and user groups
2721             *         in the search, add entries having &quot;usersGroups&quot; and
2722             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2723             *         information see {@link
2724             *         com.liferay.portal.service.persistence.GroupFinder}
2725             * @return the number of matching groups
2726             * @throws SystemException if a system exception occurred
2727             */
2728            @ThreadLocalCachable
2729            public int searchCount(
2730                            long companyId, String keywords,
2731                            LinkedHashMap<String, Object> params)
2732                    throws SystemException {
2733    
2734                    return groupFinder.countByKeywords(companyId, keywords, params);
2735            }
2736    
2737            /**
2738             * Returns the number of groups and immediate organization groups that match
2739             * the name and description, optionally including the user's inherited
2740             * organization groups and user groups. System and staged groups are not
2741             * included.
2742             *
2743             * @param  companyId the primary key of the company
2744             * @param  name the group's name (optionally <code>null</code>)
2745             * @param  description the group's description (optionally
2746             *         <code>null</code>)
2747             * @param  params the finder params (optionally <code>null</code>). To
2748             *         include the user's inherited organization groups and user groups
2749             *         in the search, add entries having &quot;usersGroups&quot; and
2750             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2751             *         information see {@link
2752             *         com.liferay.portal.service.persistence.GroupFinder}
2753             * @param  andOperator whether every field must match its keywords, or just
2754             *         one field.
2755             * @return the number of matching groups
2756             * @throws SystemException if a system exception occurred
2757             */
2758            @ThreadLocalCachable
2759            public int searchCount(
2760                            long companyId, String name, String description,
2761                            LinkedHashMap<String, Object> params, boolean andOperator)
2762                    throws SystemException {
2763    
2764                    String realName = getRealName(companyId, name);
2765    
2766                    return groupFinder.countByC_N_D(
2767                            companyId, name, realName, description, params, andOperator);
2768            }
2769    
2770            /**
2771             * Sets the groups associated with the role, removing and adding
2772             * associations as necessary.
2773             *
2774             * @param  roleId the primary key of the role
2775             * @param  groupIds the primary keys of the groups
2776             * @throws SystemException if a system exception occurred
2777             */
2778            public void setRoleGroups(long roleId, long[] groupIds)
2779                    throws SystemException {
2780    
2781                    rolePersistence.setGroups(roleId, groupIds);
2782    
2783                    PermissionCacheUtil.clearCache();
2784            }
2785    
2786            /**
2787             * Removes the groups from the role.
2788             *
2789             * @param  roleId the primary key of the role
2790             * @param  groupIds the primary keys of the groups
2791             * @throws SystemException if a system exception occurred
2792             */
2793            public void unsetRoleGroups(long roleId, long[] groupIds)
2794                    throws SystemException {
2795    
2796                    rolePersistence.removeGroups(roleId, groupIds);
2797    
2798                    PermissionCacheUtil.clearCache();
2799            }
2800    
2801            /**
2802             * Removes the user from the groups.
2803             *
2804             * @param  userId the primary key of the user
2805             * @param  groupIds the primary keys of the groups
2806             * @throws SystemException if a system exception occurred
2807             */
2808            public void unsetUserGroups(long userId, long[] groupIds)
2809                    throws SystemException {
2810    
2811                    userGroupRoleLocalService.deleteUserGroupRoles(userId, groupIds);
2812    
2813                    userPersistence.removeGroups(userId, groupIds);
2814    
2815                    PermissionCacheUtil.clearCache();
2816            }
2817    
2818            /**
2819             * Updates the group's asset replacing categories and tag names.
2820             *
2821             * @param  userId the primary key of the user
2822             * @param  group the group
2823             * @param  assetCategoryIds the primary keys of the asset categories
2824             *         (optionally <code>null</code>)
2825             * @param  assetTagNames the asset tag names (optionally <code>null</code>)
2826             * @throws PortalException if a user with the primary key could not be found
2827             * @throws SystemException if a system exception occurred
2828             */
2829            public void updateAsset(
2830                            long userId, Group group, long[] assetCategoryIds,
2831                            String[] assetTagNames)
2832                    throws PortalException, SystemException {
2833    
2834                    User user = userPersistence.findByPrimaryKey(userId);
2835    
2836                    Company company = companyPersistence.findByPrimaryKey(
2837                            user.getCompanyId());
2838    
2839                    Group companyGroup = company.getGroup();
2840    
2841                    assetEntryLocalService.updateEntry(
2842                            userId, companyGroup.getGroupId(), null, null,
2843                            Group.class.getName(), group.getGroupId(), null, 0,
2844                            assetCategoryIds, assetTagNames, false, null, null, null, null,
2845                            group.getDescriptiveName(), group.getDescription(), null, null,
2846                            null, 0, 0, null, false);
2847            }
2848    
2849            /**
2850             * Updates the group's friendly URL.
2851             *
2852             * @param  groupId the primary key of the group
2853             * @param  friendlyURL the group's new friendlyURL (optionally
2854             *         <code>null</code>)
2855             * @return the group
2856             * @throws PortalException if a group with the primary key could not be
2857             *         found or if a valid friendly URL could not be created for the
2858             *         group
2859             * @throws SystemException if a system exception occurred
2860             */
2861            public Group updateFriendlyURL(long groupId, String friendlyURL)
2862                    throws PortalException, SystemException {
2863    
2864                    Group group = groupPersistence.findByPrimaryKey(groupId);
2865    
2866                    if (group.isUser()) {
2867                            User user = userPersistence.findByPrimaryKey(group.getClassPK());
2868    
2869                            friendlyURL = StringPool.SLASH + user.getScreenName();
2870    
2871                            if (group.getFriendlyURL().equals(friendlyURL)) {
2872                                    return group;
2873                            }
2874                    }
2875    
2876                    friendlyURL = getFriendlyURL(
2877                            group.getCompanyId(), groupId, group.getClassNameId(),
2878                            group.getClassPK(), StringPool.BLANK, friendlyURL);
2879    
2880                    validateFriendlyURL(
2881                            group.getCompanyId(), group.getGroupId(), group.getClassNameId(),
2882                            group.getClassPK(), friendlyURL);
2883    
2884                    group.setFriendlyURL(friendlyURL);
2885    
2886                    groupPersistence.update(group);
2887    
2888                    return group;
2889            }
2890    
2891            /**
2892             * Updates the group.
2893             *
2894             * @param  groupId the primary key of the group
2895             * @param  parentGroupId the primary key of the parent group
2896             * @param  name the group's new name
2897             * @param  description the group's new description (optionally
2898             *         <code>null</code>)
2899             * @param  type the group's new type. For more information see {@link
2900             *         com.liferay.portal.model.GroupConstants}
2901             * @param  friendlyURL the group's new friendlyURL (optionally
2902             *         <code>null</code>)
2903             * @param  active whether the group is active
2904             * @param  serviceContext the service context to be applied (optionally
2905             *         <code>null</code>). Can set asset category IDs and asset tag
2906             *         names for the group.
2907             * @return the group
2908             * @throws PortalException if a group with the primary key could not be
2909             *         found or if the friendly URL was invalid or could one not be
2910             *         created
2911             * @throws SystemException if a system exception occurred
2912             */
2913            public Group updateGroup(
2914                            long groupId, long parentGroupId, String name, String description,
2915                            int type, String friendlyURL, boolean active,
2916                            ServiceContext serviceContext)
2917                    throws PortalException, SystemException {
2918    
2919                    Group group = groupPersistence.findByPrimaryKey(groupId);
2920    
2921                    String className = group.getClassName();
2922                    long classNameId = group.getClassNameId();
2923                    long classPK = group.getClassPK();
2924                    friendlyURL = getFriendlyURL(
2925                            group.getCompanyId(), groupId, classNameId, classPK,
2926                            StringPool.BLANK, friendlyURL);
2927    
2928                    if ((classNameId <= 0) || className.equals(Group.class.getName())) {
2929                            validateName(
2930                                    group.getGroupId(), group.getCompanyId(), name, group.isSite());
2931                    }
2932                    else if (className.equals(Organization.class.getName())) {
2933                            Organization organization =
2934                                    organizationPersistence.findByPrimaryKey(classPK);
2935    
2936                            name = getOrgGroupName(organization.getName());
2937                    }
2938                    else if (!GroupConstants.USER_PERSONAL_SITE.equals(name)) {
2939                            name = String.valueOf(classPK);
2940                    }
2941    
2942                    if (PortalUtil.isSystemGroup(group.getName()) &&
2943                            !name.equals(group.getName())) {
2944    
2945                            throw new RequiredGroupException(
2946                                    String.valueOf(group.getGroupId()),
2947                                    RequiredGroupException.SYSTEM_GROUP);
2948                    }
2949    
2950                    validateFriendlyURL(
2951                            group.getCompanyId(), group.getGroupId(), group.getClassNameId(),
2952                            group.getClassPK(), friendlyURL);
2953    
2954                    group.setParentGroupId(parentGroupId);
2955                    group.setName(name);
2956                    group.setDescription(description);
2957                    group.setType(type);
2958                    group.setFriendlyURL(friendlyURL);
2959                    group.setActive(active);
2960    
2961                    if ((serviceContext != null) && group.isSite()) {
2962                            group.setExpandoBridgeAttributes(serviceContext);
2963                    }
2964    
2965                    groupPersistence.update(group);
2966    
2967                    // Asset
2968    
2969                    if ((serviceContext != null) && group.isSite()) {
2970                            User user = null;
2971    
2972                            try {
2973                                    user = userPersistence.findByPrimaryKey(
2974                                            group.getCreatorUserId());
2975    
2976                            }
2977                            catch (NoSuchUserException nsue1) {
2978                                    try {
2979                                            user = userPersistence.findByPrimaryKey(
2980                                                    serviceContext.getUserId());
2981                                    }
2982                                    catch (NoSuchUserException nsue2) {
2983                                            user = userLocalService.getDefaultUser(
2984                                                    group.getCompanyId());
2985                                    }
2986                            }
2987    
2988                            updateAsset(
2989                                    user.getUserId(), group, serviceContext.getAssetCategoryIds(),
2990                                    serviceContext.getAssetTagNames());
2991                    }
2992    
2993                    return group;
2994            }
2995    
2996            /**
2997             * Updates the group's type settings.
2998             *
2999             * @param  groupId the primary key of the group
3000             * @param  typeSettings the group's new type settings (optionally
3001             *         <code>null</code>)
3002             * @return the group
3003             * @throws PortalException if a group with the primary key could not be
3004             *         found
3005             * @throws SystemException if a system exception occurred
3006             */
3007            public Group updateGroup(long groupId, String typeSettings)
3008                    throws PortalException, SystemException {
3009    
3010                    Group group = groupPersistence.findByPrimaryKey(groupId);
3011    
3012                    group.setTypeSettings(typeSettings);
3013    
3014                    groupPersistence.update(group);
3015    
3016                    return group;
3017            }
3018    
3019            /**
3020             * Associates the group with a main site if the group is an organization.
3021             *
3022             * @param  groupId the primary key of the group
3023             * @param  site whether the group is to be associated with a main site
3024             * @return the group
3025             * @throws PortalException if a group with the primary key could not be
3026             *         found
3027             * @throws SystemException if a system exception occurred
3028             */
3029            public Group updateSite(long groupId, boolean site)
3030                    throws PortalException, SystemException {
3031    
3032                    Group group = groupPersistence.findByPrimaryKey(groupId);
3033    
3034                    if (!group.isOrganization()) {
3035                            return group;
3036                    }
3037    
3038                    group.setSite(site);
3039    
3040                    groupPersistence.update(group);
3041    
3042                    return group;
3043            }
3044    
3045            protected void addControlPanelLayouts(Group group)
3046                    throws PortalException, SystemException {
3047    
3048                    long defaultUserId = userLocalService.getDefaultUserId(
3049                            group.getCompanyId());
3050    
3051                    String friendlyURL = getFriendlyURL(
3052                            PropsValues.CONTROL_PANEL_LAYOUT_FRIENDLY_URL);
3053    
3054                    ServiceContext serviceContext = new ServiceContext();
3055    
3056                    layoutLocalService.addLayout(
3057                            defaultUserId, group.getGroupId(), true,
3058                            LayoutConstants.DEFAULT_PARENT_LAYOUT_ID,
3059                            PropsValues.CONTROL_PANEL_LAYOUT_NAME, StringPool.BLANK,
3060                            StringPool.BLANK, LayoutConstants.TYPE_CONTROL_PANEL, false,
3061                            friendlyURL, serviceContext);
3062            }
3063    
3064            protected void addDefaultGuestPublicLayoutByProperties(Group group)
3065                    throws PortalException, SystemException {
3066    
3067                    long defaultUserId = userLocalService.getDefaultUserId(
3068                            group.getCompanyId());
3069                    String friendlyURL = getFriendlyURL(
3070                            PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_FRIENDLY_URL);
3071    
3072                    ServiceContext serviceContext = new ServiceContext();
3073    
3074                    Layout layout = layoutLocalService.addLayout(
3075                            defaultUserId, group.getGroupId(), false,
3076                            LayoutConstants.DEFAULT_PARENT_LAYOUT_ID,
3077                            PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_NAME, StringPool.BLANK,
3078                            StringPool.BLANK, LayoutConstants.TYPE_PORTLET, false, friendlyURL,
3079                            serviceContext);
3080    
3081                    LayoutTypePortlet layoutTypePortlet =
3082                            (LayoutTypePortlet)layout.getLayoutType();
3083    
3084                    layoutTypePortlet.setLayoutTemplateId(
3085                            0, PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_TEMPLATE_ID, false);
3086    
3087                    for (int i = 0; i < 10; i++) {
3088                            String columnId = "column-" + i;
3089                            String portletIds = PropsUtil.get(
3090                                    PropsKeys.DEFAULT_GUEST_PUBLIC_LAYOUT_COLUMN + i);
3091    
3092                            layoutTypePortlet.addPortletIds(
3093                                    0, StringUtil.split(portletIds), columnId, false);
3094                    }
3095    
3096                    layoutLocalService.updateLayout(
3097                            layout.getGroupId(), layout.isPrivateLayout(), layout.getLayoutId(),
3098                            layout.getTypeSettings());
3099    
3100                    boolean updateLayoutSet = false;
3101    
3102                    LayoutSet layoutSet = layout.getLayoutSet();
3103    
3104                    if (Validator.isNotNull(
3105                                    PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_REGULAR_THEME_ID)) {
3106    
3107                            layoutSet.setThemeId(
3108                                    PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_REGULAR_THEME_ID);
3109    
3110                            updateLayoutSet = true;
3111                    }
3112    
3113                    if (Validator.isNotNull(
3114                                    PropsValues.
3115                                            DEFAULT_GUEST_PUBLIC_LAYOUT_REGULAR_COLOR_SCHEME_ID)) {
3116    
3117                            layoutSet.setColorSchemeId(
3118                                    PropsValues.
3119                                            DEFAULT_GUEST_PUBLIC_LAYOUT_REGULAR_COLOR_SCHEME_ID);
3120    
3121                            updateLayoutSet = true;
3122                    }
3123    
3124                    if (Validator.isNotNull(
3125                                    PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_WAP_THEME_ID)) {
3126    
3127                            layoutSet.setWapThemeId(
3128                                    PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_WAP_THEME_ID);
3129    
3130                            updateLayoutSet = true;
3131                    }
3132    
3133                    if (Validator.isNotNull(
3134                                    PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_WAP_COLOR_SCHEME_ID)) {
3135    
3136                            layoutSet.setWapColorSchemeId(
3137                                    PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_WAP_COLOR_SCHEME_ID);
3138    
3139                            updateLayoutSet = true;
3140                    }
3141    
3142                    if (updateLayoutSet) {
3143                            layoutSetLocalService.updateLayoutSet(layoutSet);
3144                    }
3145            }
3146    
3147            protected void addDefaultGuestPublicLayouts(Group group)
3148                    throws PortalException, SystemException {
3149    
3150                    if (publicLARFile != null) {
3151                            addDefaultGuestPublicLayoutsByLAR(group, publicLARFile);
3152                    }
3153                    else {
3154                            addDefaultGuestPublicLayoutByProperties(group);
3155                    }
3156            }
3157    
3158            protected void addDefaultGuestPublicLayoutsByLAR(Group group, File larFile)
3159                    throws PortalException, SystemException {
3160    
3161                    long defaultUserId = userLocalService.getDefaultUserId(
3162                            group.getCompanyId());
3163    
3164                    Map<String, String[]> parameterMap = new HashMap<String, String[]>();
3165    
3166                    parameterMap.put(
3167                            PortletDataHandlerKeys.CATEGORIES,
3168                            new String[] {Boolean.TRUE.toString()});
3169                    parameterMap.put(
3170                            PortletDataHandlerKeys.PERMISSIONS,
3171                            new String[] {Boolean.TRUE.toString()});
3172                    parameterMap.put(
3173                            PortletDataHandlerKeys.PORTLET_DATA,
3174                            new String[] {Boolean.TRUE.toString()});
3175                    parameterMap.put(
3176                            PortletDataHandlerKeys.PORTLET_DATA_CONTROL_DEFAULT,
3177                            new String[] {Boolean.TRUE.toString()});
3178                    parameterMap.put(
3179                            PortletDataHandlerKeys.PORTLET_SETUP,
3180                            new String[] {Boolean.TRUE.toString()});
3181    
3182                    layoutLocalService.importLayouts(
3183                            defaultUserId, group.getGroupId(), false, parameterMap, larFile);
3184            }
3185    
3186            protected void deletePortletData(Group group)
3187                    throws PortalException, SystemException {
3188    
3189                    List<Portlet> portlets = portletLocalService.getPortlets(
3190                            group.getCompanyId());
3191    
3192                    for (Portlet portlet : portlets) {
3193                            if (!portlet.isActive()) {
3194                                    continue;
3195                            }
3196    
3197                            PortletDataHandler portletDataHandler =
3198                                    portlet.getPortletDataHandlerInstance();
3199    
3200                            if (portletDataHandler == null) {
3201                                    continue;
3202                            }
3203    
3204                            PortletDataContext portletDataContext = new PortletDataContextImpl(
3205                                    group.getCompanyId(), group.getGroupId(), null,
3206                                    new HashSet<String>(), null, null, null);
3207    
3208                            // For now, we are going to throw an exception if one portlet data
3209                            // handler has an exception to ensure that the transaction is
3210                            // rolled back for data integrity. We may decide that this is not
3211                            // the best behavior in the future because a bad plugin could
3212                            // disallow deletion of groups.
3213    
3214                            //try {
3215                                    portletDataHandler.deleteData(
3216                                            portletDataContext, portlet.getPortletId(), null);
3217                            /*}
3218                            catch (Exception e) {
3219                                    _log.error(
3220                                            "Unable to delete data for portlet " +
3221                                                    portlet.getPortletId() + " in group " +
3222                                                            group.getGroupId());
3223                            }*/
3224                    }
3225            }
3226    
3227            protected String getFriendlyURL(
3228                            long companyId, long groupId, long classNameId, long classPK,
3229                            String friendlyName, String friendlyURL)
3230                    throws PortalException, SystemException {
3231    
3232                    friendlyURL = getFriendlyURL(friendlyURL);
3233    
3234                    if (Validator.isNotNull(friendlyURL)) {
3235                            return friendlyURL;
3236                    }
3237    
3238                    friendlyURL = StringPool.SLASH + getFriendlyURL(friendlyName);
3239    
3240                    String originalFriendlyURL = friendlyURL;
3241    
3242                    for (int i = 1;; i++) {
3243                            try {
3244                                    validateFriendlyURL(
3245                                            companyId, groupId, classNameId, classPK, friendlyURL);
3246    
3247                                    break;
3248                            }
3249                            catch (GroupFriendlyURLException gfurle) {
3250                                    int type = gfurle.getType();
3251    
3252                                    if (type == GroupFriendlyURLException.DUPLICATE) {
3253                                            friendlyURL = originalFriendlyURL + i;
3254                                    }
3255                                    else {
3256                                            friendlyURL = StringPool.SLASH + classPK;
3257    
3258                                            break;
3259                                    }
3260                            }
3261                    }
3262    
3263                    return friendlyURL;
3264            }
3265    
3266            protected String getFriendlyURL(String friendlyURL) {
3267                    return FriendlyURLNormalizerUtil.normalize(friendlyURL);
3268            }
3269    
3270            protected String getOrgGroupName(String name) {
3271                    return name + ORGANIZATION_NAME_SUFFIX;
3272            }
3273    
3274            protected String getRealName(long companyId, String name)
3275                    throws SystemException {
3276    
3277                    if (Validator.isNull(name)) {
3278                            return name;
3279                    }
3280    
3281                    String realName = name;
3282    
3283                    try {
3284                            Company company = companyLocalService.getCompany(companyId);
3285    
3286                            Account account = company.getAccount();
3287    
3288                            String companyName = account.getName();
3289    
3290                            name = StringUtil.replace(
3291                                    name, StringPool.PERCENT, StringPool.BLANK);
3292    
3293                            if (companyName.contains(name)) {
3294                                    realName =
3295                                            StringPool.PERCENT + GroupConstants.GUEST +
3296                                                    StringPool.PERCENT;
3297                            }
3298                    }
3299                    catch (PortalException pe) {
3300                    }
3301    
3302                    return realName;
3303            }
3304    
3305            protected void initImportLARFile() {
3306                    String publicLARFileName = PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUTS_LAR;
3307    
3308                    if (_log.isDebugEnabled()) {
3309                            _log.debug("Reading public LAR file " + publicLARFileName);
3310                    }
3311    
3312                    if (Validator.isNotNull(publicLARFileName)) {
3313                            publicLARFile = new File(publicLARFileName);
3314    
3315                            if (!publicLARFile.exists()) {
3316                                    _log.error(
3317                                            "Public LAR file " + publicLARFile + " does not exist");
3318    
3319                                    publicLARFile = null;
3320                            }
3321                            else {
3322                                    if (_log.isDebugEnabled()) {
3323                                            _log.debug("Using public LAR file " + publicLARFileName);
3324                                    }
3325                            }
3326                    }
3327            }
3328    
3329            protected void initUserPersonalSitePermissions(Group group)
3330                    throws PortalException, SystemException {
3331    
3332                    // User role
3333    
3334                    Role role = roleLocalService.getRole(
3335                            group.getCompanyId(), RoleConstants.USER);
3336    
3337                    setCompanyPermissions(
3338                            role, PortletKeys.PORTAL,
3339                            new String[] {ActionKeys.VIEW_CONTROL_PANEL});
3340    
3341                    List<Portlet> portlets = portletLocalService.getPortlets(
3342                            group.getCompanyId(), false, false);
3343    
3344                    for (Portlet portlet : portlets) {
3345                            setRolePermissions(
3346                                    group, role, portlet.getPortletId(),
3347                                    new String[] {ActionKeys.VIEW});
3348                    }
3349    
3350                    setRolePermissions(
3351                            group, role, Layout.class.getName(),
3352                            new String[] {ActionKeys.VIEW});
3353    
3354                    setRolePermissions(
3355                            group, role, "com.liferay.portlet.blogs",
3356                            new String[] {
3357                                    ActionKeys.ADD_ENTRY, ActionKeys.PERMISSIONS,
3358                                    ActionKeys.SUBSCRIBE});
3359    
3360                    setRolePermissions(
3361                            group, role, "com.liferay.portlet.calendar",
3362                            new String[] {
3363                                    ActionKeys.ADD_EVENT, ActionKeys.EXPORT_ALL_EVENTS,
3364                                    ActionKeys.PERMISSIONS});
3365    
3366                    // Power User role
3367    
3368                    role = roleLocalService.getRole(
3369                            group.getCompanyId(), RoleConstants.POWER_USER);
3370    
3371                    for (Portlet portlet : portlets) {
3372                            List<String> actions =
3373                                    ResourceActionsUtil.getPortletResourceActions(
3374                                            portlet.getPortletId());
3375    
3376                            String controlPanelEntryCategory = GetterUtil.getString(
3377                                    portlet.getControlPanelEntryCategory());
3378    
3379                            if (actions.contains(ActionKeys.ACCESS_IN_CONTROL_PANEL) &&
3380                                    controlPanelEntryCategory.equals(PortletCategoryKeys.CONTENT)) {
3381    
3382                                    setRolePermissions(
3383                                            group, role, portlet.getPortletId(),
3384                                            new String[] {ActionKeys.ACCESS_IN_CONTROL_PANEL});
3385                            }
3386                    }
3387    
3388                    setRolePermissions(
3389                            group, role, Group.class.getName(),
3390                            new String[] {ActionKeys.MANAGE_LAYOUTS});
3391    
3392                    setRolePermissions(group, role, "com.liferay.portlet.asset");
3393                    setRolePermissions(group, role, "com.liferay.portlet.blogs");
3394                    setRolePermissions(group, role, "com.liferay.portlet.bookmarks");
3395                    setRolePermissions(group, role, "com.liferay.portlet.calendar");
3396                    setRolePermissions(group, role, "com.liferay.portlet.documentlibrary");
3397                    setRolePermissions(group, role, "com.liferay.portlet.imagegallery");
3398                    setRolePermissions(group, role, "com.liferay.portlet.messageboards");
3399                    setRolePermissions(group, role, "com.liferay.portlet.polls");
3400                    setRolePermissions(group, role, "com.liferay.portlet.wiki");
3401            }
3402    
3403            protected boolean isStaging(ServiceContext serviceContext) {
3404                    if (serviceContext != null) {
3405                            return ParamUtil.getBoolean(serviceContext, "staging");
3406                    }
3407    
3408                    return false;
3409            }
3410    
3411            protected void setCompanyPermissions(
3412                            Role role, String name, String[] actionIds)
3413                    throws PortalException, SystemException {
3414    
3415                    if (resourceBlockLocalService.isSupported(name)) {
3416                            resourceBlockLocalService.setCompanyScopePermissions(
3417                                    role.getCompanyId(), name, role.getRoleId(),
3418                                    Arrays.asList(actionIds));
3419                    }
3420                    else {
3421                            resourcePermissionLocalService.setResourcePermissions(
3422                                    role.getCompanyId(), name, ResourceConstants.SCOPE_COMPANY,
3423                                    String.valueOf(role.getCompanyId()), role.getRoleId(),
3424                                    actionIds);
3425                    }
3426            }
3427    
3428            protected void setRolePermissions(Group group, Role role, String name)
3429                    throws PortalException, SystemException {
3430    
3431                    List<String> actions = ResourceActionsUtil.getModelResourceActions(
3432                            name);
3433    
3434                    setRolePermissions(
3435                            group, role, name, actions.toArray(new String[actions.size()]));
3436            }
3437    
3438            protected void setRolePermissions(
3439                            Group group, Role role, String name, String[] actionIds)
3440                    throws PortalException, SystemException {
3441    
3442                    if (resourceBlockLocalService.isSupported(name)) {
3443                            resourceBlockLocalService.setGroupScopePermissions(
3444                                    role.getCompanyId(), group.getGroupId(), name, role.getRoleId(),
3445                                    Arrays.asList(actionIds));
3446                    }
3447                    else {
3448                            resourcePermissionLocalService.setResourcePermissions(
3449                                    group.getCompanyId(), name, ResourceConstants.SCOPE_GROUP,
3450                                    String.valueOf(group.getGroupId()), role.getRoleId(),
3451                                    actionIds);
3452                    }
3453            }
3454    
3455            protected void unscheduleStaging(Group group) {
3456                    try {
3457    
3458                            // Remote publishing
3459    
3460                            String groupName = StagingUtil.getSchedulerGroupName(
3461                                    DestinationNames.LAYOUTS_REMOTE_PUBLISHER, group.getGroupId());
3462    
3463                            SchedulerEngineHelperUtil.delete(groupName, StorageType.PERSISTED);
3464    
3465                            long liveGroupId = 0;
3466                            long stagingGroupId = 0;
3467    
3468                            if (group.isStagingGroup()) {
3469                                    liveGroupId = group.getLiveGroupId();
3470    
3471                                    stagingGroupId = group.getGroupId();
3472                            }
3473                            else if (group.hasStagingGroup()) {
3474                                    liveGroupId = group.getGroupId();
3475    
3476                                    stagingGroupId = group.getStagingGroup().getGroupId();
3477                            }
3478    
3479                            if ((liveGroupId != 0) && (stagingGroupId != 0)) {
3480    
3481                                    // Publish to live
3482    
3483                                    groupName = StagingUtil.getSchedulerGroupName(
3484                                            DestinationNames.LAYOUTS_LOCAL_PUBLISHER, liveGroupId);
3485    
3486                                    SchedulerEngineHelperUtil.delete(
3487                                            groupName, StorageType.PERSISTED);
3488    
3489                                    // Copy from live
3490    
3491                                    groupName = StagingUtil.getSchedulerGroupName(
3492                                            DestinationNames.LAYOUTS_LOCAL_PUBLISHER, stagingGroupId);
3493    
3494                                    SchedulerEngineHelperUtil.delete(
3495                                            groupName, StorageType.PERSISTED);
3496                            }
3497                    }
3498                    catch (Exception e) {
3499                            _log.error(
3500                                    "Unable to unschedule events for group: " + group.getGroupId());
3501                    }
3502            }
3503    
3504            protected void validateFriendlyURL(
3505                            long companyId, long groupId, long classNameId, long classPK,
3506                            String friendlyURL)
3507                    throws PortalException, SystemException {
3508    
3509                    Company company = companyPersistence.findByPrimaryKey(companyId);
3510    
3511                    if (company.isSystem()) {
3512                            return;
3513                    }
3514    
3515                    if (Validator.isNull(friendlyURL)) {
3516                            return;
3517                    }
3518    
3519                    int exceptionType = LayoutImpl.validateFriendlyURL(friendlyURL);
3520    
3521                    if (exceptionType != -1) {
3522                            throw new GroupFriendlyURLException(exceptionType);
3523                    }
3524    
3525                    Group group = groupPersistence.fetchByC_F(companyId, friendlyURL);
3526    
3527                    if ((group != null) && (group.getGroupId() != groupId)) {
3528                            throw new GroupFriendlyURLException(
3529                                    GroupFriendlyURLException.DUPLICATE);
3530                    }
3531    
3532                    String groupIdFriendlyURL = friendlyURL.substring(1);
3533    
3534                    if (Validator.isNumber(groupIdFriendlyURL)) {
3535                            long groupClassNameId = PortalUtil.getClassNameId(Group.class);
3536    
3537                            if (((classNameId != groupClassNameId) &&
3538                                     !groupIdFriendlyURL.equals(String.valueOf(classPK)) &&
3539                                     !PropsValues.USERS_SCREEN_NAME_ALLOW_NUMERIC) ||
3540                                    ((classNameId == groupClassNameId) &&
3541                                     !groupIdFriendlyURL.equals(String.valueOf(groupId)))) {
3542    
3543                                    GroupFriendlyURLException gfurle =
3544                                            new GroupFriendlyURLException(
3545                                                    GroupFriendlyURLException.POSSIBLE_DUPLICATE);
3546    
3547                                    gfurle.setKeywordConflict(groupIdFriendlyURL);
3548    
3549                                    throw gfurle;
3550                            }
3551                    }
3552    
3553                    String screenName = friendlyURL.substring(1);
3554    
3555                    User user = userPersistence.fetchByC_SN(companyId, screenName);
3556    
3557                    if (user != null) {
3558                            long userClassNameId = PortalUtil.getClassNameId(User.class);
3559    
3560                            if ((classNameId == userClassNameId) &&
3561                                    (classPK == user.getUserId())) {
3562                            }
3563                            else {
3564                                    throw new GroupFriendlyURLException(
3565                                            GroupFriendlyURLException.DUPLICATE);
3566                            }
3567                    }
3568    
3569                    if (StringUtil.count(friendlyURL, StringPool.SLASH) > 1) {
3570                            throw new GroupFriendlyURLException(
3571                                    GroupFriendlyURLException.TOO_DEEP);
3572                    }
3573            }
3574    
3575            protected void validateName(
3576                            long groupId, long companyId, String name, boolean site)
3577                    throws PortalException, SystemException {
3578    
3579                    if (Validator.isNull(name) || Validator.isNumber(name) ||
3580                            name.contains(StringPool.STAR) ||
3581                            name.contains(ORGANIZATION_NAME_SUFFIX)) {
3582    
3583                            throw new GroupNameException();
3584                    }
3585    
3586                    try {
3587                            Group group = groupFinder.findByC_N(companyId, name);
3588    
3589                            if ((groupId <= 0) || (group.getGroupId() != groupId)) {
3590                                    throw new DuplicateGroupException();
3591                            }
3592                    }
3593                    catch (NoSuchGroupException nsge) {
3594                    }
3595    
3596                    if (site) {
3597                            Company company = companyLocalService.getCompany(companyId);
3598    
3599                            if (name.equals(company.getName())) {
3600                                    throw new DuplicateGroupException();
3601                            }
3602                    }
3603            }
3604    
3605            protected File publicLARFile;
3606    
3607            private static Log _log = LogFactoryUtil.getLog(
3608                    GroupLocalServiceImpl.class);
3609    
3610            private Map<String, Group> _systemGroupsMap = new HashMap<String, Group>();
3611    
3612    }