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