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