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