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