001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
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 all the active or inactive groups associated with the company.
1088            *
1089            * @param  companyId the primary key of the company
1090            * @param  active whether to return only active groups, or only inactive
1091            *         groups
1092            * @return the active or inactive groups associated with the company
1093            * @throws SystemException if a system exception occurred
1094            */
1095            @Override
1096            public List<Group> getActiveGroups(long companyId, boolean active)
1097                    throws SystemException {
1098    
1099                    return groupPersistence.findByC_A(companyId, active);
1100            }
1101    
1102            /**
1103             * Returns the company group.
1104             *
1105             * @param  companyId the primary key of the company
1106             * @return the group associated with the company
1107             * @throws PortalException if a matching group could not be found
1108             * @throws SystemException if a system exception occurred
1109             */
1110            @Override
1111            public Group getCompanyGroup(long companyId)
1112                    throws PortalException, SystemException {
1113    
1114                    long classNameId = PortalUtil.getClassNameId(Company.class);
1115    
1116                    return groupPersistence.findByC_C_C(companyId, classNameId, companyId);
1117            }
1118    
1119            /**
1120             * Returns a range of all the groups associated with the company.
1121             *
1122             * <p>
1123             * Useful when paginating results. Returns a maximum of <code>end -
1124             * start</code> instances. <code>start</code> and <code>end</code> are not
1125             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1126             * refers to the first result in the set. Setting both <code>start</code>
1127             * and <code>end</code> to {@link
1128             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1129             * result set.
1130             * </p>
1131             *
1132             * @param  companyId the primary key of the company
1133             * @param  start the lower bound of the range of groups to return
1134             * @param  end the upper bound of the range of groups to return (not
1135             *         inclusive)
1136             * @return the range of groups associated with the company
1137             * @throws SystemException if a system exception occurred
1138             */
1139            @Override
1140            public List<Group> getCompanyGroups(long companyId, int start, int end)
1141                    throws SystemException {
1142    
1143                    return groupPersistence.findByCompanyId(companyId, start, end);
1144            }
1145    
1146            /**
1147             * Returns the number of groups associated with the company.
1148             *
1149             * @param  companyId the primary key of the company
1150             * @return the number of groups associated with the company
1151             * @throws SystemException if a system exception occurred
1152             */
1153            @Override
1154            public int getCompanyGroupsCount(long companyId) throws SystemException {
1155                    return groupPersistence.countByCompanyId(companyId);
1156            }
1157    
1158            /**
1159             * Returns the group with the matching friendly URL.
1160             *
1161             * @param  companyId the primary key of the company
1162             * @param  friendlyURL the group's friendlyURL
1163             * @return the group with the friendly URL
1164             * @throws PortalException if a matching group could not be found, or if the
1165             *         friendly URL was invalid
1166             * @throws SystemException if a system exception occurred
1167             */
1168            @Override
1169            public Group getFriendlyURLGroup(long companyId, String friendlyURL)
1170                    throws PortalException, SystemException {
1171    
1172                    if (Validator.isNull(friendlyURL)) {
1173                            StringBundler sb = new StringBundler(5);
1174    
1175                            sb.append("{companyId=");
1176                            sb.append(companyId);
1177                            sb.append(", friendlyURL=");
1178                            sb.append(friendlyURL);
1179                            sb.append("}");
1180    
1181                            throw new NoSuchGroupException(sb.toString());
1182                    }
1183    
1184                    friendlyURL = getFriendlyURL(friendlyURL);
1185    
1186                    return groupPersistence.findByC_F(companyId, friendlyURL);
1187            }
1188    
1189            /**
1190             * Returns the group with the matching primary key.
1191             *
1192             * @param  groupId the primary key of the group
1193             * @return the group with the primary key
1194             * @throws PortalException if a group with the primary key could not be
1195             *         found
1196             * @throws SystemException if a system exception occurred
1197             */
1198            @Override
1199            @ThreadLocalCachable
1200            public Group getGroup(long groupId)
1201                    throws PortalException, SystemException {
1202    
1203                    return groupPersistence.findByPrimaryKey(groupId);
1204            }
1205    
1206            /**
1207             * Returns the group with the matching group name.
1208             *
1209             * @param  companyId the primary key of the company
1210             * @param  name the group's name
1211             * @return the group with the name
1212             * @throws PortalException if a matching group could not be found
1213             * @throws SystemException if a system exception occurred
1214             */
1215            @Override
1216            @Skip
1217            public Group getGroup(long companyId, String name)
1218                    throws PortalException, SystemException {
1219    
1220                    Group group = _systemGroupsMap.get(
1221                            StringUtil.toHexString(companyId).concat(name));
1222    
1223                    if (group != null) {
1224                            return group;
1225                    }
1226    
1227                    return groupLocalService.loadGetGroup(companyId, name);
1228            }
1229    
1230            @Override
1231            public String getGroupDescriptiveName(Group group, Locale locale)
1232                    throws PortalException, SystemException {
1233    
1234                    String name = group.getName();
1235    
1236                    if (group.isCompany() && !group.isCompanyStagingGroup()) {
1237                            name = LanguageUtil.get(locale, "global");
1238                    }
1239                    else if (group.isControlPanel()) {
1240                            name = LanguageUtil.get(locale, "control-panel");
1241                    }
1242                    else if (group.isLayout()) {
1243                            Layout layout = layoutLocalService.getLayout(group.getClassPK());
1244    
1245                            name = layout.getName(locale);
1246                    }
1247                    else if (group.isLayoutPrototype()) {
1248                            LayoutPrototype layoutPrototype =
1249                                    layoutPrototypeLocalService.getLayoutPrototype(
1250                                            group.getClassPK());
1251    
1252                            name = layoutPrototype.getName(locale);
1253                    }
1254                    else if (group.isLayoutSetPrototype()) {
1255                            LayoutSetPrototype layoutSetPrototype =
1256                                    layoutSetPrototypePersistence.findByPrimaryKey(
1257                                            group.getClassPK());
1258    
1259                            name = layoutSetPrototype.getName(locale);
1260                    }
1261                    else if (group.isOrganization()) {
1262                            long organizationId = group.getOrganizationId();
1263    
1264                            Organization organization =
1265                                    organizationPersistence.findByPrimaryKey(organizationId);
1266    
1267                            name = organization.getName();
1268    
1269                            group = organization.getGroup();
1270                    }
1271                    else if (group.isUser()) {
1272                            long userId = group.getClassPK();
1273    
1274                            User user = userPersistence.findByPrimaryKey(userId);
1275    
1276                            name = user.getFullName();
1277                    }
1278                    else if (group.isUserGroup()) {
1279                            long userGroupId = group.getClassPK();
1280    
1281                            UserGroup userGroup = userGroupPersistence.findByPrimaryKey(
1282                                    userGroupId);
1283    
1284                            name = userGroup.getName();
1285                    }
1286                    else if (group.isUserPersonalSite()) {
1287                            name = LanguageUtil.get(locale, "user-personal-site");
1288                    }
1289                    else if (name.equals(GroupConstants.GUEST)) {
1290                            Company company = companyPersistence.findByPrimaryKey(
1291                                    group.getCompanyId());
1292    
1293                            Account account = company.getAccount();
1294    
1295                            name = account.getName();
1296                    }
1297    
1298                    if (group.isStaged() && !group.isStagedRemotely() &&
1299                            group.isStagingGroup()) {
1300    
1301                            Group liveGroup = group.getLiveGroup();
1302    
1303                            name = liveGroup.getDescriptiveName(locale);
1304                    }
1305    
1306                    return name;
1307            }
1308    
1309            @Override
1310            public String getGroupDescriptiveName(long groupId, Locale locale)
1311                    throws PortalException, SystemException {
1312    
1313                    Group group = groupPersistence.findByPrimaryKey(groupId);
1314    
1315                    return getGroupDescriptiveName(group, locale);
1316            }
1317    
1318            /**
1319             * Returns all the groups that are direct children of the parent group.
1320             *
1321             * @param  companyId the primary key of the company
1322             * @param  parentGroupId the primary key of the parent group
1323             * @param  site whether the group is to be associated with a main site
1324             * @return the matching groups, or <code>null</code> if no matches were
1325             *         found
1326             * @throws SystemException if a system exception occurred
1327             */
1328            @Override
1329            public List<Group> getGroups(
1330                            long companyId, long parentGroupId, boolean site)
1331                    throws SystemException {
1332    
1333                    if (parentGroupId == GroupConstants.ANY_PARENT_GROUP_ID) {
1334                            return groupPersistence.findByC_S(companyId, site);
1335                    }
1336    
1337                    return groupPersistence.findByC_P_S(companyId, parentGroupId, site);
1338            }
1339    
1340            /**
1341             * Returns all the groups that are direct children of the parent group with
1342             * the matching className.
1343             *
1344             * @param  companyId the primary key of the company
1345             * @param  className the class name of the group
1346             * @param  parentGroupId the primary key of the parent group
1347             * @return the matching groups, or <code>null</code> if no matches were
1348             *         found
1349             * @throws SystemException if a system exception occurred
1350             */
1351            @Override
1352            public List<Group> getGroups(
1353                            long companyId, String className, long parentGroupId)
1354                    throws SystemException {
1355    
1356                    long classNameId = PortalUtil.getClassNameId(className);
1357    
1358                    return groupPersistence.findByC_C_P(
1359                            companyId, classNameId, parentGroupId);
1360            }
1361    
1362            /**
1363             * Returns a range of all the groups that are direct children of the parent
1364             * group with the matching className.
1365             *
1366             * @param  companyId the primary key of the company
1367             * @param  className the class name of the group
1368             * @param  parentGroupId the primary key of the parent group
1369             * @param  start the lower bound of the range of results
1370             * @param  end the upper bound of the range of results (not inclusive)
1371             * @return the range of matching groups
1372             * @throws SystemException if a system exception occurred
1373             */
1374            @Override
1375            public List<Group> getGroups(
1376                            long companyId, String className, long parentGroupId, int start,
1377                            int end)
1378                    throws SystemException {
1379    
1380                    long classNameId = PortalUtil.getClassNameId(className);
1381    
1382                    return groupPersistence.findByC_C_P(
1383                            companyId, classNameId, parentGroupId, start, end);
1384            }
1385    
1386            /**
1387             * Returns the groups with the matching primary keys.
1388             *
1389             * @param  groupIds the primary keys of the groups
1390             * @return the groups with the primary keys
1391             * @throws PortalException if any one of the groups could not be found
1392             * @throws SystemException if a system exception occurred
1393             */
1394            @Override
1395            public List<Group> getGroups(long[] groupIds)
1396                    throws PortalException, SystemException {
1397    
1398                    List<Group> groups = new ArrayList<Group>(groupIds.length);
1399    
1400                    for (long groupId : groupIds) {
1401                            Group group = getGroup(groupId);
1402    
1403                            groups.add(group);
1404                    }
1405    
1406                    return groups;
1407            }
1408    
1409            /**
1410             * Returns the number of groups that are direct children of the parent
1411             * group.
1412             *
1413             * @param  companyId the primary key of the company
1414             * @param  parentGroupId the primary key of the parent group
1415             * @param  site whether the group is to be associated with a main site
1416             * @return the number of matching groups
1417             * @throws SystemException if a system exception occurred
1418             */
1419            @Override
1420            public int getGroupsCount(long companyId, long parentGroupId, boolean site)
1421                    throws SystemException {
1422    
1423                    if (parentGroupId == GroupConstants.ANY_PARENT_GROUP_ID) {
1424                            return groupPersistence.countByC_S(companyId, site);
1425                    }
1426    
1427                    return groupPersistence.countByC_P_S(companyId, parentGroupId, site);
1428            }
1429    
1430            /**
1431             * Returns the number of groups that are direct children of the parent group
1432             * with the matching className.
1433             *
1434             * @param  companyId the primary key of the company
1435             * @param  className the class name of the group
1436             * @param  parentGroupId the primary key of the parent group
1437             * @return the number of matching groups
1438             * @throws SystemException if a system exception occurred
1439             */
1440            @Override
1441            public int getGroupsCount(
1442                            long companyId, String className, long parentGroupId)
1443                    throws SystemException {
1444    
1445                    long classNameId = PortalUtil.getClassNameId(className);
1446    
1447                    return groupPersistence.countByC_C_P(
1448                            companyId, classNameId, parentGroupId);
1449            }
1450    
1451            /**
1452             * Returns the group associated with the layout.
1453             *
1454             * @param  companyId the primary key of the company
1455             * @param  plid the primary key of the layout
1456             * @return the group associated with the layout
1457             * @throws PortalException if a matching group could not be found
1458             * @throws SystemException if a system exception occurred
1459             */
1460            @Override
1461            public Group getLayoutGroup(long companyId, long plid)
1462                    throws PortalException, SystemException {
1463    
1464                    long classNameId = PortalUtil.getClassNameId(Layout.class);
1465    
1466                    return groupPersistence.findByC_C_C(companyId, classNameId, plid);
1467            }
1468    
1469            /**
1470             * Returns the group associated with the layout prototype.
1471             *
1472             * @param  companyId the primary key of the company
1473             * @param  layoutPrototypeId the primary key of the layout prototype
1474             * @return the group associated with the layout prototype
1475             * @throws PortalException if a matching group could not be found
1476             * @throws SystemException if a system exception occurred
1477             */
1478            @Override
1479            public Group getLayoutPrototypeGroup(long companyId, long layoutPrototypeId)
1480                    throws PortalException, SystemException {
1481    
1482                    long classNameId = PortalUtil.getClassNameId(LayoutPrototype.class);
1483    
1484                    return groupPersistence.findByC_C_C(
1485                            companyId, classNameId, layoutPrototypeId);
1486            }
1487    
1488            /**
1489             * Returns the group associated with the layout set prototype.
1490             *
1491             * @param  companyId the primary key of the company
1492             * @param  layoutSetPrototypeId the primary key of the layout set prototype
1493             * @return the group associated with the layout set prototype
1494             * @throws PortalException if a matching group could not be found
1495             * @throws SystemException if a system exception occurred
1496             */
1497            @Override
1498            public Group getLayoutSetPrototypeGroup(
1499                            long companyId, long layoutSetPrototypeId)
1500                    throws PortalException, SystemException {
1501    
1502                    long classNameId = PortalUtil.getClassNameId(LayoutSetPrototype.class);
1503    
1504                    return groupPersistence.findByC_C_C(
1505                            companyId, classNameId, layoutSetPrototypeId);
1506            }
1507    
1508            /**
1509             * Returns a range of all groups that are children of the parent group and
1510             * that have at least one layout.
1511             *
1512             * <p>
1513             * Useful when paginating results. Returns a maximum of <code>end -
1514             * start</code> instances. <code>start</code> and <code>end</code> are not
1515             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1516             * refers to the first result in the set. Setting both <code>start</code>
1517             * and <code>end</code> to {@link
1518             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1519             * result set.
1520             * </p>
1521             *
1522             * @param      companyId the primary key of the company
1523             * @param      parentGroupId the primary key of the parent group
1524             * @param      site whether the group is to be associated with a main site
1525             * @param      start the lower bound of the range of groups to return
1526             * @param      end the upper bound of the range of groups to return (not
1527             *             inclusive)
1528             * @return     the range of matching groups
1529             * @throws     SystemException if a system exception occurred
1530             * @deprecated As of 6.2.0, replaced by {@link #getLayoutsGroups(long, long,
1531             *             boolean, int, int, OrderByComparator)}
1532             */
1533            @Deprecated
1534            @Override
1535            public List<Group> getLayoutsGroups(
1536                            long companyId, long parentGroupId, boolean site, int start,
1537                            int end)
1538                    throws SystemException {
1539    
1540                    return getLayoutsGroups(
1541                            companyId, parentGroupId, site, start, end, null);
1542            }
1543    
1544            /**
1545             * Returns a range of all groups that are children of the parent group and
1546             * that have at least one layout.
1547             *
1548             * <p>
1549             * Useful when paginating results. Returns a maximum of <code>end -
1550             * start</code> instances. <code>start</code> and <code>end</code> are not
1551             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1552             * refers to the first result in the set. Setting both <code>start</code>
1553             * and <code>end</code> to {@link
1554             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1555             * result set.
1556             * </p>
1557             *
1558             * @param  companyId the primary key of the company
1559             * @param  parentGroupId the primary key of the parent group
1560             * @param  site whether the group is to be associated with a main site
1561             * @param  start the lower bound of the range of groups to return
1562             * @param  end the upper bound of the range of groups to return (not
1563             *         inclusive)
1564             * @param  obc the comparator to order the groups (optionally
1565             *         <code>null</code>)
1566             * @return the range of matching groups ordered by comparator
1567             *         <code>obc</code>
1568             * @throws SystemException if a system exception occurred
1569             */
1570            @Override
1571            public List<Group> getLayoutsGroups(
1572                            long companyId, long parentGroupId, boolean site, int start,
1573                            int end, OrderByComparator obc)
1574                    throws SystemException {
1575    
1576                    return groupFinder.findByLayouts(
1577                            companyId, parentGroupId, site, start, end, obc);
1578            }
1579    
1580            /**
1581             * Returns the number of groups that are children or the parent group and
1582             * that have at least one layout
1583             *
1584             * @param  companyId the primary key of the company
1585             * @param  parentGroupId the primary key of the parent group
1586             * @param  site whether the group is to be associated with a main site
1587             * @return the number of matching groups
1588             * @throws SystemException if a system exception occurred
1589             */
1590            @Override
1591            public int getLayoutsGroupsCount(
1592                            long companyId, long parentGroupId, boolean site)
1593                    throws SystemException {
1594    
1595                    return groupFinder.countByLayouts(companyId, parentGroupId, site);
1596            }
1597    
1598            /**
1599             * Returns all live groups.
1600             *
1601             * @return all live groups
1602             * @throws SystemException if a system exception occurred
1603             */
1604            @Override
1605            public List<Group> getLiveGroups() throws SystemException {
1606                    return groupFinder.findByLiveGroups();
1607            }
1608    
1609            /**
1610             * Returns a range of all non-system groups of a specified type (className)
1611             * that have no layouts.
1612             *
1613             * <p>
1614             * Useful when paginating results. Returns a maximum of <code>end -
1615             * start</code> instances. <code>start</code> and <code>end</code> are not
1616             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1617             * refers to the first result in the set. Setting both <code>start</code>
1618             * and <code>end</code> to {@link
1619             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1620             * result set.
1621             * </p>
1622             *
1623             * @param  className the entity's class name
1624             * @param  privateLayout whether to include groups with private layout sets
1625             *         or non-private layout sets
1626             * @param  start the lower bound of the range of groups to return
1627             * @param  end the upper bound of the range of groups to return (not
1628             *         inclusive)
1629             * @return the range of matching groups
1630             * @throws SystemException if a system exception occurred
1631             */
1632            @Override
1633            public List<Group> getNoLayoutsGroups(
1634                            String className, boolean privateLayout, int start, int end)
1635                    throws SystemException {
1636    
1637                    long classNameId = PortalUtil.getClassNameId(className);
1638    
1639                    return groupFinder.findByNoLayouts(
1640                            classNameId, privateLayout, start, end);
1641            }
1642    
1643            /**
1644             * Returns all non-system groups having <code>null</code> or empty friendly
1645             * URLs.
1646             *
1647             * @return the non-system groups having <code>null</code> or empty friendly
1648             *         URLs
1649             * @throws SystemException if a system exception occurred
1650             */
1651            @Override
1652            public List<Group> getNullFriendlyURLGroups() throws SystemException {
1653                    return groupFinder.findByNullFriendlyURL();
1654            }
1655    
1656            /**
1657             * Returns the specified organization group.
1658             *
1659             * @param  companyId the primary key of the company
1660             * @param  organizationId the primary key of the organization
1661             * @return the group associated with the organization
1662             * @throws PortalException if a matching group could not be found
1663             * @throws SystemException if a system exception occurred
1664             */
1665            @Override
1666            public Group getOrganizationGroup(long companyId, long organizationId)
1667                    throws PortalException, SystemException {
1668    
1669                    long classNameId = PortalUtil.getClassNameId(Organization.class);
1670    
1671                    return groupPersistence.findByC_C_C(
1672                            companyId, classNameId, organizationId);
1673            }
1674    
1675            /**
1676             * Returns the specified organization groups.
1677             *
1678             * @param  organizations the organizations
1679             * @return the groups associated with the organizations
1680             */
1681            @Override
1682            public List<Group> getOrganizationsGroups(
1683                    List<Organization> organizations) {
1684    
1685                    List<Group> organizationGroups = new ArrayList<Group>();
1686    
1687                    for (int i = 0; i < organizations.size(); i++) {
1688                            Organization organization = organizations.get(i);
1689    
1690                            Group group = organization.getGroup();
1691    
1692                            organizationGroups.add(group);
1693                    }
1694    
1695                    return organizationGroups;
1696            }
1697    
1698            /**
1699             * Returns all the groups related to the organizations.
1700             *
1701             * @param  organizations the organizations
1702             * @return the groups related to the organizations
1703             * @throws SystemException if a system exception occurred
1704             */
1705            @Override
1706            public List<Group> getOrganizationsRelatedGroups(
1707                            List<Organization> organizations)
1708                    throws SystemException {
1709    
1710                    List<Group> organizationGroups = new ArrayList<Group>();
1711    
1712                    for (int i = 0; i < organizations.size(); i++) {
1713                            Organization organization = organizations.get(i);
1714    
1715                            List<Group> groups = organizationPersistence.getGroups(
1716                                    organization.getOrganizationId());
1717    
1718                            organizationGroups.addAll(groups);
1719                    }
1720    
1721                    return organizationGroups;
1722            }
1723    
1724            /**
1725             * Returns the group followed by all its parent groups ordered by closest
1726             * ancestor.
1727             *
1728             * @param  groupId the primary key of the group
1729             * @return the group followed by all its parent groups ordered by closest
1730             *         ancestor
1731             * @throws PortalException if a group with the primary key could not be
1732             *         found
1733             * @throws SystemException if a system exception occurred
1734             */
1735            @Override
1736            public List<Group> getParentGroups(long groupId)
1737                    throws PortalException, SystemException {
1738    
1739                    if (groupId == GroupConstants.DEFAULT_PARENT_GROUP_ID) {
1740                            return new ArrayList<Group>();
1741                    }
1742    
1743                    Group group = groupPersistence.findByPrimaryKey(groupId);
1744    
1745                    return group.getAncestors();
1746            }
1747    
1748            /**
1749             * Returns the staging group.
1750             *
1751             * @param  liveGroupId the primary key of the live group
1752             * @return the staging group
1753             * @throws PortalException if a matching staging group could not be found
1754             * @throws SystemException if a system exception occurred
1755             */
1756            @Override
1757            public Group getStagingGroup(long liveGroupId)
1758                    throws PortalException, SystemException {
1759    
1760                    return groupPersistence.findByLiveGroupId(liveGroupId);
1761            }
1762    
1763            /**
1764             * Returns the group associated with the user.
1765             *
1766             * @param  companyId the primary key of the company
1767             * @param  userId the primary key of the user
1768             * @return the group associated with the user
1769             * @throws PortalException if a matching group could not be found
1770             * @throws SystemException if a system exception occurred
1771             */
1772            @Override
1773            public Group getUserGroup(long companyId, long userId)
1774                    throws PortalException, SystemException {
1775    
1776                    long classNameId = PortalUtil.getClassNameId(User.class);
1777    
1778                    return groupPersistence.findByC_C_C(companyId, classNameId, userId);
1779            }
1780    
1781            /**
1782             * Returns the specified "user group" group. That is, the group that
1783             * represents the {@link com.liferay.portal.model.UserGroup} entity.
1784             *
1785             * @param  companyId the primary key of the company
1786             * @param  userGroupId the primary key of the user group
1787             * @return the group associated with the user group
1788             * @throws PortalException if a matching group could not be found
1789             * @throws SystemException if a system exception occurred
1790             */
1791            @Override
1792            public Group getUserGroupGroup(long companyId, long userGroupId)
1793                    throws PortalException, SystemException {
1794    
1795                    long classNameId = PortalUtil.getClassNameId(UserGroup.class);
1796    
1797                    return groupPersistence.findByC_C_C(
1798                            companyId, classNameId, userGroupId);
1799            }
1800    
1801            /**
1802             * Returns all the user's site groups and immediate organization groups,
1803             * optionally including the user's inherited organization groups and user
1804             * groups. System and staged groups are not included.
1805             *
1806             * @param  userId the primary key of the user
1807             * @param  inherit whether to include the user's inherited organization
1808             *         groups and user groups
1809             * @return the user's groups and immediate organization groups
1810             * @throws PortalException if a user with the primary key could not be found
1811             * @throws SystemException if a system exception occurred
1812             */
1813            @Override
1814            public List<Group> getUserGroups(long userId, boolean inherit)
1815                    throws PortalException, SystemException {
1816    
1817                    return getUserGroups(
1818                            userId, inherit, QueryUtil.ALL_POS, QueryUtil.ALL_POS);
1819            }
1820    
1821            /**
1822             * Returns an ordered range of all the user's site groups and immediate
1823             * organization groups, optionally including the user's inherited
1824             * organization groups and user groups. System and staged groups are not
1825             * included.
1826             *
1827             * <p>
1828             * Useful when paginating results. Returns a maximum of <code>end -
1829             * start</code> instances. <code>start</code> and <code>end</code> are not
1830             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1831             * refers to the first result in the set. Setting both <code>start</code>
1832             * and <code>end</code> to {@link
1833             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1834             * result set.
1835             * </p>
1836             *
1837             * @param  userId the primary key of the user
1838             * @param  inherit whether to include the user's inherited organization
1839             *         groups and user groups
1840             * @param  start the lower bound of the range of groups to return
1841             * @param  end the upper bound of the range of groups to return (not
1842             *         inclusive)
1843             * @return the range of the user's groups and immediate organization groups
1844             *         ordered by name
1845             * @throws PortalException if a user with the primary key could not be found
1846             * @throws SystemException if a system exception occurred
1847             */
1848            @Override
1849            public List<Group> getUserGroups(
1850                            long userId, boolean inherit, int start, int end)
1851                    throws PortalException, SystemException {
1852    
1853                    if (inherit) {
1854                            User user = userPersistence.findByPrimaryKey(userId);
1855    
1856                            LinkedHashMap<String, Object> groupParams =
1857                                    new LinkedHashMap<String, Object>();
1858    
1859                            groupParams.put("usersGroups", new Long(userId));
1860    
1861                            return search(
1862                                    user.getCompanyId(), null, null, groupParams, start, end);
1863                    }
1864                    else {
1865                            return userPersistence.getGroups(userId, start, end);
1866                    }
1867            }
1868    
1869            /**
1870             * Returns the groups associated with the user groups.
1871             *
1872             * @param  userGroups the user groups
1873             * @return the groups associated with the user groups
1874             * @throws PortalException if any one of the user group's group could not be
1875             *         found
1876             * @throws SystemException if a system exception occurred
1877             */
1878            @Override
1879            public List<Group> getUserGroupsGroups(List<UserGroup> userGroups)
1880                    throws PortalException, SystemException {
1881    
1882                    List<Group> userGroupGroups = new ArrayList<Group>();
1883    
1884                    for (int i = 0; i < userGroups.size(); i++) {
1885                            UserGroup userGroup = userGroups.get(i);
1886    
1887                            Group group = userGroup.getGroup();
1888    
1889                            userGroupGroups.add(group);
1890                    }
1891    
1892                    return userGroupGroups;
1893            }
1894    
1895            /**
1896             * Returns all the groups related to the user groups.
1897             *
1898             * @param  userGroups the user groups
1899             * @return the groups related to the user groups
1900             * @throws SystemException if a system exception occurred
1901             */
1902            @Override
1903            public List<Group> getUserGroupsRelatedGroups(List<UserGroup> userGroups)
1904                    throws SystemException {
1905    
1906                    List<Group> userGroupGroups = new ArrayList<Group>();
1907    
1908                    for (int i = 0; i < userGroups.size(); i++) {
1909                            UserGroup userGroup = userGroups.get(i);
1910    
1911                            List<Group> groups = userGroupPersistence.getGroups(
1912                                    userGroup.getUserGroupId());
1913    
1914                            userGroupGroups.addAll(groups);
1915                    }
1916    
1917                    return userGroupGroups;
1918            }
1919    
1920            /**
1921             * Returns the range of all groups associated with the user's organization
1922             * groups, including the ancestors of the organization groups, unless portal
1923             * property <code>organizations.membership.strict</code> is set to
1924             * <code>true</code>.
1925             *
1926             * <p>
1927             * Useful when paginating results. Returns a maximum of <code>end -
1928             * start</code> instances. <code>start</code> and <code>end</code> are not
1929             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1930             * refers to the first result in the set. Setting both <code>start</code>
1931             * and <code>end</code> to {@link
1932             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1933             * result set.
1934             * </p>
1935             *
1936             * @param  userId the primary key of the user
1937             * @param  start the lower bound of the range of groups to consider
1938             * @param  end the upper bound of the range of groups to consider (not
1939             *         inclusive)
1940             * @return the range of groups associated with the user's organization
1941             *         groups
1942             * @throws PortalException if a user with the primary key could not be found
1943             *         or if another portal exception occurred
1944             * @throws SystemException if a system exception occurred
1945             */
1946            @Override
1947            public List<Group> getUserOrganizationsGroups(
1948                            long userId, int start, int end)
1949                    throws PortalException, SystemException {
1950    
1951                    List<Group> userOrgsGroups = new UniqueList<Group>();
1952    
1953                    List<Organization> userOrgs =
1954                            organizationLocalService.getUserOrganizations(userId, start, end);
1955    
1956                    for (Organization organization : userOrgs) {
1957                            userOrgsGroups.add(0, organization.getGroup());
1958    
1959                            if (!PropsValues.ORGANIZATIONS_MEMBERSHIP_STRICT) {
1960                                    for (Organization ancestorOrganization :
1961                                                    organization.getAncestors()) {
1962    
1963                                            userOrgsGroups.add(0, ancestorOrganization.getGroup());
1964                                    }
1965                            }
1966                    }
1967    
1968                    return userOrgsGroups;
1969            }
1970    
1971            @Override
1972            public Group getUserPersonalSiteGroup(long companyId)
1973                    throws PortalException, SystemException {
1974    
1975                    long classNameId = PortalUtil.getClassNameId(UserPersonalSite.class);
1976                    long defaultUserId = userLocalService.getDefaultUserId(companyId);
1977    
1978                    return groupPersistence.findByC_C_C(
1979                            companyId, classNameId, defaultUserId);
1980            }
1981    
1982            @Override
1983            public List<Group> getUserSitesGroups(long userId)
1984                    throws PortalException, SystemException {
1985    
1986                    User user = userPersistence.findByPrimaryKey(userId);
1987    
1988                    LinkedHashMap<String, Object> groupParams =
1989                            new LinkedHashMap<String, Object>();
1990    
1991                    groupParams.put("inherit", Boolean.TRUE);
1992                    groupParams.put("site", Boolean.TRUE);
1993                    groupParams.put("usersGroups", userId);
1994    
1995                    return groupFinder.findByCompanyId(
1996                            user.getCompanyId(), groupParams, QueryUtil.ALL_POS,
1997                            QueryUtil.ALL_POS, new GroupNameComparator(true));
1998            }
1999    
2000            @Override
2001            public List<Group> getUserSitesGroups(
2002                            long userId, boolean includeAdministrative)
2003                    throws PortalException, SystemException {
2004    
2005                    if (!includeAdministrative) {
2006                            return getUserSitesGroups(userId);
2007                    }
2008    
2009                    Set<Group> sites = new HashSet<Group>();
2010    
2011                    List<UserGroupRole> userGroupRoles =
2012                            userGroupRoleLocalService.getUserGroupRoles(userId);
2013    
2014                    for (UserGroupRole userGroupRole : userGroupRoles) {
2015                            Role role = userGroupRole.getRole();
2016    
2017                            String roleName = role.getName();
2018    
2019                            if (roleName.equals(RoleConstants.SITE_ADMINISTRATOR) ||
2020                                    roleName.equals(RoleConstants.SITE_OWNER)) {
2021    
2022                                    Group group = userGroupRole.getGroup();
2023    
2024                                    sites.add(group);
2025                            }
2026                    }
2027    
2028                    sites.addAll(getUserSitesGroups(userId));
2029    
2030                    return new ArrayList<Group>(sites);
2031            }
2032    
2033            /**
2034             * Returns <code>true</code> if the live group has a staging group.
2035             *
2036             * @param  liveGroupId the primary key of the live group
2037             * @return <code>true</code> if the live group has a staging group;
2038             *         <code>false</code> otherwise
2039             * @throws SystemException if a system exception occurred
2040             */
2041            @Override
2042            public boolean hasStagingGroup(long liveGroupId) throws SystemException {
2043                    if (groupPersistence.fetchByLiveGroupId(liveGroupId) != null) {
2044                            return true;
2045                    }
2046                    else {
2047                            return false;
2048                    }
2049            }
2050    
2051            /**
2052             * Returns <code>true</code> if the user is immediately associated with the
2053             * group, or associated with the group via the user's organizations,
2054             * inherited organizations, or user groups.
2055             *
2056             * @param  userId the primary key of the user
2057             * @param  groupId the primary key of the group
2058             * @return <code>true</code> if the user is associated with the group;
2059             *         <code>false</code> otherwise
2060             * @throws SystemException if a system exception occurred
2061             */
2062            @Override
2063            public boolean hasUserGroup(long userId, long groupId)
2064                    throws SystemException {
2065    
2066                    return hasUserGroup(userId, groupId, true);
2067            }
2068    
2069            /**
2070             * Returns <code>true</code> if the user is immediately associated with the
2071             * group, or optionally if the user is associated with the group via the
2072             * user's organizations, inherited organizations, or user groups.
2073             *
2074             * @param  userId the primary key of the user
2075             * @param  groupId the primary key of the group
2076             * @param  inherit whether to include organization groups and user groups to
2077             *         which the user belongs in the determination
2078             * @return <code>true</code> if the user is associated with the group;
2079             *         <code>false</code> otherwise
2080             * @throws SystemException if a system exception occurred
2081             */
2082            @Override
2083            public boolean hasUserGroup(long userId, long groupId, boolean inherit)
2084                    throws SystemException {
2085    
2086                    if (groupFinder.countByG_U(groupId, userId, inherit) > 0) {
2087                            return true;
2088                    }
2089                    else {
2090                            return false;
2091                    }
2092            }
2093    
2094            /**
2095             * Returns the group with the matching group name by first searching the
2096             * system groups and then using the finder cache.
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, or
2101             *         <code>null</code> if a matching group could not be found
2102             * @throws SystemException if a system exception occurred
2103             */
2104            @Override
2105            public Group loadFetchGroup(long companyId, String name)
2106                    throws SystemException {
2107    
2108                    return groupPersistence.fetchByC_N(companyId, name);
2109            }
2110    
2111            /**
2112             * Returns the group with the matching group name.
2113             *
2114             * @param  companyId the primary key of the company
2115             * @param  name the group's name
2116             * @return the group with the name and associated company
2117             * @throws PortalException if a matching group could not be found
2118             * @throws SystemException if a system exception occurred
2119             */
2120            @Override
2121            public Group loadGetGroup(long companyId, String name)
2122                    throws PortalException, SystemException {
2123    
2124                    return groupPersistence.findByC_N(companyId, name);
2125            }
2126    
2127            /**
2128             * Rebuilds the group tree.
2129             *
2130             * <p>
2131             * Only call this method if the tree has become stale through operations
2132             * other than normal CRUD. Under normal circumstances the tree is
2133             * automatically rebuilt whenever necessary.
2134             * </p>
2135             *
2136             * @param  companyId the primary key of the group's company
2137             * @throws PortalException if a group with the primary key could not be
2138             *         found
2139             * @throws SystemException if a system exception occurred
2140             */
2141            @Override
2142            public void rebuildTree(long companyId)
2143                    throws PortalException, SystemException {
2144    
2145                    TreePathUtil.rebuildTree(
2146                            companyId, GroupConstants.DEFAULT_PARENT_GROUP_ID, StringPool.SLASH,
2147                            new TreeModelFinder<Group>() {
2148    
2149                                    @Override
2150                                    public List<Group> findTreeModels(
2151                                                    long previousId, long companyId, long parentPrimaryKey,
2152                                                    int size)
2153                                            throws SystemException {
2154    
2155                                            return groupPersistence.findByG_C_P(
2156                                                    previousId, companyId, parentPrimaryKey,
2157                                                    QueryUtil.ALL_POS, size, new GroupIdComparator());
2158                                    }
2159    
2160                                    @Override
2161                                    public void rebuildDependentModelsTreePaths(
2162                                            long parentPrimaryKey, String treePath) {
2163                                    }
2164    
2165                                    @Override
2166                                    public void reindexTreeModels(List<TreeModel> treeModels) {
2167                                    }
2168    
2169                            }
2170                    );
2171            }
2172    
2173            /**
2174             * Returns an ordered range of all the company's groups, optionally
2175             * including the user's inherited organization groups and user groups.
2176             * System and staged groups are not included.
2177             *
2178             * <p>
2179             * Useful when paginating results. Returns a maximum of <code>end -
2180             * start</code> instances. <code>start</code> and <code>end</code> are not
2181             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2182             * refers to the first result in the set. Setting both <code>start</code>
2183             * and <code>end</code> to {@link
2184             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2185             * result set.
2186             * </p>
2187             *
2188             * @param  companyId the primary key of the company
2189             * @param  params the finder params (optionally <code>null</code>). To
2190             *         include a user's organizations, inherited organizations, and user
2191             *         groups in the search, add an entry with key
2192             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
2193             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
2194             *         For more information see {@link
2195             *         com.liferay.portal.service.persistence.GroupFinder}
2196             * @param  start the lower bound of the range of groups to return
2197             * @param  end the upper bound of the range of groups to return (not
2198             *         inclusive)
2199             * @return the matching groups ordered by name
2200             * @throws SystemException if a system exception occurred
2201             */
2202            @Override
2203            public List<Group> search(
2204                            long companyId, LinkedHashMap<String, Object> params, int start,
2205                            int end)
2206                    throws SystemException {
2207    
2208                    return groupFinder.findByCompanyId(
2209                            companyId, params, start, end, new GroupNameComparator(true));
2210            }
2211    
2212            /**
2213             * Returns an ordered range of all the groups belonging to the parent group
2214             * that match the keywords, optionally including the user's inherited
2215             * organization groups and user groups. System and staged groups are not
2216             * included.
2217             *
2218             * <p>
2219             * Useful when paginating results. Returns a maximum of <code>end -
2220             * start</code> instances. <code>start</code> and <code>end</code> are not
2221             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2222             * refers to the first result in the set. Setting both <code>start</code>
2223             * and <code>end</code> to {@link
2224             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2225             * result set.
2226             * </p>
2227             *
2228             * @param  companyId the primary key of the company
2229             * @param  parentGroupId the primary key of the parent group
2230             * @param  keywords the keywords (space separated), which may occur in the
2231             *         sites's name, or description (optionally <code>null</code>)
2232             * @param  params the finder params (optionally <code>null</code>). To
2233             *         include the user's inherited organizations and user groups in the
2234             *         search, add entries having &quot;usersGroups&quot; and
2235             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2236             *         information see {@link
2237             *         com.liferay.portal.service.persistence.GroupFinder}
2238             * @param  start the lower bound of the range of groups to return
2239             * @param  end the upper bound of the range of groups to return (not
2240             *         inclusive)
2241             * @return the matching groups ordered by name
2242             * @throws SystemException if a system exception occurred
2243             */
2244            @Override
2245            public List<Group> search(
2246                            long companyId, long parentGroupId, String keywords,
2247                            LinkedHashMap<String, Object> params, int start, int end)
2248                    throws SystemException {
2249    
2250                    return search(
2251                            companyId, getClassNameIds(), parentGroupId, keywords, params,
2252                            start, end, null);
2253            }
2254    
2255            /**
2256             * Returns an ordered range of all the groups belonging to the parent group
2257             * that match the keywords, optionally including the user's inherited
2258             * organization groups and user groups. System and staged groups are not
2259             * included.
2260             *
2261             * <p>
2262             * Useful when paginating results. Returns a maximum of <code>end -
2263             * start</code> instances. <code>start</code> and <code>end</code> are not
2264             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2265             * refers to the first result in the set. Setting both <code>start</code>
2266             * and <code>end</code> to {@link
2267             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2268             * result set.
2269             * </p>
2270             *
2271             * @param  companyId the primary key of the company
2272             * @param  parentGroupId the primary key of the parent group
2273             * @param  keywords the keywords (space separated), which may occur in the
2274             *         sites's name, or description (optionally <code>null</code>)
2275             * @param  params the finder params (optionally <code>null</code>). To
2276             *         include the user's inherited organizations and user groups in the
2277             *         search, add entries having &quot;usersGroups&quot; and
2278             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2279             *         information see {@link
2280             *         com.liferay.portal.service.persistence.GroupFinder}
2281             * @param  start the lower bound of the range of groups to return
2282             * @param  end the upper bound of the range of groups to return (not
2283             *         inclusive)
2284             * @param  obc the comparator to order the groups (optionally
2285             *         <code>null</code>)
2286             * @return the matching groups ordered by comparator <code>obc</code>
2287             * @throws SystemException if a system exception occurred
2288             */
2289            @Override
2290            public List<Group> search(
2291                            long companyId, long parentGroupId, String keywords,
2292                            LinkedHashMap<String, Object> params, int start, int end,
2293                            OrderByComparator obc)
2294                    throws SystemException {
2295    
2296                    return search(
2297                            companyId, getClassNameIds(), parentGroupId, keywords, params,
2298                            start, end, obc);
2299            }
2300    
2301            /**
2302             * Returns an ordered range of all the site groups belonging to the parent
2303             * group and organization groups that match the name and description,
2304             * optionally including the user's inherited organization groups and user
2305             * groups. System and staged groups are not included.
2306             *
2307             * <p>
2308             * Useful when paginating results. Returns a maximum of <code>end -
2309             * start</code> instances. <code>start</code> and <code>end</code> are not
2310             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2311             * refers to the first result in the set. Setting both <code>start</code>
2312             * and <code>end</code> to {@link
2313             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2314             * result set.
2315             * </p>
2316             *
2317             * @param  companyId the primary key of the company
2318             * @param  parentGroupId the primary key of the parent group
2319             * @param  name the group's name (optionally <code>null</code>)
2320             * @param  description the group's description (optionally
2321             *         <code>null</code>)
2322             * @param  params the finder params (optionally <code>null</code>). To
2323             *         include the user's inherited organizations and user groups in the
2324             *         search, add entries having &quot;usersGroups&quot; and
2325             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2326             *         information see {@link
2327             *         com.liferay.portal.service.persistence.GroupFinder}
2328             * @param  andOperator whether every field must match its keywords, or just
2329             *         one field.
2330             * @param  start the lower bound of the range of groups to return
2331             * @param  end the upper bound of the range of groups to return (not
2332             *         inclusive)
2333             * @return the matching groups ordered by name
2334             * @throws SystemException if a system exception occurred
2335             */
2336            @Override
2337            public List<Group> search(
2338                            long companyId, long parentGroupId, String name, String description,
2339                            LinkedHashMap<String, Object> params, boolean andOperator,
2340                            int start, int end)
2341                    throws SystemException {
2342    
2343                    return search(
2344                            companyId, getClassNameIds(), parentGroupId, name, description,
2345                            params, andOperator, start, end, null);
2346            }
2347    
2348            /**
2349             * Returns an ordered range of all the site groups belonging to the parent
2350             * group and organization groups that match the name and description,
2351             * optionally including the user's inherited organization groups and user
2352             * groups. System and staged groups are not included.
2353             *
2354             * <p>
2355             * Useful when paginating results. Returns a maximum of <code>end -
2356             * start</code> instances. <code>start</code> and <code>end</code> are not
2357             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2358             * refers to the first result in the set. Setting both <code>start</code>
2359             * and <code>end</code> to {@link
2360             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2361             * result set.
2362             * </p>
2363             *
2364             * @param  companyId the primary key of the company
2365             * @param  parentGroupId the primary key of the parent group
2366             * @param  name the group's name (optionally <code>null</code>)
2367             * @param  description the group's description (optionally
2368             *         <code>null</code>)
2369             * @param  params the finder params (optionally <code>null</code>). To
2370             *         include the user's inherited organizations and user groups in the
2371             *         search, add entries having &quot;usersGroups&quot; and
2372             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2373             *         information see {@link
2374             *         com.liferay.portal.service.persistence.GroupFinder}
2375             * @param  andOperator whether every field must match its keywords, or just
2376             *         one field.
2377             * @param  start the lower bound of the range of groups to return
2378             * @param  end the upper bound of the range of groups to return (not
2379             *         inclusive)
2380             * @param  obc the comparator to order the groups (optionally
2381             *         <code>null</code>)
2382             * @return the matching groups ordered by comparator <code>obc</code>
2383             * @throws SystemException if a system exception occurred
2384             */
2385            @Override
2386            public List<Group> search(
2387                            long companyId, long parentGroupId, String name, String description,
2388                            LinkedHashMap<String, Object> params, boolean andOperator,
2389                            int start, int end, OrderByComparator obc)
2390                    throws SystemException {
2391    
2392                    return search(
2393                            companyId, getClassNameIds(), parentGroupId, name, description,
2394                            params, andOperator, start, end, obc);
2395            }
2396    
2397            /**
2398             * Returns an ordered range of all the groups belonging to the parent group
2399             * that match the class name IDs and keywords, optionally including the
2400             * user's inherited organization groups and user groups. System and staged
2401             * groups are not included.
2402             *
2403             * <p>
2404             * Useful when paginating results. Returns a maximum of <code>end -
2405             * start</code> instances. <code>start</code> and <code>end</code> are not
2406             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2407             * refers to the first result in the set. Setting both <code>start</code>
2408             * and <code>end</code> to {@link
2409             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2410             * result set.
2411             * </p>
2412             *
2413             * @param  companyId the primary key of the company
2414             * @param  classNameIds the primary keys of the class names of the entities
2415             *         the groups are related to (optionally <code>null</code>)
2416             * @param  parentGroupId the primary key of the parent group
2417             * @param  keywords the keywords (space separated), which may occur in the
2418             *         sites's name, or description (optionally <code>null</code>)
2419             * @param  params the finder params (optionally <code>null</code>). To
2420             *         include a user's organizations, inherited organizations, and user
2421             *         groups in the search, add an entry with key
2422             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
2423             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
2424             *         For more information see {@link
2425             *         com.liferay.portal.service.persistence.GroupFinder}
2426             * @param  start the lower bound of the range of groups to return
2427             * @param  end the upper bound of the range of groups to return (not
2428             *         inclusive)
2429             * @return the matching groups ordered by name
2430             * @throws SystemException if a system exception occurred
2431             */
2432            @Override
2433            public List<Group> search(
2434                            long companyId, long[] classNameIds, long parentGroupId,
2435                            String keywords, LinkedHashMap<String, Object> params, int start,
2436                            int end)
2437                    throws SystemException {
2438    
2439                    return search(
2440                            companyId, classNameIds, parentGroupId, keywords, params, start,
2441                            end, null);
2442            }
2443    
2444            /**
2445             * Returns an ordered range of all the groups belonging to the parent group
2446             * that match the class name IDs and keywords, optionally including the
2447             * user's inherited organization groups and user groups. System and staged
2448             * groups are not included.
2449             *
2450             * <p>
2451             * Useful when paginating results. Returns a maximum of <code>end -
2452             * start</code> instances. <code>start</code> and <code>end</code> are not
2453             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2454             * refers to the first result in the set. Setting both <code>start</code>
2455             * and <code>end</code> to {@link
2456             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2457             * result set.
2458             * </p>
2459             *
2460             * @param  companyId the primary key of the company
2461             * @param  classNameIds the primary keys of the class names of the entities
2462             *         the groups are related to (optionally <code>null</code>)
2463             * @param  parentGroupId the primary key of the parent group
2464             * @param  keywords the keywords (space separated), which may occur in the
2465             *         sites's name, or description (optionally <code>null</code>)
2466             * @param  params the finder params (optionally <code>null</code>). To
2467             *         include a user's organizations, inherited organizations, and user
2468             *         groups in the search, add an entry with key
2469             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
2470             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
2471             *         For more information see {@link
2472             *         com.liferay.portal.service.persistence.GroupFinder}
2473             * @param  start the lower bound of the range of groups to return
2474             * @param  end the upper bound of the range of groups to return (not
2475             *         inclusive)
2476             * @param  obc the comparator to order the groups (optionally
2477             *         <code>null</code>)
2478             * @return the matching groups ordered by comparator <code>obc</code>
2479             * @throws SystemException if a system exception occurred
2480             */
2481            @Override
2482            public List<Group> search(
2483                            long companyId, long[] classNameIds, long parentGroupId,
2484                            String keywords, LinkedHashMap<String, Object> params, int start,
2485                            int end, OrderByComparator obc)
2486                    throws SystemException {
2487    
2488                    String[] keywordsArray = getSearchNames(companyId, keywords);
2489    
2490                    boolean andOperator = false;
2491    
2492                    if (Validator.isNull(keywords)) {
2493                            andOperator = true;
2494                    }
2495    
2496                    if (isUseComplexSQL(classNameIds)) {
2497                            return groupFinder.findByC_C_PG_N_D(
2498                                    companyId, classNameIds, parentGroupId, keywordsArray,
2499                                    keywordsArray, params, andOperator, start, end, obc);
2500                    }
2501    
2502                    List<Group> groups = doSearch(
2503                            companyId, classNameIds, parentGroupId, keywordsArray,
2504                            keywordsArray, params, andOperator);
2505    
2506                    return sort(groups, start, end, obc);
2507            }
2508    
2509            /**
2510             * Returns an ordered range of all the groups belonging to the parent group
2511             * that match the class name IDs, name, and description, optionally
2512             * including the user's inherited organization groups and user groups.
2513             * System and staged groups are not included.
2514             *
2515             * <p>
2516             * Useful when paginating results. Returns a maximum of <code>end -
2517             * start</code> instances. <code>start</code> and <code>end</code> are not
2518             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2519             * refers to the first result in the set. Setting both <code>start</code>
2520             * and <code>end</code> to {@link
2521             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2522             * result set.
2523             * </p>
2524             *
2525             * @param  companyId the primary key of the company
2526             * @param  classNameIds the primary keys of the class names of the entities
2527             *         the groups are related to (optionally <code>null</code>)
2528             * @param  parentGroupId the primary key of the parent group
2529             * @param  name the group's name (optionally <code>null</code>)
2530             * @param  description the group's description (optionally
2531             *         <code>null</code>)
2532             * @param  params the finder params (optionally <code>null</code>). To
2533             *         include a user's organizations, inherited organizations, and user
2534             *         groups in the search, add an entry with key
2535             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
2536             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
2537             *         For more information see {@link
2538             *         com.liferay.portal.service.persistence.GroupFinder}
2539             * @param  andOperator whether every field must match its keywords, or just
2540             *         one field.
2541             * @param  start the lower bound of the range of groups to return
2542             * @param  end the upper bound of the range of groups to return (not
2543             *         inclusive)
2544             * @return the matching groups ordered by name
2545             * @throws SystemException if a system exception occurred
2546             */
2547            @Override
2548            public List<Group> search(
2549                            long companyId, long[] classNameIds, long parentGroupId,
2550                            String name, String description,
2551                            LinkedHashMap<String, Object> params, boolean andOperator,
2552                            int start, int end)
2553                    throws SystemException {
2554    
2555                    return search(
2556                            companyId, classNameIds, parentGroupId, name, description, params,
2557                            andOperator, start, end, null);
2558            }
2559    
2560            /**
2561             * Returns an ordered range of all the groups belonging to the parent group
2562             * that match the class name IDs, name, and description, optionally
2563             * including the user's inherited organization groups and user groups.
2564             * System and staged groups are not included.
2565             *
2566             * <p>
2567             * Useful when paginating results. Returns a maximum of <code>end -
2568             * start</code> instances. <code>start</code> and <code>end</code> are not
2569             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2570             * refers to the first result in the set. Setting both <code>start</code>
2571             * and <code>end</code> to {@link
2572             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2573             * result set.
2574             * </p>
2575             *
2576             * @param  companyId the primary key of the company
2577             * @param  classNameIds the primary keys of the class names of the entities
2578             *         the groups are related to (optionally <code>null</code>)
2579             * @param  parentGroupId the primary key of the parent group
2580             * @param  name the group's name (optionally <code>null</code>)
2581             * @param  description the group's description (optionally
2582             *         <code>null</code>)
2583             * @param  params the finder params (optionally <code>null</code>). To
2584             *         include a user's organizations, inherited organizations, and user
2585             *         groups in the search, add an entry with key
2586             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
2587             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
2588             *         For more information see {@link
2589             *         com.liferay.portal.service.persistence.GroupFinder}
2590             * @param  andOperator whether every field must match its keywords, or just
2591             *         one field.
2592             * @param  start the lower bound of the range of groups to return
2593             * @param  end the upper bound of the range of groups to return (not
2594             *         inclusive)
2595             * @param  obc the comparator to order the groups (optionally
2596             *         <code>null</code>)
2597             * @return the matching groups ordered by comparator <code>obc</code>
2598             * @throws SystemException if a system exception occurred
2599             */
2600            @Override
2601            public List<Group> search(
2602                            long companyId, long[] classNameIds, long parentGroupId,
2603                            String name, String description,
2604                            LinkedHashMap<String, Object> params, boolean andOperator,
2605                            int start, int end, OrderByComparator obc)
2606                    throws SystemException {
2607    
2608                    String[] names = getSearchNames(companyId, name);
2609                    String[] descriptions = CustomSQLUtil.keywords(description);
2610    
2611                    if (isUseComplexSQL(classNameIds)) {
2612                            return groupFinder.findByC_C_PG_N_D(
2613                                    companyId, classNameIds, parentGroupId, names, descriptions,
2614                                    params, andOperator, start, end, obc);
2615                    }
2616    
2617                    List<Group> groups = doSearch(
2618                            companyId, classNameIds, parentGroupId, names, descriptions, params,
2619                            andOperator);
2620    
2621                    return sort(groups, start, end, obc);
2622            }
2623    
2624            /**
2625             * Returns an ordered range of all the groups that match the class name IDs
2626             * and keywords, optionally including the user's inherited organization
2627             * groups and user groups. System and staged groups are not included.
2628             *
2629             * <p>
2630             * Useful when paginating results. Returns a maximum of <code>end -
2631             * start</code> instances. <code>start</code> and <code>end</code> are not
2632             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2633             * refers to the first result in the set. Setting both <code>start</code>
2634             * and <code>end</code> to {@link
2635             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2636             * result set.
2637             * </p>
2638             *
2639             * @param  companyId the primary key of the company
2640             * @param  classNameIds the primary keys of the class names of the entities
2641             *         the groups are related to (optionally <code>null</code>)
2642             * @param  keywords the keywords (space separated), which may occur in the
2643             *         sites's name, or description (optionally <code>null</code>)
2644             * @param  params the finder params (optionally <code>null</code>). To
2645             *         include a user's organizations, inherited organizations, and user
2646             *         groups in the search, add an entry with key
2647             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
2648             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
2649             *         For more information see {@link
2650             *         com.liferay.portal.service.persistence.GroupFinder}
2651             * @param  start the lower bound of the range of groups to return
2652             * @param  end the upper bound of the range of groups to return (not
2653             *         inclusive)
2654             * @return the matching groups ordered by name
2655             * @throws SystemException if a system exception occurred
2656             */
2657            @Override
2658            public List<Group> search(
2659                            long companyId, long[] classNameIds, String keywords,
2660                            LinkedHashMap<String, Object> params, int start, int end)
2661                    throws SystemException {
2662    
2663                    return search(
2664                            companyId, classNameIds, GroupConstants.ANY_PARENT_GROUP_ID,
2665                            keywords, params, start, end, null);
2666            }
2667    
2668            /**
2669             * Returns an ordered range of all the groups that match the class name IDs
2670             * and keywords, optionally including the user's inherited organization
2671             * groups and user groups. System and staged groups are not included.
2672             *
2673             * <p>
2674             * Useful when paginating results. Returns a maximum of <code>end -
2675             * start</code> instances. <code>start</code> and <code>end</code> are not
2676             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2677             * refers to the first result in the set. Setting both <code>start</code>
2678             * and <code>end</code> to {@link
2679             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2680             * result set.
2681             * </p>
2682             *
2683             * @param  companyId the primary key of the company
2684             * @param  classNameIds the primary keys of the class names of the entities
2685             *         the groups are related to (optionally <code>null</code>)
2686             * @param  keywords the keywords (space separated), which may occur in the
2687             *         sites's name, or description (optionally <code>null</code>)
2688             * @param  params the finder params (optionally <code>null</code>). To
2689             *         include a user's organizations, inherited organizations, and user
2690             *         groups in the search, add an entry with key
2691             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
2692             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
2693             *         For more information see {@link
2694             *         com.liferay.portal.service.persistence.GroupFinder}
2695             * @param  start the lower bound of the range of groups to return
2696             * @param  end the upper bound of the range of groups to return (not
2697             *         inclusive)
2698             * @param  obc the comparator to order the groups (optionally
2699             *         <code>null</code>)
2700             * @return the matching groups ordered by comparator <code>obc</code>
2701             * @throws SystemException if a system exception occurred
2702             */
2703            @Override
2704            public List<Group> search(
2705                            long companyId, long[] classNameIds, String keywords,
2706                            LinkedHashMap<String, Object> params, int start, int end,
2707                            OrderByComparator obc)
2708                    throws SystemException {
2709    
2710                    return search(
2711                            companyId, classNameIds, GroupConstants.ANY_PARENT_GROUP_ID,
2712                            keywords, params, start, end, obc);
2713            }
2714    
2715            /**
2716             * Returns an ordered range of all the groups that match the class name IDs,
2717             * name, and description, optionally including the user's inherited
2718             * organization groups and user groups. System and staged groups are not
2719             * included.
2720             *
2721             * <p>
2722             * Useful when paginating results. Returns a maximum of <code>end -
2723             * start</code> instances. <code>start</code> and <code>end</code> are not
2724             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2725             * refers to the first result in the set. Setting both <code>start</code>
2726             * and <code>end</code> to {@link
2727             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2728             * result set.
2729             * </p>
2730             *
2731             * @param  companyId the primary key of the company
2732             * @param  classNameIds the primary keys of the class names of the entities
2733             *         the groups are related to (optionally <code>null</code>)
2734             * @param  name the group's name (optionally <code>null</code>)
2735             * @param  description the group's description (optionally
2736             *         <code>null</code>)
2737             * @param  params the finder params (optionally <code>null</code>). To
2738             *         include a user's organizations, inherited organizations, and user
2739             *         groups in the search, add an entry with key
2740             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
2741             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
2742             *         For more information see {@link
2743             *         com.liferay.portal.service.persistence.GroupFinder}
2744             * @param  andOperator whether every field must match its keywords, or just
2745             *         one field.
2746             * @param  start the lower bound of the range of groups to return
2747             * @param  end the upper bound of the range of groups to return (not
2748             *         inclusive)
2749             * @return the matching groups ordered by name
2750             * @throws SystemException if a system exception occurred
2751             */
2752            @Override
2753            public List<Group> search(
2754                            long companyId, long[] classNameIds, String name,
2755                            String description, LinkedHashMap<String, Object> params,
2756                            boolean andOperator, int start, int end)
2757                    throws SystemException {
2758    
2759                    return search(
2760                            companyId, classNameIds, GroupConstants.ANY_PARENT_GROUP_ID, name,
2761                            description, params, andOperator, start, end, null);
2762            }
2763    
2764            /**
2765             * Returns an ordered range of all the groups that match the class name IDs,
2766             * name, and description, optionally including the user's inherited
2767             * organization groups and user groups. System and staged groups are not
2768             * included.
2769             *
2770             * <p>
2771             * Useful when paginating results. Returns a maximum of <code>end -
2772             * start</code> instances. <code>start</code> and <code>end</code> are not
2773             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2774             * refers to the first result in the set. Setting both <code>start</code>
2775             * and <code>end</code> to {@link
2776             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2777             * result set.
2778             * </p>
2779             *
2780             * @param  companyId the primary key of the company
2781             * @param  classNameIds the primary keys of the class names of the entities
2782             *         the groups are related to (optionally <code>null</code>)
2783             * @param  name the group's name (optionally <code>null</code>)
2784             * @param  description the group's description (optionally
2785             *         <code>null</code>)
2786             * @param  params the finder params (optionally <code>null</code>). To
2787             *         include a user's organizations, inherited organizations, and user
2788             *         groups in the search, add an entry with key
2789             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
2790             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
2791             *         For more information see {@link
2792             *         com.liferay.portal.service.persistence.GroupFinder}
2793             * @param  andOperator whether every field must match its keywords, or just
2794             *         one field.
2795             * @param  start the lower bound of the range of groups to return
2796             * @param  end the upper bound of the range of groups to return (not
2797             *         inclusive)
2798             * @param  obc the comparator to order the groups (optionally
2799             *         <code>null</code>)
2800             * @return the matching groups ordered by comparator <code>obc</code>
2801             * @throws SystemException if a system exception occurred
2802             */
2803            @Override
2804            public List<Group> search(
2805                            long companyId, long[] classNameIds, String name,
2806                            String description, LinkedHashMap<String, Object> params,
2807                            boolean andOperator, int start, int end, OrderByComparator obc)
2808                    throws SystemException {
2809    
2810                    return search(
2811                            companyId, classNameIds, GroupConstants.ANY_PARENT_GROUP_ID, name,
2812                            description, params, andOperator, start, end, obc);
2813            }
2814    
2815            /**
2816             * Returns an ordered range of all the groups that match the keywords,
2817             * optionally including the user's inherited organization groups and user
2818             * groups. System and staged groups are not included.
2819             *
2820             * <p>
2821             * Useful when paginating results. Returns a maximum of <code>end -
2822             * start</code> instances. <code>start</code> and <code>end</code> are not
2823             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2824             * refers to the first result in the set. Setting both <code>start</code>
2825             * and <code>end</code> to {@link
2826             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2827             * result set.
2828             * </p>
2829             *
2830             * @param  companyId the primary key of the company
2831             * @param  keywords the keywords (space separated), which may occur in the
2832             *         sites's name, or description (optionally <code>null</code>)
2833             * @param  params the finder params (optionally <code>null</code>). To
2834             *         include the user's inherited organizations and user groups in the
2835             *         search, add entries having &quot;usersGroups&quot; and
2836             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2837             *         information see {@link
2838             *         com.liferay.portal.service.persistence.GroupFinder}
2839             * @param  start the lower bound of the range of groups to return
2840             * @param  end the upper bound of the range of groups to return (not
2841             *         inclusive)
2842             * @return the matching groups ordered by name
2843             * @throws SystemException if a system exception occurred
2844             */
2845            @Override
2846            @ThreadLocalCachable
2847            public List<Group> search(
2848                            long companyId, String keywords,
2849                            LinkedHashMap<String, Object> params, int start, int end)
2850                    throws SystemException {
2851    
2852                    return search(
2853                            companyId, getClassNameIds(), GroupConstants.ANY_PARENT_GROUP_ID,
2854                            keywords, params, start, end, null);
2855            }
2856    
2857            /**
2858             * Returns an ordered range of all the groups that match the keywords,
2859             * optionally including the user's inherited organization groups and user
2860             * groups. System and staged groups are not included.
2861             *
2862             * <p>
2863             * Useful when paginating results. Returns a maximum of <code>end -
2864             * start</code> instances. <code>start</code> and <code>end</code> are not
2865             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2866             * refers to the first result in the set. Setting both <code>start</code>
2867             * and <code>end</code> to {@link
2868             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2869             * result set.
2870             * </p>
2871             *
2872             * @param  companyId the primary key of the company
2873             * @param  keywords the keywords (space separated), which may occur in the
2874             *         sites's name, or description (optionally <code>null</code>)
2875             * @param  params the finder params (optionally <code>null</code>). To
2876             *         include the user's inherited organizations and user groups in the
2877             *         search, add entries having &quot;usersGroups&quot; and
2878             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2879             *         information see {@link
2880             *         com.liferay.portal.service.persistence.GroupFinder}
2881             * @param  start the lower bound of the range of groups to return
2882             * @param  end the upper bound of the range of groups to return (not
2883             *         inclusive)
2884             * @param  obc the comparator to order the groups (optionally
2885             *         <code>null</code>)
2886             * @return the matching groups ordered by comparator <code>obc</code>
2887             * @throws SystemException if a system exception occurred
2888             */
2889            @Override
2890            public List<Group> search(
2891                            long companyId, String keywords,
2892                            LinkedHashMap<String, Object> params, int start, int end,
2893                            OrderByComparator obc)
2894                    throws SystemException {
2895    
2896                    return search(
2897                            companyId, getClassNameIds(), GroupConstants.ANY_PARENT_GROUP_ID,
2898                            keywords, params, start, end, obc);
2899            }
2900    
2901            /**
2902             * Returns an ordered range of all the site groups and organization groups
2903             * that match the name and description, optionally including the user's
2904             * inherited organization groups and user groups. System and staged groups
2905             * are not included.
2906             *
2907             * <p>
2908             * Useful when paginating results. Returns a maximum of <code>end -
2909             * start</code> instances. <code>start</code> and <code>end</code> are not
2910             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2911             * refers to the first result in the set. Setting both <code>start</code>
2912             * and <code>end</code> to {@link
2913             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2914             * result set.
2915             * </p>
2916             *
2917             * @param  companyId the primary key of the company
2918             * @param  name the group's name (optionally <code>null</code>)
2919             * @param  description the group's description (optionally
2920             *         <code>null</code>)
2921             * @param  params the finder params (optionally <code>null</code>). To
2922             *         include the user's inherited organizations and user groups in the
2923             *         search, add entries having &quot;usersGroups&quot; and
2924             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2925             *         information see {@link
2926             *         com.liferay.portal.service.persistence.GroupFinder}
2927             * @param  andOperator whether every field must match its keywords, or just
2928             *         one field.
2929             * @param  start the lower bound of the range of groups to return
2930             * @param  end the upper bound of the range of groups to return (not
2931             *         inclusive)
2932             * @return the matching groups ordered by name
2933             * @throws SystemException if a system exception occurred
2934             */
2935            @Override
2936            public List<Group> search(
2937                            long companyId, String name, String description,
2938                            LinkedHashMap<String, Object> params, boolean andOperator,
2939                            int start, int end)
2940                    throws SystemException {
2941    
2942                    return search(
2943                            companyId, getClassNameIds(), GroupConstants.ANY_PARENT_GROUP_ID,
2944                            name, description, params, andOperator, start, end, null);
2945            }
2946    
2947            /**
2948             * Returns an ordered range of all the site groups and organization groups
2949             * that match the name and description, optionally including the user's
2950             * inherited organization groups and user groups. System and staged groups
2951             * are not included.
2952             *
2953             * <p>
2954             * Useful when paginating results. Returns a maximum of <code>end -
2955             * start</code> instances. <code>start</code> and <code>end</code> are not
2956             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2957             * refers to the first result in the set. Setting both <code>start</code>
2958             * and <code>end</code> to {@link
2959             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2960             * result set.
2961             * </p>
2962             *
2963             * @param  companyId the primary key of the company
2964             * @param  name the group's name (optionally <code>null</code>)
2965             * @param  description the group's description (optionally
2966             *         <code>null</code>)
2967             * @param  params the finder params (optionally <code>null</code>). To
2968             *         include the user's inherited organizations and user groups in the
2969             *         search, add entries having &quot;usersGroups&quot; and
2970             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2971             *         information see {@link
2972             *         com.liferay.portal.service.persistence.GroupFinder}
2973             * @param  andOperator whether every field must match its keywords, or just
2974             *         one field.
2975             * @param  start the lower bound of the range of groups to return
2976             * @param  end the upper bound of the range of groups to return (not
2977             *         inclusive)
2978             * @param  obc the comparator to order the groups (optionally
2979             *         <code>null</code>)
2980             * @return the matching groups ordered by comparator <code>obc</code>
2981             * @throws SystemException if a system exception occurred
2982             */
2983            @Override
2984            public List<Group> search(
2985                            long companyId, String name, String description,
2986                            LinkedHashMap<String, Object> params, boolean andOperator,
2987                            int start, int end, OrderByComparator obc)
2988                    throws SystemException {
2989    
2990                    return search(
2991                            companyId, getClassNameIds(), GroupConstants.ANY_PARENT_GROUP_ID,
2992                            name, description, params, andOperator, start, end, obc);
2993            }
2994    
2995            /**
2996             * Returns the number of groups belonging to the parent group that match the
2997             * keywords, optionally including the user's inherited organization groups
2998             * and user groups. System and staged groups are not included.
2999             *
3000             * @param  companyId the primary key of the company
3001             * @param  parentGroupId the primary key of the parent group
3002             * @param  keywords the keywords (space separated), which may occur in the
3003             *         sites's name, or description (optionally <code>null</code>)
3004             * @param  params the finder params (optionally <code>null</code>). To
3005             *         include the user's inherited organization groups and user groups
3006             *         in the search, add entries having &quot;usersGroups&quot; and
3007             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
3008             *         information see {@link
3009             *         com.liferay.portal.service.persistence.GroupFinder}
3010             * @return the number of matching groups
3011             * @throws SystemException if a system exception occurred
3012             */
3013            @Override
3014            @ThreadLocalCachable
3015            public int searchCount(
3016                            long companyId, long parentGroupId, String keywords,
3017                            LinkedHashMap<String, Object> params)
3018                    throws SystemException {
3019    
3020                    return searchCount(
3021                            companyId, getClassNameIds(), parentGroupId, keywords, params);
3022            }
3023    
3024            /**
3025             * Returns the number of groups belonging to the parent group and immediate
3026             * organization groups that match the name and description, optionally
3027             * including the user's inherited organization groups and user groups.
3028             * System and staged groups are not included.
3029             *
3030             * @param  companyId the primary key of the company
3031             * @param  parentGroupId the primary key of the parent group
3032             * @param  name the group's name (optionally <code>null</code>)
3033             * @param  description the group's description (optionally
3034             *         <code>null</code>)
3035             * @param  params the finder params (optionally <code>null</code>). To
3036             *         include the user's inherited organization groups and user groups
3037             *         in the search, add entries having &quot;usersGroups&quot; and
3038             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
3039             *         information see {@link
3040             *         com.liferay.portal.service.persistence.GroupFinder}
3041             * @param  andOperator whether every field must match its keywords, or just
3042             *         one field.
3043             * @return the number of matching groups
3044             * @throws SystemException if a system exception occurred
3045             */
3046            @Override
3047            @ThreadLocalCachable
3048            public int searchCount(
3049                            long companyId, long parentGroupId, String name, String description,
3050                            LinkedHashMap<String, Object> params, boolean andOperator)
3051                    throws SystemException {
3052    
3053                    return searchCount(
3054                            companyId, getClassNameIds(), parentGroupId, name, description,
3055                            params, andOperator);
3056            }
3057    
3058            /**
3059             * Returns the number of groups belonging to the parent group that match the
3060             * class name IDs, and keywords, optionally including the user's inherited
3061             * organization groups and user groups. System and staged groups are not
3062             * included.
3063             *
3064             * @param  companyId the primary key of the company
3065             * @param  classNameIds the primary keys of the class names of the entities
3066             *         the groups are related to (optionally <code>null</code>)
3067             * @param  parentGroupId the primary key of the parent group
3068             * @param  keywords the keywords (space separated), which may occur in the
3069             *         sites's name, or description (optionally <code>null</code>)
3070             * @param  params the finder params (optionally <code>null</code>). To
3071             *         include the user's inherited organization groups and user groups
3072             *         in the search, add entries having &quot;usersGroups&quot; and
3073             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
3074             *         information see {@link
3075             *         com.liferay.portal.service.persistence.GroupFinder}
3076             * @return the number of matching groups
3077             * @throws SystemException if a system exception occurred
3078             */
3079            @Override
3080            @ThreadLocalCachable
3081            public int searchCount(
3082                            long companyId, long[] classNameIds, long parentGroupId,
3083                            String keywords, LinkedHashMap<String, Object> params)
3084                    throws SystemException {
3085    
3086                    String[] keywordsArray = getSearchNames(companyId, keywords);
3087    
3088                    boolean andOperator = false;
3089    
3090                    if (Validator.isNull(keywords)) {
3091                            andOperator = true;
3092                    }
3093    
3094                    if (isUseComplexSQL(classNameIds)) {
3095                            return groupFinder.countByC_C_PG_N_D(
3096                                    companyId, classNameIds, parentGroupId, keywordsArray,
3097                                    keywordsArray, params, andOperator);
3098                    }
3099    
3100                    List<Group> groups = doSearch(
3101                            companyId, classNameIds, parentGroupId, keywordsArray,
3102                            keywordsArray, params, andOperator);
3103    
3104                    return groups.size();
3105            }
3106    
3107            /**
3108             * Returns the number of groups belonging to the parent group that match the
3109             * class name IDs, name, and description, optionally including the user's
3110             * inherited organization groups and user groups. System and staged groups
3111             * are not included.
3112             *
3113             * @param  companyId the primary key of the company
3114             * @param  classNameIds the primary keys of the class names of the entities
3115             *         the groups are related to (optionally <code>null</code>)
3116             * @param  parentGroupId the primary key of the parent group
3117             * @param  name the group's name (optionally <code>null</code>)
3118             * @param  description the group's description (optionally
3119             *         <code>null</code>)
3120             * @param  params the finder params (optionally <code>null</code>). To
3121             *         include the user's inherited organization groups and user groups
3122             *         in the search, add entries having &quot;usersGroups&quot; and
3123             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
3124             *         information see {@link
3125             *         com.liferay.portal.service.persistence.GroupFinder}
3126             * @param  andOperator whether every field must match its keywords, or just
3127             *         one field.
3128             * @return the number of matching groups
3129             * @throws SystemException if a system exception occurred
3130             */
3131            @Override
3132            @ThreadLocalCachable
3133            public int searchCount(
3134                            long companyId, long[] classNameIds, long parentGroupId,
3135                            String name, String description,
3136                            LinkedHashMap<String, Object> params, boolean andOperator)
3137                    throws SystemException {
3138    
3139                    String[] names = getSearchNames(companyId, name);
3140                    String[] descriptions = CustomSQLUtil.keywords(description);
3141    
3142                    if (isUseComplexSQL(classNameIds)) {
3143                            return groupFinder.countByC_C_PG_N_D(
3144                                    companyId, classNameIds, parentGroupId, names, descriptions,
3145                                    params, andOperator);
3146                    }
3147    
3148                    List<Group> groups = doSearch(
3149                            companyId, classNameIds, parentGroupId, names, descriptions, params,
3150                            andOperator);
3151    
3152                    return groups.size();
3153            }
3154    
3155            /**
3156             * Returns the number of groups that match the class name IDs, and keywords,
3157             * optionally including the user's inherited organization groups and user
3158             * groups. System and staged groups are not included.
3159             *
3160             * @param  companyId the primary key of the company
3161             * @param  classNameIds the primary keys of the class names of the entities
3162             *         the groups are related to (optionally <code>null</code>)
3163             * @param  keywords the keywords (space separated), which may occur in the
3164             *         sites's name, or description (optionally <code>null</code>)
3165             * @param  params the finder params (optionally <code>null</code>). To
3166             *         include the user's inherited organization groups and user groups
3167             *         in the search, add entries having &quot;usersGroups&quot; and
3168             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
3169             *         information see {@link
3170             *         com.liferay.portal.service.persistence.GroupFinder}
3171             * @return the number of matching groups
3172             * @throws SystemException if a system exception occurred
3173             */
3174            @Override
3175            @ThreadLocalCachable
3176            public int searchCount(
3177                            long companyId, long[] classNameIds, String keywords,
3178                            LinkedHashMap<String, Object> params)
3179                    throws SystemException {
3180    
3181                    return searchCount(
3182                            companyId, classNameIds, GroupConstants.ANY_PARENT_GROUP_ID,
3183                            keywords, params);
3184            }
3185    
3186            /**
3187             * Returns the number of groups that match the class name IDs, name, and
3188             * description, optionally including the user's inherited organization
3189             * groups and user groups. System and staged groups are not included.
3190             *
3191             * @param  companyId the primary key of the company
3192             * @param  classNameIds the primary keys of the class names of the entities
3193             *         the groups are related to (optionally <code>null</code>)
3194             * @param  name the group's name (optionally <code>null</code>)
3195             * @param  description the group's description (optionally
3196             *         <code>null</code>)
3197             * @param  params the finder params (optionally <code>null</code>). To
3198             *         include the user's inherited organization groups and user groups
3199             *         in the search, add entries having &quot;usersGroups&quot; and
3200             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
3201             *         information see {@link
3202             *         com.liferay.portal.service.persistence.GroupFinder}
3203             * @param  andOperator whether every field must match its keywords, or just
3204             *         one field.
3205             * @return the number of matching groups
3206             * @throws SystemException if a system exception occurred
3207             */
3208            @Override
3209            @ThreadLocalCachable
3210            public int searchCount(
3211                            long companyId, long[] classNameIds, String name,
3212                            String description, LinkedHashMap<String, Object> params,
3213                            boolean andOperator)
3214                    throws SystemException {
3215    
3216                    return searchCount(
3217                            companyId, classNameIds, GroupConstants.ANY_PARENT_GROUP_ID, name,
3218                            description, params, andOperator);
3219            }
3220    
3221            /**
3222             * Returns the number of groups that match the keywords, optionally
3223             * including the user's inherited organization groups and user groups.
3224             * System and staged groups are not included.
3225             *
3226             * @param  companyId the primary key of the company
3227             * @param  keywords the keywords (space separated), which may occur in the
3228             *         sites's name, or description (optionally <code>null</code>)
3229             * @param  params the finder params (optionally <code>null</code>). To
3230             *         include the user's inherited organization groups and user groups
3231             *         in the search, add entries having &quot;usersGroups&quot; and
3232             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
3233             *         information see {@link
3234             *         com.liferay.portal.service.persistence.GroupFinder}
3235             * @return the number of matching groups
3236             * @throws SystemException if a system exception occurred
3237             */
3238            @Override
3239            @ThreadLocalCachable
3240            public int searchCount(
3241                            long companyId, String keywords,
3242                            LinkedHashMap<String, Object> params)
3243                    throws SystemException {
3244    
3245                    return searchCount(
3246                            companyId, getClassNameIds(), GroupConstants.ANY_PARENT_GROUP_ID,
3247                            keywords, params);
3248            }
3249    
3250            /**
3251             * Returns the number of groups and immediate organization groups that match
3252             * the name and description, optionally including the user's inherited
3253             * organization groups and user groups. System and staged groups are not
3254             * included.
3255             *
3256             * @param  companyId the primary key of the company
3257             * @param  name the group's name (optionally <code>null</code>)
3258             * @param  description the group's description (optionally
3259             *         <code>null</code>)
3260             * @param  params the finder params (optionally <code>null</code>). To
3261             *         include the user's inherited organization groups and user groups
3262             *         in the search, add entries having &quot;usersGroups&quot; and
3263             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
3264             *         information see {@link
3265             *         com.liferay.portal.service.persistence.GroupFinder}
3266             * @param  andOperator whether every field must match its keywords, or just
3267             *         one field.
3268             * @return the number of matching groups
3269             * @throws SystemException if a system exception occurred
3270             */
3271            @Override
3272            @ThreadLocalCachable
3273            public int searchCount(
3274                            long companyId, String name, String description,
3275                            LinkedHashMap<String, Object> params, boolean andOperator)
3276                    throws SystemException {
3277    
3278                    return searchCount(
3279                            companyId, getClassNameIds(), GroupConstants.ANY_PARENT_GROUP_ID,
3280                            name, description, params, andOperator);
3281            }
3282    
3283            /**
3284             * Sets the groups associated with the role, removing and adding
3285             * associations as necessary.
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 setRoleGroups(long roleId, long[] groupIds)
3293                    throws SystemException {
3294    
3295                    rolePersistence.setGroups(roleId, groupIds);
3296    
3297                    PermissionCacheUtil.clearCache();
3298            }
3299    
3300            /**
3301             * Removes the groups from the role.
3302             *
3303             * @param  roleId the primary key of the role
3304             * @param  groupIds the primary keys of the groups
3305             * @throws SystemException if a system exception occurred
3306             */
3307            @Override
3308            public void unsetRoleGroups(long roleId, long[] groupIds)
3309                    throws SystemException {
3310    
3311                    rolePersistence.removeGroups(roleId, groupIds);
3312    
3313                    PermissionCacheUtil.clearCache();
3314            }
3315    
3316            /**
3317             * Removes the user from the groups.
3318             *
3319             * @param  userId the primary key of the user
3320             * @param  groupIds the primary keys of the groups
3321             * @throws SystemException if a system exception occurred
3322             */
3323            @Override
3324            public void unsetUserGroups(long userId, long[] groupIds)
3325                    throws SystemException {
3326    
3327                    userGroupRoleLocalService.deleteUserGroupRoles(userId, groupIds);
3328    
3329                    userPersistence.removeGroups(userId, groupIds);
3330    
3331                    PermissionCacheUtil.clearCache(userId);
3332            }
3333    
3334            /**
3335             * Updates the group's asset replacing categories and tag names.
3336             *
3337             * @param  userId the primary key of the user
3338             * @param  group the group
3339             * @param  assetCategoryIds the primary keys of the asset categories
3340             *         (optionally <code>null</code>)
3341             * @param  assetTagNames the asset tag names (optionally <code>null</code>)
3342             * @throws PortalException if a user with the primary key could not be found
3343             * @throws SystemException if a system exception occurred
3344             */
3345            @Override
3346            public void updateAsset(
3347                            long userId, Group group, long[] assetCategoryIds,
3348                            String[] assetTagNames)
3349                    throws PortalException, SystemException {
3350    
3351                    User user = userPersistence.findByPrimaryKey(userId);
3352    
3353                    Company company = companyPersistence.findByPrimaryKey(
3354                            user.getCompanyId());
3355    
3356                    Group companyGroup = company.getGroup();
3357    
3358                    assetEntryLocalService.updateEntry(
3359                            userId, companyGroup.getGroupId(), null, null,
3360                            Group.class.getName(), group.getGroupId(), null, 0,
3361                            assetCategoryIds, assetTagNames, false, null, null, null, null,
3362                            group.getDescriptiveName(), group.getDescription(), null, null,
3363                            null, 0, 0, null, false);
3364            }
3365    
3366            /**
3367             * Updates the group's friendly URL.
3368             *
3369             * @param  groupId the primary key of the group
3370             * @param  friendlyURL the group's new friendlyURL (optionally
3371             *         <code>null</code>)
3372             * @return the group
3373             * @throws PortalException if a group with the primary key could not be
3374             *         found or if a valid friendly URL could not be created for the
3375             *         group
3376             * @throws SystemException if a system exception occurred
3377             */
3378            @Override
3379            public Group updateFriendlyURL(long groupId, String friendlyURL)
3380                    throws PortalException, SystemException {
3381    
3382                    Group group = groupPersistence.findByPrimaryKey(groupId);
3383    
3384                    if (group.isUser()) {
3385                            User user = userPersistence.findByPrimaryKey(group.getClassPK());
3386    
3387                            friendlyURL = StringPool.SLASH + user.getScreenName();
3388    
3389                            if (group.getFriendlyURL().equals(friendlyURL)) {
3390                                    return group;
3391                            }
3392                    }
3393    
3394                    friendlyURL = getFriendlyURL(
3395                            group.getCompanyId(), groupId, group.getClassNameId(),
3396                            group.getClassPK(), StringPool.BLANK, friendlyURL);
3397    
3398                    validateFriendlyURL(
3399                            group.getCompanyId(), group.getGroupId(), group.getClassNameId(),
3400                            group.getClassPK(), friendlyURL);
3401    
3402                    group.setFriendlyURL(friendlyURL);
3403    
3404                    groupPersistence.update(group);
3405    
3406                    return group;
3407            }
3408    
3409            /**
3410             * Updates the group.
3411             *
3412             * @param  groupId the primary key of the group
3413             * @param  parentGroupId the primary key of the parent group
3414             * @param  name the group's new name
3415             * @param  description the group's new description (optionally
3416             *         <code>null</code>)
3417             * @param  type the group's new type. For more information see {@link
3418             *         com.liferay.portal.model.GroupConstants}
3419             * @param  friendlyURL the group's new friendlyURL (optionally
3420             *         <code>null</code>)
3421             * @param  active whether the group is active
3422             * @param  serviceContext the service context to be applied (optionally
3423             *         <code>null</code>). Can set asset category IDs and asset tag
3424             *         names for the group.
3425             * @return the group
3426             * @throws PortalException if a group with the primary key could not be
3427             *         found or if the friendly URL was invalid or could one not be
3428             *         created
3429             * @throws SystemException if a system exception occurred
3430             */
3431            @Override
3432            public Group updateGroup(
3433                            long groupId, long parentGroupId, String name, String description,
3434                            int type, boolean manualMembership, int membershipRestriction,
3435                            String friendlyURL, boolean active, ServiceContext serviceContext)
3436                    throws PortalException, SystemException {
3437    
3438                    Group group = groupPersistence.findByPrimaryKey(groupId);
3439    
3440                    String className = group.getClassName();
3441                    long classNameId = group.getClassNameId();
3442                    long classPK = group.getClassPK();
3443                    friendlyURL = getFriendlyURL(
3444                            group.getCompanyId(), groupId, classNameId, classPK,
3445                            StringPool.BLANK, friendlyURL);
3446    
3447                    if ((classNameId <= 0) || className.equals(Group.class.getName())) {
3448                            validateName(
3449                                    group.getGroupId(), group.getCompanyId(), name, group.isSite());
3450                    }
3451                    else if (className.equals(Organization.class.getName())) {
3452                            Organization organization =
3453                                    organizationPersistence.findByPrimaryKey(classPK);
3454    
3455                            name = getOrgGroupName(organization.getName());
3456                    }
3457                    else if (!GroupConstants.USER_PERSONAL_SITE.equals(name)) {
3458                            name = String.valueOf(classPK);
3459                    }
3460    
3461                    if (PortalUtil.isSystemGroup(group.getName()) &&
3462                            !name.equals(group.getName())) {
3463    
3464                            throw new RequiredGroupException(
3465                                    String.valueOf(group.getGroupId()),
3466                                    RequiredGroupException.SYSTEM_GROUP);
3467                    }
3468    
3469                    validateFriendlyURL(
3470                            group.getCompanyId(), group.getGroupId(), group.getClassNameId(),
3471                            group.getClassPK(), friendlyURL);
3472    
3473                    validateParentGroup(group.getGroupId(), parentGroupId);
3474    
3475                    group.setParentGroupId(parentGroupId);
3476                    group.setTreePath(group.buildTreePath());
3477                    group.setName(name);
3478                    group.setDescription(description);
3479                    group.setType(type);
3480                    group.setManualMembership(manualMembership);
3481                    group.setMembershipRestriction(membershipRestriction);
3482                    group.setFriendlyURL(friendlyURL);
3483                    group.setActive(active);
3484    
3485                    if ((serviceContext != null) && group.isSite()) {
3486                            group.setExpandoBridgeAttributes(serviceContext);
3487                    }
3488    
3489                    groupPersistence.update(group);
3490    
3491                    // Asset
3492    
3493                    if ((serviceContext == null) || !group.isSite()) {
3494                            return group;
3495                    }
3496    
3497                    User user = null;
3498    
3499                    user = userPersistence.fetchByPrimaryKey(group.getCreatorUserId());
3500    
3501                    if (user == null) {
3502                            user = userPersistence.fetchByPrimaryKey(
3503                                    serviceContext.getUserId());
3504                    }
3505    
3506                    if (user == null) {
3507                            user = userLocalService.getDefaultUser(group.getCompanyId());
3508                    }
3509    
3510                    updateAsset(
3511                            user.getUserId(), group, serviceContext.getAssetCategoryIds(),
3512                            serviceContext.getAssetTagNames());
3513    
3514                    return group;
3515            }
3516    
3517            /**
3518             * Updates the group's type settings.
3519             *
3520             * @param  groupId the primary key of the group
3521             * @param  typeSettings the group's new type settings (optionally
3522             *         <code>null</code>)
3523             * @return the group
3524             * @throws PortalException if a group with the primary key could not be
3525             *         found
3526             * @throws SystemException if a system exception occurred
3527             */
3528            @Override
3529            public Group updateGroup(long groupId, String typeSettings)
3530                    throws PortalException, SystemException {
3531    
3532                    Group group = groupPersistence.findByPrimaryKey(groupId);
3533    
3534                    UnicodeProperties oldTypeSettingsProperties =
3535                            group.getTypeSettingsProperties();
3536    
3537                    UnicodeProperties typeSettingsProperties = new UnicodeProperties(true);
3538    
3539                    typeSettingsProperties.fastLoad(typeSettings);
3540    
3541                    String newLanguageIds = typeSettingsProperties.getProperty(
3542                            PropsKeys.LOCALES);
3543    
3544                    if (Validator.isNotNull(newLanguageIds)) {
3545                            String oldLanguageIds = oldTypeSettingsProperties.getProperty(
3546                                    PropsKeys.LOCALES, StringPool.BLANK);
3547    
3548                            String defaultLanguageId = typeSettingsProperties.getProperty(
3549                                    "languageId", LocaleUtil.toLanguageId(LocaleUtil.getDefault()));
3550    
3551                            if (!Validator.equals(oldLanguageIds, newLanguageIds)) {
3552                                    validateLanguageIds(defaultLanguageId, newLanguageIds);
3553    
3554                                    LanguageUtil.resetAvailableGroupLocales(groupId);
3555                            }
3556                    }
3557    
3558                    group.setTypeSettings(typeSettings);
3559    
3560                    groupPersistence.update(group);
3561    
3562                    return group;
3563            }
3564    
3565            /**
3566             * Associates the group with a main site if the group is an organization.
3567             *
3568             * @param  groupId the primary key of the group
3569             * @param  site whether the group is to be associated with a main site
3570             * @return the group
3571             * @throws PortalException if a group with the primary key could not be
3572             *         found
3573             * @throws SystemException if a system exception occurred
3574             */
3575            @Override
3576            public Group updateSite(long groupId, boolean site)
3577                    throws PortalException, SystemException {
3578    
3579                    Group group = groupPersistence.findByPrimaryKey(groupId);
3580    
3581                    if (!group.isOrganization()) {
3582                            return group;
3583                    }
3584    
3585                    group.setSite(site);
3586    
3587                    groupPersistence.update(group);
3588    
3589                    return group;
3590            }
3591    
3592            protected void addControlPanelLayouts(Group group)
3593                    throws PortalException, SystemException {
3594    
3595                    long defaultUserId = userLocalService.getDefaultUserId(
3596                            group.getCompanyId());
3597    
3598                    String friendlyURL = getFriendlyURL(
3599                            PropsValues.CONTROL_PANEL_LAYOUT_FRIENDLY_URL);
3600    
3601                    ServiceContext serviceContext = new ServiceContext();
3602    
3603                    layoutLocalService.addLayout(
3604                            defaultUserId, group.getGroupId(), true,
3605                            LayoutConstants.DEFAULT_PARENT_LAYOUT_ID,
3606                            PropsValues.CONTROL_PANEL_LAYOUT_NAME, StringPool.BLANK,
3607                            StringPool.BLANK, LayoutConstants.TYPE_CONTROL_PANEL, false,
3608                            friendlyURL, serviceContext);
3609            }
3610    
3611            protected void addDefaultGuestPublicLayoutByProperties(Group group)
3612                    throws PortalException, SystemException {
3613    
3614                    List<Portlet> portlets = portletLocalService.getPortlets(
3615                            group.getCompanyId());
3616    
3617                    if (portlets.isEmpty()) {
3618    
3619                            // LPS-38457
3620    
3621                            return;
3622                    }
3623    
3624                    long defaultUserId = userLocalService.getDefaultUserId(
3625                            group.getCompanyId());
3626                    String friendlyURL = getFriendlyURL(
3627                            PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_FRIENDLY_URL);
3628    
3629                    ServiceContext serviceContext = new ServiceContext();
3630    
3631                    Layout layout = layoutLocalService.addLayout(
3632                            defaultUserId, group.getGroupId(), false,
3633                            LayoutConstants.DEFAULT_PARENT_LAYOUT_ID,
3634                            PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_NAME, StringPool.BLANK,
3635                            StringPool.BLANK, LayoutConstants.TYPE_PORTLET, false, friendlyURL,
3636                            serviceContext);
3637    
3638                    LayoutTypePortlet layoutTypePortlet =
3639                            (LayoutTypePortlet)layout.getLayoutType();
3640    
3641                    layoutTypePortlet.setLayoutTemplateId(
3642                            0, PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_TEMPLATE_ID, false);
3643    
3644                    LayoutTemplate layoutTemplate = layoutTypePortlet.getLayoutTemplate();
3645    
3646                    for (String columnId : layoutTemplate.getColumns()) {
3647                            String keyPrefix = PropsKeys.DEFAULT_GUEST_PUBLIC_LAYOUT_PREFIX;
3648    
3649                            String portletIds = PropsUtil.get(keyPrefix.concat(columnId));
3650    
3651                            layoutTypePortlet.addPortletIds(
3652                                    0, StringUtil.split(portletIds), columnId, false);
3653                    }
3654    
3655                    layoutLocalService.updateLayout(
3656                            layout.getGroupId(), layout.isPrivateLayout(), layout.getLayoutId(),
3657                            layout.getTypeSettings());
3658    
3659                    boolean updateLayoutSet = false;
3660    
3661                    LayoutSet layoutSet = layout.getLayoutSet();
3662    
3663                    if (Validator.isNotNull(
3664                                    PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_REGULAR_THEME_ID)) {
3665    
3666                            layoutSet.setThemeId(
3667                                    PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_REGULAR_THEME_ID);
3668    
3669                            updateLayoutSet = true;
3670                    }
3671    
3672                    if (Validator.isNotNull(
3673                                    PropsValues.
3674                                            DEFAULT_GUEST_PUBLIC_LAYOUT_REGULAR_COLOR_SCHEME_ID)) {
3675    
3676                            layoutSet.setColorSchemeId(
3677                                    PropsValues.
3678                                            DEFAULT_GUEST_PUBLIC_LAYOUT_REGULAR_COLOR_SCHEME_ID);
3679    
3680                            updateLayoutSet = true;
3681                    }
3682    
3683                    if (Validator.isNotNull(
3684                                    PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_WAP_THEME_ID)) {
3685    
3686                            layoutSet.setWapThemeId(
3687                                    PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_WAP_THEME_ID);
3688    
3689                            updateLayoutSet = true;
3690                    }
3691    
3692                    if (Validator.isNotNull(
3693                                    PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_WAP_COLOR_SCHEME_ID)) {
3694    
3695                            layoutSet.setWapColorSchemeId(
3696                                    PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_WAP_COLOR_SCHEME_ID);
3697    
3698                            updateLayoutSet = true;
3699                    }
3700    
3701                    if (updateLayoutSet) {
3702                            layoutSetLocalService.updateLayoutSet(layoutSet);
3703                    }
3704            }
3705    
3706            protected void addDefaultGuestPublicLayouts(Group group)
3707                    throws PortalException, SystemException {
3708    
3709                    if (publicLARFile != null) {
3710                            addDefaultGuestPublicLayoutsByLAR(group, publicLARFile);
3711                    }
3712                    else {
3713                            addDefaultGuestPublicLayoutByProperties(group);
3714                    }
3715            }
3716    
3717            protected void addDefaultGuestPublicLayoutsByLAR(Group group, File larFile)
3718                    throws PortalException, SystemException {
3719    
3720                    long defaultUserId = userLocalService.getDefaultUserId(
3721                            group.getCompanyId());
3722    
3723                    Map<String, String[]> parameterMap = new HashMap<String, String[]>();
3724    
3725                    parameterMap.put(
3726                            PortletDataHandlerKeys.CATEGORIES,
3727                            new String[] {Boolean.TRUE.toString()});
3728                    parameterMap.put(
3729                            PortletDataHandlerKeys.PERMISSIONS,
3730                            new String[] {Boolean.TRUE.toString()});
3731                    parameterMap.put(
3732                            PortletDataHandlerKeys.PORTLET_CONFIGURATION,
3733                            new String[] {Boolean.TRUE.toString()});
3734                    parameterMap.put(
3735                            PortletDataHandlerKeys.PORTLET_DATA,
3736                            new String[] {Boolean.TRUE.toString()});
3737                    parameterMap.put(
3738                            PortletDataHandlerKeys.PORTLET_DATA_CONTROL_DEFAULT,
3739                            new String[] {Boolean.TRUE.toString()});
3740    
3741                    layoutLocalService.importLayouts(
3742                            defaultUserId, group.getGroupId(), false, parameterMap, larFile);
3743            }
3744    
3745            protected void deletePortletData(Group group)
3746                    throws PortalException, SystemException {
3747    
3748                    List<Portlet> portlets = portletLocalService.getPortlets(
3749                            group.getCompanyId());
3750    
3751                    for (Portlet portlet : portlets) {
3752                            if (!portlet.isActive()) {
3753                                    continue;
3754                            }
3755    
3756                            PortletDataHandler portletDataHandler =
3757                                    portlet.getPortletDataHandlerInstance();
3758    
3759                            if ((portletDataHandler == null) ||
3760                                    portletDataHandler.isDataPortalLevel()) {
3761    
3762                                    continue;
3763                            }
3764    
3765                            PortletDataContext portletDataContext =
3766                                    PortletDataContextFactoryUtil.createExportPortletDataContext(
3767                                            group.getCompanyId(), group.getGroupId(),
3768                                            (Map<String, String[]>)null, (Date)null, (Date)null,
3769                                            (ZipWriter)null);
3770    
3771                            // For now, we are going to throw an exception if one portlet data
3772                            // handler has an exception to ensure that the transaction is rolled
3773                            // back for data integrity. We may decide that this is not the best
3774                            // behavior in the future because a bad plugin could disallow
3775                            // deletion of groups.
3776    
3777                            //try {
3778                                    portletDataHandler.deleteData(
3779                                            portletDataContext, portlet.getPortletId(), null);
3780                            /*}
3781                            catch (Exception e) {
3782                                    _log.error(
3783                                            "Unable to delete data for portlet " +
3784                                                    portlet.getPortletId() + " in group " +
3785                                                            group.getGroupId());
3786                            }*/
3787                    }
3788            }
3789    
3790            protected List<Group> doSearch(
3791                            long companyId, long[] classNameIds, long parentGroupId,
3792                            String[] names, String[] descriptions,
3793                            LinkedHashMap<String, Object> params, boolean andOperator)
3794                    throws SystemException {
3795    
3796                    boolean parentGroupIdEquals = true;
3797    
3798                    if (parentGroupId == GroupConstants.ANY_PARENT_GROUP_ID) {
3799                            parentGroupIdEquals = false;
3800                    }
3801    
3802                    params = new LinkedHashMap<String, Object>(params);
3803    
3804                    Boolean active = (Boolean)params.remove("active");
3805                    List<Long> excludedGroupIds = (List<Long>)params.remove(
3806                            "excludedGroupIds");
3807                    List<Group> groupsTree = (List<Group>)params.remove("groupsTree");
3808                    Boolean manualMembership = (Boolean)params.remove("manualMembership");
3809                    Integer membershipRestriction = (Integer)params.remove(
3810                            "membershipRestriction");
3811                    Boolean site = (Boolean)params.remove("site");
3812                    List<Integer> types = (List<Integer>)params.remove("types");
3813    
3814                    Collection<Group> groups = new HashSet<Group>();
3815    
3816                    Long userId = (Long)params.remove("usersGroups");
3817    
3818                    for (long classNameId : classNameIds) {
3819                            groups.addAll(groupPersistence.findByC_C(companyId, classNameId));
3820                    }
3821    
3822                    Iterator<Group> iterator = groups.iterator();
3823    
3824                    while (iterator.hasNext()) {
3825                            Group group = iterator.next();
3826    
3827                            // Filter by live group ID
3828    
3829                            long liveGroupId = group.getLiveGroupId();
3830    
3831                            if (liveGroupId != 0) {
3832                                    iterator.remove();
3833    
3834                                    continue;
3835                            }
3836    
3837                            // Filter by parent group ID
3838    
3839                            long groupParentGroupId = group.getParentGroupId();
3840    
3841                            if ((parentGroupIdEquals &&
3842                                     (groupParentGroupId != parentGroupId)) ||
3843                                    (!parentGroupIdEquals &&
3844                                     (groupParentGroupId == parentGroupId))) {
3845    
3846                                    iterator.remove();
3847    
3848                                    continue;
3849                            }
3850    
3851                            // Filter by name and description
3852    
3853                            String name = group.getName();
3854    
3855                            if (name.equals(GroupConstants.CONTROL_PANEL)) {
3856                                    iterator.remove();
3857    
3858                                    continue;
3859                            }
3860    
3861                            boolean containsName = matches(name, names);
3862                            boolean containsDescription = matches(
3863                                    group.getDescription(), descriptions);
3864    
3865                            if ((andOperator && (!containsName || !containsDescription)) ||
3866                                    (!andOperator && (!containsName && !containsDescription))) {
3867    
3868                                    iterator.remove();
3869    
3870                                    continue;
3871                            }
3872    
3873                            // Filter by active
3874    
3875                            if (active != null) {
3876                                    if (active != group.isActive()) {
3877                                            iterator.remove();
3878    
3879                                            continue;
3880                                    }
3881                            }
3882    
3883                            // Filter by excluded group IDs
3884    
3885                            if ((excludedGroupIds != null) &&
3886                                    excludedGroupIds.contains(group.getGroupId())) {
3887    
3888                                    iterator.remove();
3889    
3890                                    continue;
3891                            }
3892    
3893                            // Filter by groups tree
3894    
3895                            if (groupsTree != null) {
3896                                    String treePath = group.getTreePath();
3897    
3898                                    boolean matched = false;
3899    
3900                                    for (Group groupTree : groupsTree) {
3901                                            String groupTreePath = StringUtil.quote(
3902                                                    String.valueOf(groupTree.getGroupId()),
3903                                                    StringPool.SLASH);
3904    
3905                                            if (treePath.contains(groupTreePath)) {
3906                                                    matched = true;
3907    
3908                                                    break;
3909                                            }
3910                                    }
3911    
3912                                    if (!matched) {
3913                                            iterator.remove();
3914    
3915                                            continue;
3916                                    }
3917                            }
3918    
3919                            // Filter by manual membership
3920    
3921                            if ((manualMembership != null) &&
3922                                    (manualMembership != group.isManualMembership())) {
3923    
3924                                    iterator.remove();
3925    
3926                                    continue;
3927                            }
3928    
3929                            // Filter by membership restriction
3930    
3931                            if ((membershipRestriction != null) &&
3932                                    (membershipRestriction != group.getMembershipRestriction())) {
3933    
3934                                    iterator.remove();
3935    
3936                                    continue;
3937                            }
3938    
3939                            // Filter by site
3940    
3941                            if (site != null) {
3942                                    if (site != group.isSite()) {
3943                                            iterator.remove();
3944    
3945                                            continue;
3946                                    }
3947                            }
3948    
3949                            // Filter by type and types
3950    
3951                            int type = group.getType();
3952    
3953                            if (type == 4) {
3954                                    iterator.remove();
3955    
3956                                    continue;
3957                            }
3958    
3959                            if ((types != null) && !types.contains(type)) {
3960                                    iterator.remove();
3961    
3962                                    continue;
3963                            }
3964                    }
3965    
3966                    // Join by role permissions
3967    
3968                    List<?> rolePermissions = (List<?>)params.remove("rolePermissions");
3969    
3970                    if (rolePermissions != null) {
3971                            String resourceName = (String)rolePermissions.get(0);
3972                            Integer resourceScope = (Integer)rolePermissions.get(1);
3973                            String resourceActionId = (String)rolePermissions.get(2);
3974                            Long resourceRoleId = (Long)rolePermissions.get(3);
3975    
3976                            ResourceAction resourceAction =
3977                                    resourceActionLocalService.fetchResourceAction(
3978                                            resourceName, resourceActionId);
3979    
3980                            if (resourceAction != null) {
3981                                    Set<Group> rolePermissionsGroups = new HashSet<Group>();
3982    
3983                                    if (resourceBlockLocalService.isSupported(resourceName)) {
3984                                            List<ResourceTypePermission> resourceTypePermissions =
3985                                                    resourceTypePermissionPersistence.findByRoleId(
3986                                                            resourceRoleId);
3987    
3988                                            for (ResourceTypePermission resourceTypePermission :
3989                                                            resourceTypePermissions) {
3990    
3991                                                    if ((resourceTypePermission.getCompanyId() ==
3992                                                                    companyId) &&
3993                                                            resourceName.equals(
3994                                                                    resourceTypePermission.getName()) &&
3995                                                            ((resourceTypePermission.getActionIds() &
3996                                                              resourceAction.getBitwiseValue()) != 0)) {
3997    
3998                                                            Group group = groupPersistence.fetchByPrimaryKey(
3999                                                                    resourceTypePermission.getGroupId());
4000    
4001                                                            if (group != null) {
4002                                                                    rolePermissionsGroups.add(group);
4003                                                            }
4004                                                    }
4005                                            }
4006                                    }
4007                                    else {
4008                                            List<ResourcePermission> resourcePermissions =
4009                                                    resourcePermissionPersistence.findByC_N_S(
4010                                                            companyId, resourceName, resourceScope);
4011    
4012                                            for (ResourcePermission resourcePermission :
4013                                                            resourcePermissions) {
4014    
4015                                                    if ((resourcePermission.getRoleId() ==
4016                                                                    resourceRoleId) &&
4017                                                            ((resourcePermission.getActionIds() &
4018                                                              resourceAction.getBitwiseValue()) != 0)) {
4019    
4020                                                            Group group = groupPersistence.fetchByPrimaryKey(
4021                                                                    GetterUtil.getLong(
4022                                                                            resourcePermission.getPrimKey()));
4023    
4024                                                            if (group != null) {
4025                                                                    rolePermissionsGroups.add(group);
4026                                                            }
4027                                                    }
4028                                            }
4029                                    }
4030    
4031                                    groups.retainAll(rolePermissionsGroups);
4032                            }
4033                    }
4034    
4035                    if (userId == null) {
4036                            return new ArrayList<Group>(groups);
4037                    }
4038    
4039                    // Join by Users_Groups
4040    
4041                    Set<Group> joinedGroups = new HashSet<Group>(
4042                            userPersistence.getGroups(userId));
4043    
4044                    boolean inherit = GetterUtil.getBoolean(params.remove("inherit"), true);
4045    
4046                    if (inherit) {
4047    
4048                            // Join by Users_Orgs
4049    
4050                            List<Organization> organizations = userPersistence.getOrganizations(
4051                                    userId);
4052    
4053                            for (Organization organization : organizations) {
4054                                    long organizationId = organization.getOrganizationId();
4055    
4056                                    for (Group group : groups) {
4057                                            if (organizationId == group.getClassPK()) {
4058                                                    joinedGroups.add(group);
4059                                            }
4060                                    }
4061                            }
4062    
4063                            // Join by Groups_Orgs and Users_Orgs
4064    
4065                            for (Organization organization : organizations) {
4066                                    joinedGroups.addAll(
4067                                            organizationPersistence.getGroups(
4068                                                    organization.getOrganizationId()));
4069                            }
4070    
4071                            // Join by Groups_UserGroups and Users_UserGroups
4072    
4073                            List<UserGroup> userGroups = userPersistence.getUserGroups(userId);
4074    
4075                            for (UserGroup userGroup : userGroups) {
4076                                    joinedGroups.addAll(
4077                                            userGroupPersistence.getGroups(userGroup.getUserGroupId()));
4078                            }
4079                    }
4080    
4081                    if (_log.isDebugEnabled() && !params.isEmpty()) {
4082                            _log.debug("Unprocessed parameters " + MapUtil.toString(params));
4083                    }
4084    
4085                    // Join by Groups_Roles
4086    
4087                    Long roleId = (Long)params.remove("groupsRoles");
4088    
4089                    if (roleId != null) {
4090                            joinedGroups.retainAll(rolePersistence.getGroups(roleId));
4091                    }
4092    
4093                    if (joinedGroups.size() > groups.size()) {
4094                            groups.retainAll(joinedGroups);
4095    
4096                            return new ArrayList<Group>(groups);
4097                    }
4098                    else {
4099                            joinedGroups.retainAll(groups);
4100    
4101                            return new ArrayList<Group>(joinedGroups);
4102                    }
4103            }
4104    
4105            protected long[] getClassNameIds() {
4106                    if (_classNameIds == null) {
4107                            _classNameIds = new long[] {
4108                                    classNameLocalService.getClassNameId(Group.class),
4109                                    classNameLocalService.getClassNameId(Organization.class)
4110                            };
4111                    }
4112    
4113                    return _classNameIds;
4114            }
4115    
4116            protected String getFriendlyURL(
4117                            long companyId, long groupId, long classNameId, long classPK,
4118                            String friendlyName, String friendlyURL)
4119                    throws PortalException, SystemException {
4120    
4121                    friendlyURL = getFriendlyURL(friendlyURL);
4122    
4123                    if (Validator.isNotNull(friendlyURL)) {
4124                            return friendlyURL;
4125                    }
4126    
4127                    friendlyURL = StringPool.SLASH + getFriendlyURL(friendlyName);
4128    
4129                    String originalFriendlyURL = friendlyURL;
4130    
4131                    for (int i = 1;; i++) {
4132                            try {
4133                                    validateFriendlyURL(
4134                                            companyId, groupId, classNameId, classPK, friendlyURL);
4135    
4136                                    break;
4137                            }
4138                            catch (GroupFriendlyURLException gfurle) {
4139                                    int type = gfurle.getType();
4140    
4141                                    if (type == GroupFriendlyURLException.DUPLICATE) {
4142                                            friendlyURL = originalFriendlyURL + i;
4143                                    }
4144                                    else {
4145                                            friendlyURL = StringPool.SLASH + classPK;
4146    
4147                                            break;
4148                                    }
4149                            }
4150                    }
4151    
4152                    return friendlyURL;
4153            }
4154    
4155            protected String getFriendlyURL(String friendlyURL) {
4156                    return FriendlyURLNormalizerUtil.normalize(friendlyURL);
4157            }
4158    
4159            protected String getOrgGroupName(String name) {
4160                    return name + ORGANIZATION_NAME_SUFFIX;
4161            }
4162    
4163            protected String[] getSearchNames(long companyId, String name)
4164                    throws SystemException {
4165    
4166                    if (Validator.isNull(name)) {
4167                            return new String[] {null};
4168                    }
4169    
4170                    Company company = companyPersistence.fetchByPrimaryKey(companyId);
4171    
4172                    if (company == null) {
4173                            return CustomSQLUtil.keywords(name);
4174                    }
4175    
4176                    Account account = accountPersistence.fetchByPrimaryKey(
4177                            company.getAccountId());
4178    
4179                    if (account == null) {
4180                            return CustomSQLUtil.keywords(name);
4181                    }
4182    
4183                    String companyName = account.getName();
4184    
4185                    if (StringUtil.wildcardMatches(
4186                                    companyName, name, CharPool.UNDERLINE, CharPool.PERCENT,
4187                                    CharPool.BACK_SLASH, false)) {
4188    
4189                            String[] searchNames = CustomSQLUtil.keywords(name);
4190    
4191                            String guestName = StringUtil.quote(
4192                                    StringUtil.toLowerCase(GroupConstants.GUEST),
4193                                    StringPool.PERCENT);
4194    
4195                            return ArrayUtil.append(searchNames, guestName);
4196                    }
4197    
4198                    return CustomSQLUtil.keywords(name);
4199            }
4200    
4201            protected void initImportLARFile() {
4202                    String publicLARFileName = PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUTS_LAR;
4203    
4204                    if (_log.isDebugEnabled()) {
4205                            _log.debug("Reading public LAR file " + publicLARFileName);
4206                    }
4207    
4208                    if (Validator.isNotNull(publicLARFileName)) {
4209                            publicLARFile = new File(publicLARFileName);
4210    
4211                            if (!publicLARFile.exists()) {
4212                                    _log.error(
4213                                            "Public LAR file " + publicLARFile + " does not exist");
4214    
4215                                    publicLARFile = null;
4216                            }
4217                            else {
4218                                    if (_log.isDebugEnabled()) {
4219                                            _log.debug("Using public LAR file " + publicLARFileName);
4220                                    }
4221                            }
4222                    }
4223            }
4224    
4225            protected void initUserPersonalSitePermissions(Group group)
4226                    throws PortalException, SystemException {
4227    
4228                    // User role
4229    
4230                    Role role = roleLocalService.getRole(
4231                            group.getCompanyId(), RoleConstants.USER);
4232    
4233                    setRolePermissions(
4234                            group, role, Layout.class.getName(),
4235                            new String[] {ActionKeys.VIEW});
4236    
4237                    setRolePermissions(
4238                            group, role, "com.liferay.portlet.blogs",
4239                            new String[] {
4240                                    ActionKeys.ADD_ENTRY, ActionKeys.PERMISSIONS,
4241                                    ActionKeys.SUBSCRIBE});
4242    
4243                    // Power User role
4244    
4245                    role = roleLocalService.getRole(
4246                            group.getCompanyId(), RoleConstants.POWER_USER);
4247    
4248                    List<Portlet> portlets = portletLocalService.getPortlets(
4249                            group.getCompanyId(), false, false);
4250    
4251                    for (Portlet portlet : portlets) {
4252                            List<String> actions =
4253                                    ResourceActionsUtil.getPortletResourceActions(
4254                                            portlet.getPortletId());
4255    
4256                            String controlPanelEntryCategory = GetterUtil.getString(
4257                                    portlet.getControlPanelEntryCategory());
4258    
4259                            if (actions.contains(ActionKeys.ACCESS_IN_CONTROL_PANEL) &&
4260                                    controlPanelEntryCategory.startsWith(
4261                                            PortletCategoryKeys.SITE_ADMINISTRATION)) {
4262    
4263                                    setRolePermissions(
4264                                            group, role, portlet.getPortletId(),
4265                                            new String[] {ActionKeys.ACCESS_IN_CONTROL_PANEL});
4266                            }
4267                    }
4268    
4269                    setRolePermissions(
4270                            group, role, Group.class.getName(),
4271                            new String[] {
4272                                    ActionKeys.MANAGE_LAYOUTS, ActionKeys.VIEW_SITE_ADMINISTRATION
4273                            });
4274    
4275                    setRolePermissions(group, role, "com.liferay.portlet.asset");
4276                    setRolePermissions(group, role, "com.liferay.portlet.blogs");
4277                    setRolePermissions(group, role, "com.liferay.portlet.bookmarks");
4278                    setRolePermissions(group, role, "com.liferay.portlet.documentlibrary");
4279                    setRolePermissions(group, role, "com.liferay.portlet.imagegallery");
4280                    setRolePermissions(group, role, "com.liferay.portlet.journal");
4281                    setRolePermissions(group, role, "com.liferay.portlet.messageboards");
4282                    setRolePermissions(group, role, "com.liferay.portlet.polls");
4283                    setRolePermissions(group, role, "com.liferay.portlet.wiki");
4284            }
4285    
4286            protected boolean isParentGroup(long parentGroupId, long groupId)
4287                    throws PortalException, SystemException {
4288    
4289                    // Return true if parentGroupId is among the parent groups of groupId
4290    
4291                    if (groupId == GroupConstants.DEFAULT_PARENT_GROUP_ID) {
4292                            return false;
4293                    }
4294    
4295                    Group group = groupPersistence.findByPrimaryKey(groupId);
4296    
4297                    String treePath = group.getTreePath();
4298    
4299                    if (treePath.contains(
4300                                    StringPool.SLASH + parentGroupId + StringPool.SLASH)) {
4301    
4302                            return true;
4303                    }
4304                    else {
4305                            return false;
4306                    }
4307            }
4308    
4309            protected boolean isStaging(ServiceContext serviceContext) {
4310                    if (serviceContext != null) {
4311                            return ParamUtil.getBoolean(serviceContext, "staging");
4312                    }
4313    
4314                    return false;
4315            }
4316    
4317            protected boolean isUseComplexSQL(long[] classNameIds) {
4318                    if (ArrayUtil.isEmpty(classNameIds)) {
4319                            return true;
4320                    }
4321    
4322                    if (_complexSQLClassNameIds == null) {
4323                            String[] complexSQLClassNames =
4324                                    PropsValues.GROUPS_COMPLEX_SQL_CLASS_NAMES;
4325    
4326                            long[] complexSQLClassNameIds =
4327                                    new long[complexSQLClassNames.length];
4328    
4329                            for (int i = 0; i < complexSQLClassNames.length; i++) {
4330                                    String complexSQLClassName = complexSQLClassNames[i];
4331    
4332                                    complexSQLClassNameIds[i] = PortalUtil.getClassNameId(
4333                                            complexSQLClassName);
4334                            }
4335    
4336                            _complexSQLClassNameIds = complexSQLClassNameIds;
4337                    }
4338    
4339                    for (long classNameId : classNameIds) {
4340                            if (ArrayUtil.contains(_complexSQLClassNameIds, classNameId)) {
4341                                    return true;
4342                            }
4343                    }
4344    
4345                    return false;
4346            }
4347    
4348            protected boolean matches(String s, String[] keywords) {
4349                    if ((keywords == null) ||
4350                            ((keywords.length == 1) && (keywords[0] == null))) {
4351    
4352                            return true;
4353                    }
4354    
4355                    for (String keyword : keywords) {
4356                            if (StringUtil.wildcardMatches(
4357                                            s, keyword, CharPool.UNDERLINE, CharPool.PERCENT,
4358                                            CharPool.BACK_SLASH, false)) {
4359    
4360                                    return true;
4361                            }
4362                    }
4363    
4364                    return false;
4365            }
4366    
4367            protected void setCompanyPermissions(
4368                            Role role, String name, String[] actionIds)
4369                    throws PortalException, SystemException {
4370    
4371                    if (resourceBlockLocalService.isSupported(name)) {
4372                            resourceBlockLocalService.setCompanyScopePermissions(
4373                                    role.getCompanyId(), name, role.getRoleId(),
4374                                    Arrays.asList(actionIds));
4375                    }
4376                    else {
4377                            resourcePermissionLocalService.setResourcePermissions(
4378                                    role.getCompanyId(), name, ResourceConstants.SCOPE_COMPANY,
4379                                    String.valueOf(role.getCompanyId()), role.getRoleId(),
4380                                    actionIds);
4381                    }
4382            }
4383    
4384            protected void setRolePermissions(Group group, Role role, String name)
4385                    throws PortalException, SystemException {
4386    
4387                    List<String> actions = ResourceActionsUtil.getModelResourceActions(
4388                            name);
4389    
4390                    setRolePermissions(
4391                            group, role, name, actions.toArray(new String[actions.size()]));
4392            }
4393    
4394            protected void setRolePermissions(
4395                            Group group, Role role, String name, String[] actionIds)
4396                    throws PortalException, SystemException {
4397    
4398                    if (resourceBlockLocalService.isSupported(name)) {
4399                            resourceBlockLocalService.setGroupScopePermissions(
4400                                    role.getCompanyId(), group.getGroupId(), name, role.getRoleId(),
4401                                    Arrays.asList(actionIds));
4402                    }
4403                    else {
4404                            resourcePermissionLocalService.setResourcePermissions(
4405                                    group.getCompanyId(), name, ResourceConstants.SCOPE_GROUP,
4406                                    String.valueOf(group.getGroupId()), role.getRoleId(),
4407                                    actionIds);
4408                    }
4409            }
4410    
4411            protected List<Group> sort(
4412                    List<Group> groups, int start, int end, OrderByComparator obc) {
4413    
4414                    if (obc == null) {
4415                            obc = new GroupNameComparator(true);
4416                    }
4417    
4418                    Collections.sort(groups, obc);
4419    
4420                    return Collections.unmodifiableList(
4421                            ListUtil.subList(groups, start, end));
4422            }
4423    
4424            protected void unscheduleStaging(Group group) {
4425                    try {
4426    
4427                            // Remote publishing
4428    
4429                            String groupName = StagingUtil.getSchedulerGroupName(
4430                                    DestinationNames.LAYOUTS_REMOTE_PUBLISHER, group.getGroupId());
4431    
4432                            SchedulerEngineHelperUtil.delete(groupName, StorageType.PERSISTED);
4433    
4434                            long liveGroupId = 0;
4435                            long stagingGroupId = 0;
4436    
4437                            if (group.isStagingGroup()) {
4438                                    liveGroupId = group.getLiveGroupId();
4439    
4440                                    stagingGroupId = group.getGroupId();
4441                            }
4442                            else if (group.hasStagingGroup()) {
4443                                    liveGroupId = group.getGroupId();
4444    
4445                                    stagingGroupId = group.getStagingGroup().getGroupId();
4446                            }
4447    
4448                            if ((liveGroupId != 0) && (stagingGroupId != 0)) {
4449    
4450                                    // Publish to live
4451    
4452                                    groupName = StagingUtil.getSchedulerGroupName(
4453                                            DestinationNames.LAYOUTS_LOCAL_PUBLISHER, liveGroupId);
4454    
4455                                    SchedulerEngineHelperUtil.delete(
4456                                            groupName, StorageType.PERSISTED);
4457    
4458                                    // Copy from live
4459    
4460                                    groupName = StagingUtil.getSchedulerGroupName(
4461                                            DestinationNames.LAYOUTS_LOCAL_PUBLISHER, stagingGroupId);
4462    
4463                                    SchedulerEngineHelperUtil.delete(
4464                                            groupName, StorageType.PERSISTED);
4465                            }
4466                    }
4467                    catch (Exception e) {
4468                            _log.error(
4469                                    "Unable to unschedule events for group: " + group.getGroupId());
4470                    }
4471            }
4472    
4473            protected void validateFriendlyURL(
4474                            long companyId, long groupId, long classNameId, long classPK,
4475                            String friendlyURL)
4476                    throws PortalException, SystemException {
4477    
4478                    Company company = companyPersistence.findByPrimaryKey(companyId);
4479    
4480                    if (company.isSystem()) {
4481                            return;
4482                    }
4483    
4484                    if (Validator.isNull(friendlyURL)) {
4485                            return;
4486                    }
4487    
4488                    int exceptionType = LayoutImpl.validateFriendlyURL(friendlyURL);
4489    
4490                    if (exceptionType != -1) {
4491                            throw new GroupFriendlyURLException(exceptionType);
4492                    }
4493    
4494                    Group group = groupPersistence.fetchByC_F(companyId, friendlyURL);
4495    
4496                    if ((group != null) && (group.getGroupId() != groupId)) {
4497                            throw new GroupFriendlyURLException(
4498                                    GroupFriendlyURLException.DUPLICATE);
4499                    }
4500    
4501                    String groupIdFriendlyURL = friendlyURL.substring(1);
4502    
4503                    if (Validator.isNumber(groupIdFriendlyURL)) {
4504                            long groupClassNameId = PortalUtil.getClassNameId(Group.class);
4505    
4506                            if (((classNameId != groupClassNameId) &&
4507                                     !groupIdFriendlyURL.equals(String.valueOf(classPK)) &&
4508                                     !PropsValues.USERS_SCREEN_NAME_ALLOW_NUMERIC) ||
4509                                    ((classNameId == groupClassNameId) &&
4510                                     !groupIdFriendlyURL.equals(String.valueOf(groupId)))) {
4511    
4512                                    GroupFriendlyURLException gfurle =
4513                                            new GroupFriendlyURLException(
4514                                                    GroupFriendlyURLException.POSSIBLE_DUPLICATE);
4515    
4516                                    gfurle.setKeywordConflict(groupIdFriendlyURL);
4517    
4518                                    throw gfurle;
4519                            }
4520                    }
4521    
4522                    String screenName = friendlyURL.substring(1);
4523    
4524                    User user = userPersistence.fetchByC_SN(companyId, screenName);
4525    
4526                    if (user != null) {
4527                            long userClassNameId = PortalUtil.getClassNameId(User.class);
4528    
4529                            if ((classNameId == userClassNameId) &&
4530                                    (classPK == user.getUserId())) {
4531                            }
4532                            else {
4533                                    throw new GroupFriendlyURLException(
4534                                            GroupFriendlyURLException.DUPLICATE);
4535                            }
4536                    }
4537    
4538                    if (StringUtil.count(friendlyURL, StringPool.SLASH) > 1) {
4539                            throw new GroupFriendlyURLException(
4540                                    GroupFriendlyURLException.TOO_DEEP);
4541                    }
4542            }
4543    
4544            protected void validateLanguageIds(
4545                            String defaultLanguageId, String languageIds)
4546                    throws PortalException {
4547    
4548                    Locale[] availableLocales = LanguageUtil.getAvailableLocales();
4549    
4550                    String[] availableLanguageIds = LocaleUtil.toLanguageIds(
4551                            availableLocales);
4552    
4553                    String[] languageIdsArray = StringUtil.split(languageIds);
4554    
4555                    for (String languageId : languageIdsArray) {
4556                            if (!ArrayUtil.contains(availableLanguageIds, languageId)) {
4557                                    LocaleException le = new LocaleException(
4558                                            LocaleException.TYPE_DISPLAY_SETTINGS);
4559    
4560                                    le.setSourceAvailableLocales(availableLocales);
4561                                    le.setTargetAvailableLocales(
4562                                            LocaleUtil.fromLanguageIds(languageIdsArray));
4563    
4564                                    throw le;
4565                            }
4566                    }
4567    
4568                    if (!ArrayUtil.contains(languageIdsArray, defaultLanguageId)) {
4569                            LocaleException le = new LocaleException(
4570                                    LocaleException.TYPE_DEFAULT);
4571    
4572                            le.setSourceAvailableLocales(availableLocales);
4573                            le.setTargetAvailableLocales(
4574                                    LocaleUtil.fromLanguageIds(languageIdsArray));
4575    
4576                            throw le;
4577                    }
4578            }
4579    
4580            protected void validateName(
4581                            long groupId, long companyId, String name, boolean site)
4582                    throws PortalException, SystemException {
4583    
4584                    if (Validator.isNull(name) || Validator.isNumber(name) ||
4585                            name.contains(StringPool.STAR) ||
4586                            name.contains(ORGANIZATION_NAME_SUFFIX)) {
4587    
4588                            throw new GroupNameException();
4589                    }
4590    
4591                    try {
4592                            Group group = groupFinder.findByC_N(companyId, name);
4593    
4594                            if ((groupId <= 0) || (group.getGroupId() != groupId)) {
4595                                    throw new DuplicateGroupException("{groupId=" + groupId + "}");
4596                            }
4597                    }
4598                    catch (NoSuchGroupException nsge) {
4599                    }
4600    
4601                    if (site) {
4602                            Company company = companyLocalService.getCompany(companyId);
4603    
4604                            if (name.equals(company.getName())) {
4605                                    throw new DuplicateGroupException();
4606                            }
4607                    }
4608            }
4609    
4610            protected void validateParentGroup(long groupId, long parentGroupId)
4611                    throws PortalException, SystemException {
4612    
4613                    if (parentGroupId == GroupConstants.DEFAULT_PARENT_GROUP_ID) {
4614                            return;
4615                    }
4616    
4617                    if (groupId == parentGroupId) {
4618                            throw new GroupParentException(
4619                                    GroupParentException.SELF_DESCENDANT);
4620                    }
4621    
4622                    Group group = groupPersistence.fetchByPrimaryKey(groupId);
4623    
4624                    if (group == null) {
4625                            return;
4626                    }
4627    
4628                    if ((groupId > 0) &&
4629                            (parentGroupId != GroupConstants.DEFAULT_PARENT_GROUP_ID)) {
4630    
4631                            // Prevent circular groupal references
4632    
4633                            if (isParentGroup(groupId, parentGroupId)) {
4634                                    throw new GroupParentException(
4635                                            GroupParentException.CHILD_DESCENDANT);
4636                            }
4637                    }
4638    
4639                    Group parentGroup = groupPersistence.findByPrimaryKey(parentGroupId);
4640    
4641                    if (group.isStagingGroup()) {
4642                            Group stagingGroup = parentGroup.getStagingGroup();
4643    
4644                            if (groupId == stagingGroup.getGroupId()) {
4645                                    throw new GroupParentException(
4646                                            GroupParentException.STAGING_DESCENDANT);
4647                            }
4648                    }
4649            }
4650    
4651            protected File publicLARFile;
4652    
4653            private static Log _log = LogFactoryUtil.getLog(
4654                    GroupLocalServiceImpl.class);
4655    
4656            private volatile long[] _classNameIds;
4657            private volatile long[] _complexSQLClassNameIds;
4658            private Map<String, Group> _systemGroupsMap = new HashMap<String, Group>();
4659    
4660    }