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            @Override
2095            public boolean isLiveGroupActive(Group group) {
2096                    if (group == null) {
2097                            return false;
2098                    }
2099    
2100                    if (!group.isStagingGroup()) {
2101                            return group.isActive();
2102                    }
2103    
2104                    Group liveGroup = group.getLiveGroup();
2105    
2106                    if (liveGroup == null) {
2107                            return false;
2108                    }
2109    
2110                    return liveGroup.isActive();
2111            }
2112    
2113            /**
2114             * Returns the group with the matching group name by first searching the
2115             * system groups and then using the finder cache.
2116             *
2117             * @param  companyId the primary key of the company
2118             * @param  name the group's name
2119             * @return the group with the name and associated company, or
2120             *         <code>null</code> if a matching group could not be found
2121             * @throws SystemException if a system exception occurred
2122             */
2123            @Override
2124            public Group loadFetchGroup(long companyId, String name)
2125                    throws SystemException {
2126    
2127                    return groupPersistence.fetchByC_N(companyId, name);
2128            }
2129    
2130            /**
2131             * Returns the group with the matching group name.
2132             *
2133             * @param  companyId the primary key of the company
2134             * @param  name the group's name
2135             * @return the group with the name and associated company
2136             * @throws PortalException if a matching group could not be found
2137             * @throws SystemException if a system exception occurred
2138             */
2139            @Override
2140            public Group loadGetGroup(long companyId, String name)
2141                    throws PortalException, SystemException {
2142    
2143                    return groupPersistence.findByC_N(companyId, name);
2144            }
2145    
2146            /**
2147             * Rebuilds the group tree.
2148             *
2149             * <p>
2150             * Only call this method if the tree has become stale through operations
2151             * other than normal CRUD. Under normal circumstances the tree is
2152             * automatically rebuilt whenever necessary.
2153             * </p>
2154             *
2155             * @param  companyId the primary key of the group's company
2156             * @throws PortalException if a group with the primary key could not be
2157             *         found
2158             * @throws SystemException if a system exception occurred
2159             */
2160            @Override
2161            public void rebuildTree(long companyId)
2162                    throws PortalException, SystemException {
2163    
2164                    TreePathUtil.rebuildTree(
2165                            companyId, GroupConstants.DEFAULT_PARENT_GROUP_ID, StringPool.SLASH,
2166                            new TreeModelFinder<Group>() {
2167    
2168                                    @Override
2169                                    public List<Group> findTreeModels(
2170                                                    long previousId, long companyId, long parentPrimaryKey,
2171                                                    int size)
2172                                            throws SystemException {
2173    
2174                                            return groupPersistence.findByG_C_P(
2175                                                    previousId, companyId, parentPrimaryKey,
2176                                                    QueryUtil.ALL_POS, size, new GroupIdComparator());
2177                                    }
2178    
2179                                    @Override
2180                                    public void rebuildDependentModelsTreePaths(
2181                                            long parentPrimaryKey, String treePath) {
2182                                    }
2183    
2184                                    @Override
2185                                    public void reindexTreeModels(List<TreeModel> treeModels) {
2186                                    }
2187    
2188                            }
2189                    );
2190            }
2191    
2192            /**
2193             * Returns an ordered range of all the company's groups, optionally
2194             * including the user's inherited organization groups and user groups.
2195             * System and staged groups are not included.
2196             *
2197             * <p>
2198             * Useful when paginating results. Returns a maximum of <code>end -
2199             * start</code> instances. <code>start</code> and <code>end</code> are not
2200             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2201             * refers to the first result in the set. Setting both <code>start</code>
2202             * and <code>end</code> to {@link
2203             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2204             * result set.
2205             * </p>
2206             *
2207             * @param  companyId the primary key of the company
2208             * @param  params the finder params (optionally <code>null</code>). To
2209             *         include a user's organizations, inherited organizations, and user
2210             *         groups in the search, add an entry with key
2211             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
2212             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
2213             *         For more information see {@link
2214             *         com.liferay.portal.service.persistence.GroupFinder}
2215             * @param  start the lower bound of the range of groups to return
2216             * @param  end the upper bound of the range of groups to return (not
2217             *         inclusive)
2218             * @return the matching groups ordered by name
2219             * @throws SystemException if a system exception occurred
2220             */
2221            @Override
2222            public List<Group> search(
2223                            long companyId, LinkedHashMap<String, Object> params, int start,
2224                            int end)
2225                    throws SystemException {
2226    
2227                    return groupFinder.findByCompanyId(
2228                            companyId, params, start, end, new GroupNameComparator(true));
2229            }
2230    
2231            /**
2232             * Returns an ordered range of all the groups belonging to the parent group
2233             * that match the keywords, optionally including the user's inherited
2234             * organization groups and user groups. System and staged groups are not
2235             * included.
2236             *
2237             * <p>
2238             * Useful when paginating results. Returns a maximum of <code>end -
2239             * start</code> instances. <code>start</code> and <code>end</code> are not
2240             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2241             * refers to the first result in the set. Setting both <code>start</code>
2242             * and <code>end</code> to {@link
2243             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2244             * result set.
2245             * </p>
2246             *
2247             * @param  companyId the primary key of the company
2248             * @param  parentGroupId the primary key of the parent group
2249             * @param  keywords the keywords (space separated), which may occur in the
2250             *         sites's name, or description (optionally <code>null</code>)
2251             * @param  params the finder params (optionally <code>null</code>). To
2252             *         include the user's inherited organizations and user groups in the
2253             *         search, add entries having &quot;usersGroups&quot; and
2254             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2255             *         information see {@link
2256             *         com.liferay.portal.service.persistence.GroupFinder}
2257             * @param  start the lower bound of the range of groups to return
2258             * @param  end the upper bound of the range of groups to return (not
2259             *         inclusive)
2260             * @return the matching groups ordered by name
2261             * @throws SystemException if a system exception occurred
2262             */
2263            @Override
2264            public List<Group> search(
2265                            long companyId, long parentGroupId, String keywords,
2266                            LinkedHashMap<String, Object> params, int start, int end)
2267                    throws SystemException {
2268    
2269                    return search(
2270                            companyId, getClassNameIds(), parentGroupId, keywords, params,
2271                            start, end, null);
2272            }
2273    
2274            /**
2275             * Returns an ordered range of all the groups belonging to the parent group
2276             * that match the keywords, optionally including the user's inherited
2277             * organization groups and user groups. System and staged groups are not
2278             * included.
2279             *
2280             * <p>
2281             * Useful when paginating results. Returns a maximum of <code>end -
2282             * start</code> instances. <code>start</code> and <code>end</code> are not
2283             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2284             * refers to the first result in the set. Setting both <code>start</code>
2285             * and <code>end</code> to {@link
2286             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2287             * result set.
2288             * </p>
2289             *
2290             * @param  companyId the primary key of the company
2291             * @param  parentGroupId the primary key of the parent group
2292             * @param  keywords the keywords (space separated), which may occur in the
2293             *         sites's name, or description (optionally <code>null</code>)
2294             * @param  params the finder params (optionally <code>null</code>). To
2295             *         include the user's inherited organizations and user groups in the
2296             *         search, add entries having &quot;usersGroups&quot; and
2297             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2298             *         information see {@link
2299             *         com.liferay.portal.service.persistence.GroupFinder}
2300             * @param  start the lower bound of the range of groups to return
2301             * @param  end the upper bound of the range of groups to return (not
2302             *         inclusive)
2303             * @param  obc the comparator to order the groups (optionally
2304             *         <code>null</code>)
2305             * @return the matching groups ordered by comparator <code>obc</code>
2306             * @throws SystemException if a system exception occurred
2307             */
2308            @Override
2309            public List<Group> search(
2310                            long companyId, long parentGroupId, String keywords,
2311                            LinkedHashMap<String, Object> params, int start, int end,
2312                            OrderByComparator obc)
2313                    throws SystemException {
2314    
2315                    return search(
2316                            companyId, getClassNameIds(), parentGroupId, keywords, params,
2317                            start, end, obc);
2318            }
2319    
2320            /**
2321             * Returns an ordered range of all the site groups belonging to the parent
2322             * group and organization groups that match the name and description,
2323             * optionally including the user's inherited organization groups and user
2324             * groups. System and staged groups are not included.
2325             *
2326             * <p>
2327             * Useful when paginating results. Returns a maximum of <code>end -
2328             * start</code> instances. <code>start</code> and <code>end</code> are not
2329             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2330             * refers to the first result in the set. Setting both <code>start</code>
2331             * and <code>end</code> to {@link
2332             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2333             * result set.
2334             * </p>
2335             *
2336             * @param  companyId the primary key of the company
2337             * @param  parentGroupId the primary key of the parent group
2338             * @param  name the group's name (optionally <code>null</code>)
2339             * @param  description the group's description (optionally
2340             *         <code>null</code>)
2341             * @param  params the finder params (optionally <code>null</code>). To
2342             *         include the user's inherited organizations and user groups in the
2343             *         search, add entries having &quot;usersGroups&quot; and
2344             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2345             *         information see {@link
2346             *         com.liferay.portal.service.persistence.GroupFinder}
2347             * @param  andOperator whether every field must match its keywords, or just
2348             *         one field.
2349             * @param  start the lower bound of the range of groups to return
2350             * @param  end the upper bound of the range of groups to return (not
2351             *         inclusive)
2352             * @return the matching groups ordered by name
2353             * @throws SystemException if a system exception occurred
2354             */
2355            @Override
2356            public List<Group> search(
2357                            long companyId, long parentGroupId, String name, String description,
2358                            LinkedHashMap<String, Object> params, boolean andOperator,
2359                            int start, int end)
2360                    throws SystemException {
2361    
2362                    return search(
2363                            companyId, getClassNameIds(), parentGroupId, name, description,
2364                            params, andOperator, start, end, null);
2365            }
2366    
2367            /**
2368             * Returns an ordered range of all the site groups belonging to the parent
2369             * group and organization groups that match the name and description,
2370             * optionally including the user's inherited organization groups and user
2371             * groups. System and staged groups are not included.
2372             *
2373             * <p>
2374             * Useful when paginating results. Returns a maximum of <code>end -
2375             * start</code> instances. <code>start</code> and <code>end</code> are not
2376             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2377             * refers to the first result in the set. Setting both <code>start</code>
2378             * and <code>end</code> to {@link
2379             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2380             * result set.
2381             * </p>
2382             *
2383             * @param  companyId the primary key of the company
2384             * @param  parentGroupId the primary key of the parent group
2385             * @param  name the group's name (optionally <code>null</code>)
2386             * @param  description the group's description (optionally
2387             *         <code>null</code>)
2388             * @param  params the finder params (optionally <code>null</code>). To
2389             *         include the user's inherited organizations and user groups in the
2390             *         search, add entries having &quot;usersGroups&quot; and
2391             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2392             *         information see {@link
2393             *         com.liferay.portal.service.persistence.GroupFinder}
2394             * @param  andOperator whether every field must match its keywords, or just
2395             *         one field.
2396             * @param  start the lower bound of the range of groups to return
2397             * @param  end the upper bound of the range of groups to return (not
2398             *         inclusive)
2399             * @param  obc the comparator to order the groups (optionally
2400             *         <code>null</code>)
2401             * @return the matching groups ordered by comparator <code>obc</code>
2402             * @throws SystemException if a system exception occurred
2403             */
2404            @Override
2405            public List<Group> search(
2406                            long companyId, long parentGroupId, String name, String description,
2407                            LinkedHashMap<String, Object> params, boolean andOperator,
2408                            int start, int end, OrderByComparator obc)
2409                    throws SystemException {
2410    
2411                    return search(
2412                            companyId, getClassNameIds(), parentGroupId, name, description,
2413                            params, andOperator, start, end, obc);
2414            }
2415    
2416            /**
2417             * Returns an ordered range of all the groups belonging to the parent group
2418             * that match the class name IDs and keywords, optionally including the
2419             * user's inherited organization groups and user groups. System and staged
2420             * groups are not included.
2421             *
2422             * <p>
2423             * Useful when paginating results. Returns a maximum of <code>end -
2424             * start</code> instances. <code>start</code> and <code>end</code> are not
2425             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2426             * refers to the first result in the set. Setting both <code>start</code>
2427             * and <code>end</code> to {@link
2428             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2429             * result set.
2430             * </p>
2431             *
2432             * @param  companyId the primary key of the company
2433             * @param  classNameIds the primary keys of the class names of the entities
2434             *         the groups are related to (optionally <code>null</code>)
2435             * @param  parentGroupId the primary key of the parent group
2436             * @param  keywords the keywords (space separated), which may occur in the
2437             *         sites's name, or description (optionally <code>null</code>)
2438             * @param  params the finder params (optionally <code>null</code>). To
2439             *         include a user's organizations, inherited organizations, and user
2440             *         groups in the search, add an entry with key
2441             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
2442             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
2443             *         For more information see {@link
2444             *         com.liferay.portal.service.persistence.GroupFinder}
2445             * @param  start the lower bound of the range of groups to return
2446             * @param  end the upper bound of the range of groups to return (not
2447             *         inclusive)
2448             * @return the matching groups ordered by name
2449             * @throws SystemException if a system exception occurred
2450             */
2451            @Override
2452            public List<Group> search(
2453                            long companyId, long[] classNameIds, long parentGroupId,
2454                            String keywords, LinkedHashMap<String, Object> params, int start,
2455                            int end)
2456                    throws SystemException {
2457    
2458                    return search(
2459                            companyId, classNameIds, parentGroupId, keywords, params, start,
2460                            end, null);
2461            }
2462    
2463            /**
2464             * Returns an ordered range of all the groups belonging to the parent group
2465             * that match the class name IDs and keywords, optionally including the
2466             * user's inherited organization groups and user groups. System and staged
2467             * groups are not included.
2468             *
2469             * <p>
2470             * Useful when paginating results. Returns a maximum of <code>end -
2471             * start</code> instances. <code>start</code> and <code>end</code> are not
2472             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2473             * refers to the first result in the set. Setting both <code>start</code>
2474             * and <code>end</code> to {@link
2475             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2476             * result set.
2477             * </p>
2478             *
2479             * @param  companyId the primary key of the company
2480             * @param  classNameIds the primary keys of the class names of the entities
2481             *         the groups are related to (optionally <code>null</code>)
2482             * @param  parentGroupId the primary key of the parent group
2483             * @param  keywords the keywords (space separated), which may occur in the
2484             *         sites's name, or description (optionally <code>null</code>)
2485             * @param  params the finder params (optionally <code>null</code>). To
2486             *         include a user's organizations, inherited organizations, and user
2487             *         groups in the search, add an entry with key
2488             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
2489             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
2490             *         For more information see {@link
2491             *         com.liferay.portal.service.persistence.GroupFinder}
2492             * @param  start the lower bound of the range of groups to return
2493             * @param  end the upper bound of the range of groups to return (not
2494             *         inclusive)
2495             * @param  obc the comparator to order the groups (optionally
2496             *         <code>null</code>)
2497             * @return the matching groups ordered by comparator <code>obc</code>
2498             * @throws SystemException if a system exception occurred
2499             */
2500            @Override
2501            public List<Group> search(
2502                            long companyId, long[] classNameIds, long parentGroupId,
2503                            String keywords, LinkedHashMap<String, Object> params, int start,
2504                            int end, OrderByComparator obc)
2505                    throws SystemException {
2506    
2507                    String[] keywordsArray = getSearchNames(companyId, keywords);
2508    
2509                    boolean andOperator = false;
2510    
2511                    if (Validator.isNull(keywords)) {
2512                            andOperator = true;
2513                    }
2514    
2515                    if (isUseComplexSQL(classNameIds)) {
2516                            return groupFinder.findByC_C_PG_N_D(
2517                                    companyId, classNameIds, parentGroupId, keywordsArray,
2518                                    keywordsArray, params, andOperator, start, end, obc);
2519                    }
2520    
2521                    List<Group> groups = doSearch(
2522                            companyId, classNameIds, parentGroupId, keywordsArray,
2523                            keywordsArray, params, andOperator);
2524    
2525                    return sort(groups, start, end, obc);
2526            }
2527    
2528            /**
2529             * Returns an ordered range of all the groups belonging to the parent group
2530             * that match the class name IDs, name, and description, optionally
2531             * including the user's inherited organization groups and user groups.
2532             * System and staged groups are not included.
2533             *
2534             * <p>
2535             * Useful when paginating results. Returns a maximum of <code>end -
2536             * start</code> instances. <code>start</code> and <code>end</code> are not
2537             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2538             * refers to the first result in the set. Setting both <code>start</code>
2539             * and <code>end</code> to {@link
2540             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2541             * result set.
2542             * </p>
2543             *
2544             * @param  companyId the primary key of the company
2545             * @param  classNameIds the primary keys of the class names of the entities
2546             *         the groups are related to (optionally <code>null</code>)
2547             * @param  parentGroupId the primary key of the parent group
2548             * @param  name the group's name (optionally <code>null</code>)
2549             * @param  description the group's description (optionally
2550             *         <code>null</code>)
2551             * @param  params the finder params (optionally <code>null</code>). To
2552             *         include a user's organizations, inherited organizations, and user
2553             *         groups in the search, add an entry with key
2554             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
2555             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
2556             *         For more information see {@link
2557             *         com.liferay.portal.service.persistence.GroupFinder}
2558             * @param  andOperator whether every field must match its keywords, or just
2559             *         one field.
2560             * @param  start the lower bound of the range of groups to return
2561             * @param  end the upper bound of the range of groups to return (not
2562             *         inclusive)
2563             * @return the matching groups ordered by name
2564             * @throws SystemException if a system exception occurred
2565             */
2566            @Override
2567            public List<Group> search(
2568                            long companyId, long[] classNameIds, long parentGroupId,
2569                            String name, String description,
2570                            LinkedHashMap<String, Object> params, boolean andOperator,
2571                            int start, int end)
2572                    throws SystemException {
2573    
2574                    return search(
2575                            companyId, classNameIds, parentGroupId, name, description, params,
2576                            andOperator, start, end, null);
2577            }
2578    
2579            /**
2580             * Returns an ordered range of all the groups belonging to the parent group
2581             * that match the class name IDs, name, and description, optionally
2582             * including the user's inherited organization groups and user groups.
2583             * System and staged groups are not included.
2584             *
2585             * <p>
2586             * Useful when paginating results. Returns a maximum of <code>end -
2587             * start</code> instances. <code>start</code> and <code>end</code> are not
2588             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2589             * refers to the first result in the set. Setting both <code>start</code>
2590             * and <code>end</code> to {@link
2591             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2592             * result set.
2593             * </p>
2594             *
2595             * @param  companyId the primary key of the company
2596             * @param  classNameIds the primary keys of the class names of the entities
2597             *         the groups are related to (optionally <code>null</code>)
2598             * @param  parentGroupId the primary key of the parent group
2599             * @param  name the group's name (optionally <code>null</code>)
2600             * @param  description the group's description (optionally
2601             *         <code>null</code>)
2602             * @param  params the finder params (optionally <code>null</code>). To
2603             *         include a user's organizations, inherited organizations, and user
2604             *         groups in the search, add an entry with key
2605             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
2606             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
2607             *         For more information see {@link
2608             *         com.liferay.portal.service.persistence.GroupFinder}
2609             * @param  andOperator whether every field must match its keywords, or just
2610             *         one field.
2611             * @param  start the lower bound of the range of groups to return
2612             * @param  end the upper bound of the range of groups to return (not
2613             *         inclusive)
2614             * @param  obc the comparator to order the groups (optionally
2615             *         <code>null</code>)
2616             * @return the matching groups ordered by comparator <code>obc</code>
2617             * @throws SystemException if a system exception occurred
2618             */
2619            @Override
2620            public List<Group> search(
2621                            long companyId, long[] classNameIds, long parentGroupId,
2622                            String name, String description,
2623                            LinkedHashMap<String, Object> params, boolean andOperator,
2624                            int start, int end, OrderByComparator obc)
2625                    throws SystemException {
2626    
2627                    String[] names = getSearchNames(companyId, name);
2628                    String[] descriptions = CustomSQLUtil.keywords(description);
2629    
2630                    if (isUseComplexSQL(classNameIds)) {
2631                            return groupFinder.findByC_C_PG_N_D(
2632                                    companyId, classNameIds, parentGroupId, names, descriptions,
2633                                    params, andOperator, start, end, obc);
2634                    }
2635    
2636                    List<Group> groups = doSearch(
2637                            companyId, classNameIds, parentGroupId, names, descriptions, params,
2638                            andOperator);
2639    
2640                    return sort(groups, start, end, obc);
2641            }
2642    
2643            /**
2644             * Returns an ordered range of all the groups that match the class name IDs
2645             * and keywords, optionally including the user's inherited organization
2646             * groups and user groups. System and staged groups are not included.
2647             *
2648             * <p>
2649             * Useful when paginating results. Returns a maximum of <code>end -
2650             * start</code> instances. <code>start</code> and <code>end</code> are not
2651             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2652             * refers to the first result in the set. Setting both <code>start</code>
2653             * and <code>end</code> to {@link
2654             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2655             * result set.
2656             * </p>
2657             *
2658             * @param  companyId the primary key of the company
2659             * @param  classNameIds the primary keys of the class names of the entities
2660             *         the groups are related to (optionally <code>null</code>)
2661             * @param  keywords the keywords (space separated), which may occur in the
2662             *         sites's name, or description (optionally <code>null</code>)
2663             * @param  params the finder params (optionally <code>null</code>). To
2664             *         include a user's organizations, inherited organizations, and user
2665             *         groups in the search, add an entry with key
2666             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
2667             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
2668             *         For more information see {@link
2669             *         com.liferay.portal.service.persistence.GroupFinder}
2670             * @param  start the lower bound of the range of groups to return
2671             * @param  end the upper bound of the range of groups to return (not
2672             *         inclusive)
2673             * @return the matching groups ordered by name
2674             * @throws SystemException if a system exception occurred
2675             */
2676            @Override
2677            public List<Group> search(
2678                            long companyId, long[] classNameIds, String keywords,
2679                            LinkedHashMap<String, Object> params, int start, int end)
2680                    throws SystemException {
2681    
2682                    return search(
2683                            companyId, classNameIds, GroupConstants.ANY_PARENT_GROUP_ID,
2684                            keywords, params, start, end, null);
2685            }
2686    
2687            /**
2688             * Returns an ordered range of all the groups that match the class name IDs
2689             * and keywords, optionally including the user's inherited organization
2690             * groups and user groups. System and staged groups are not included.
2691             *
2692             * <p>
2693             * Useful when paginating results. Returns a maximum of <code>end -
2694             * start</code> instances. <code>start</code> and <code>end</code> are not
2695             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2696             * refers to the first result in the set. Setting both <code>start</code>
2697             * and <code>end</code> to {@link
2698             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2699             * result set.
2700             * </p>
2701             *
2702             * @param  companyId the primary key of the company
2703             * @param  classNameIds the primary keys of the class names of the entities
2704             *         the groups are related to (optionally <code>null</code>)
2705             * @param  keywords the keywords (space separated), which may occur in the
2706             *         sites's name, or description (optionally <code>null</code>)
2707             * @param  params the finder params (optionally <code>null</code>). To
2708             *         include a user's organizations, inherited organizations, and user
2709             *         groups in the search, add an entry with key
2710             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
2711             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
2712             *         For more information see {@link
2713             *         com.liferay.portal.service.persistence.GroupFinder}
2714             * @param  start the lower bound of the range of groups to return
2715             * @param  end the upper bound of the range of groups to return (not
2716             *         inclusive)
2717             * @param  obc the comparator to order the groups (optionally
2718             *         <code>null</code>)
2719             * @return the matching groups ordered by comparator <code>obc</code>
2720             * @throws SystemException if a system exception occurred
2721             */
2722            @Override
2723            public List<Group> search(
2724                            long companyId, long[] classNameIds, String keywords,
2725                            LinkedHashMap<String, Object> params, int start, int end,
2726                            OrderByComparator obc)
2727                    throws SystemException {
2728    
2729                    return search(
2730                            companyId, classNameIds, GroupConstants.ANY_PARENT_GROUP_ID,
2731                            keywords, params, start, end, obc);
2732            }
2733    
2734            /**
2735             * Returns an ordered range of all the groups that match the class name IDs,
2736             * name, and description, optionally including the user's inherited
2737             * organization groups and user groups. System and staged groups are not
2738             * included.
2739             *
2740             * <p>
2741             * Useful when paginating results. Returns a maximum of <code>end -
2742             * start</code> instances. <code>start</code> and <code>end</code> are not
2743             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2744             * refers to the first result in the set. Setting both <code>start</code>
2745             * and <code>end</code> to {@link
2746             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2747             * result set.
2748             * </p>
2749             *
2750             * @param  companyId the primary key of the company
2751             * @param  classNameIds the primary keys of the class names of the entities
2752             *         the groups are related to (optionally <code>null</code>)
2753             * @param  name the group's name (optionally <code>null</code>)
2754             * @param  description the group's description (optionally
2755             *         <code>null</code>)
2756             * @param  params the finder params (optionally <code>null</code>). To
2757             *         include a user's organizations, inherited organizations, and user
2758             *         groups in the search, add an entry with key
2759             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
2760             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
2761             *         For more information see {@link
2762             *         com.liferay.portal.service.persistence.GroupFinder}
2763             * @param  andOperator whether every field must match its keywords, or just
2764             *         one field.
2765             * @param  start the lower bound of the range of groups to return
2766             * @param  end the upper bound of the range of groups to return (not
2767             *         inclusive)
2768             * @return the matching groups ordered by name
2769             * @throws SystemException if a system exception occurred
2770             */
2771            @Override
2772            public List<Group> search(
2773                            long companyId, long[] classNameIds, String name,
2774                            String description, LinkedHashMap<String, Object> params,
2775                            boolean andOperator, int start, int end)
2776                    throws SystemException {
2777    
2778                    return search(
2779                            companyId, classNameIds, GroupConstants.ANY_PARENT_GROUP_ID, name,
2780                            description, params, andOperator, start, end, null);
2781            }
2782    
2783            /**
2784             * Returns an ordered range of all the groups that match the class name IDs,
2785             * name, and description, optionally including the user's inherited
2786             * organization groups and user groups. System and staged groups are not
2787             * included.
2788             *
2789             * <p>
2790             * Useful when paginating results. Returns a maximum of <code>end -
2791             * start</code> instances. <code>start</code> and <code>end</code> are not
2792             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2793             * refers to the first result in the set. Setting both <code>start</code>
2794             * and <code>end</code> to {@link
2795             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2796             * result set.
2797             * </p>
2798             *
2799             * @param  companyId the primary key of the company
2800             * @param  classNameIds the primary keys of the class names of the entities
2801             *         the groups are related to (optionally <code>null</code>)
2802             * @param  name the group's name (optionally <code>null</code>)
2803             * @param  description the group's description (optionally
2804             *         <code>null</code>)
2805             * @param  params the finder params (optionally <code>null</code>). To
2806             *         include a user's organizations, inherited organizations, and user
2807             *         groups in the search, add an entry with key
2808             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
2809             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
2810             *         For more information see {@link
2811             *         com.liferay.portal.service.persistence.GroupFinder}
2812             * @param  andOperator whether every field must match its keywords, or just
2813             *         one field.
2814             * @param  start the lower bound of the range of groups to return
2815             * @param  end the upper bound of the range of groups to return (not
2816             *         inclusive)
2817             * @param  obc the comparator to order the groups (optionally
2818             *         <code>null</code>)
2819             * @return the matching groups ordered by comparator <code>obc</code>
2820             * @throws SystemException if a system exception occurred
2821             */
2822            @Override
2823            public List<Group> search(
2824                            long companyId, long[] classNameIds, String name,
2825                            String description, LinkedHashMap<String, Object> params,
2826                            boolean andOperator, int start, int end, OrderByComparator obc)
2827                    throws SystemException {
2828    
2829                    return search(
2830                            companyId, classNameIds, GroupConstants.ANY_PARENT_GROUP_ID, name,
2831                            description, params, andOperator, start, end, obc);
2832            }
2833    
2834            /**
2835             * Returns an ordered range of all the groups that match the keywords,
2836             * optionally including the user's inherited organization groups and user
2837             * groups. System and staged groups are not included.
2838             *
2839             * <p>
2840             * Useful when paginating results. Returns a maximum of <code>end -
2841             * start</code> instances. <code>start</code> and <code>end</code> are not
2842             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2843             * refers to the first result in the set. Setting both <code>start</code>
2844             * and <code>end</code> to {@link
2845             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2846             * result set.
2847             * </p>
2848             *
2849             * @param  companyId the primary key of the company
2850             * @param  keywords the keywords (space separated), which may occur in the
2851             *         sites's name, or description (optionally <code>null</code>)
2852             * @param  params the finder params (optionally <code>null</code>). To
2853             *         include the user's inherited organizations and user groups in the
2854             *         search, add entries having &quot;usersGroups&quot; and
2855             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2856             *         information see {@link
2857             *         com.liferay.portal.service.persistence.GroupFinder}
2858             * @param  start the lower bound of the range of groups to return
2859             * @param  end the upper bound of the range of groups to return (not
2860             *         inclusive)
2861             * @return the matching groups ordered by name
2862             * @throws SystemException if a system exception occurred
2863             */
2864            @Override
2865            @ThreadLocalCachable
2866            public List<Group> search(
2867                            long companyId, String keywords,
2868                            LinkedHashMap<String, Object> params, int start, int end)
2869                    throws SystemException {
2870    
2871                    return search(
2872                            companyId, getClassNameIds(), GroupConstants.ANY_PARENT_GROUP_ID,
2873                            keywords, params, start, end, null);
2874            }
2875    
2876            /**
2877             * Returns an ordered range of all the groups that match the keywords,
2878             * optionally including the user's inherited organization groups and user
2879             * groups. System and staged groups are not included.
2880             *
2881             * <p>
2882             * Useful when paginating results. Returns a maximum of <code>end -
2883             * start</code> instances. <code>start</code> and <code>end</code> are not
2884             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2885             * refers to the first result in the set. Setting both <code>start</code>
2886             * and <code>end</code> to {@link
2887             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2888             * result set.
2889             * </p>
2890             *
2891             * @param  companyId the primary key of the company
2892             * @param  keywords the keywords (space separated), which may occur in the
2893             *         sites's name, or description (optionally <code>null</code>)
2894             * @param  params the finder params (optionally <code>null</code>). To
2895             *         include the user's inherited organizations and user groups in the
2896             *         search, add entries having &quot;usersGroups&quot; and
2897             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2898             *         information see {@link
2899             *         com.liferay.portal.service.persistence.GroupFinder}
2900             * @param  start the lower bound of the range of groups to return
2901             * @param  end the upper bound of the range of groups to return (not
2902             *         inclusive)
2903             * @param  obc the comparator to order the groups (optionally
2904             *         <code>null</code>)
2905             * @return the matching groups ordered by comparator <code>obc</code>
2906             * @throws SystemException if a system exception occurred
2907             */
2908            @Override
2909            public List<Group> search(
2910                            long companyId, String keywords,
2911                            LinkedHashMap<String, Object> params, int start, int end,
2912                            OrderByComparator obc)
2913                    throws SystemException {
2914    
2915                    return search(
2916                            companyId, getClassNameIds(), GroupConstants.ANY_PARENT_GROUP_ID,
2917                            keywords, params, start, end, obc);
2918            }
2919    
2920            /**
2921             * Returns an ordered range of all the site groups and organization groups
2922             * that match the name and description, optionally including the user's
2923             * inherited organization groups and user groups. System and staged groups
2924             * are not included.
2925             *
2926             * <p>
2927             * Useful when paginating results. Returns a maximum of <code>end -
2928             * start</code> instances. <code>start</code> and <code>end</code> are not
2929             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2930             * refers to the first result in the set. Setting both <code>start</code>
2931             * and <code>end</code> to {@link
2932             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2933             * result set.
2934             * </p>
2935             *
2936             * @param  companyId the primary key of the company
2937             * @param  name the group's name (optionally <code>null</code>)
2938             * @param  description the group's description (optionally
2939             *         <code>null</code>)
2940             * @param  params the finder params (optionally <code>null</code>). To
2941             *         include the user's inherited organizations and user groups in the
2942             *         search, add entries having &quot;usersGroups&quot; and
2943             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2944             *         information see {@link
2945             *         com.liferay.portal.service.persistence.GroupFinder}
2946             * @param  andOperator whether every field must match its keywords, or just
2947             *         one field.
2948             * @param  start the lower bound of the range of groups to return
2949             * @param  end the upper bound of the range of groups to return (not
2950             *         inclusive)
2951             * @return the matching groups ordered by name
2952             * @throws SystemException if a system exception occurred
2953             */
2954            @Override
2955            public List<Group> search(
2956                            long companyId, String name, String description,
2957                            LinkedHashMap<String, Object> params, boolean andOperator,
2958                            int start, int end)
2959                    throws SystemException {
2960    
2961                    return search(
2962                            companyId, getClassNameIds(), GroupConstants.ANY_PARENT_GROUP_ID,
2963                            name, description, params, andOperator, start, end, null);
2964            }
2965    
2966            /**
2967             * Returns an ordered range of all the site groups and organization groups
2968             * that match the name and description, optionally including the user's
2969             * inherited organization groups and user groups. System and staged groups
2970             * are not included.
2971             *
2972             * <p>
2973             * Useful when paginating results. Returns a maximum of <code>end -
2974             * start</code> instances. <code>start</code> and <code>end</code> are not
2975             * primary keys, they are indexes in the result set. Thus, <code>0</code>
2976             * refers to the first result in the set. Setting both <code>start</code>
2977             * and <code>end</code> to {@link
2978             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
2979             * result set.
2980             * </p>
2981             *
2982             * @param  companyId the primary key of the company
2983             * @param  name the group's name (optionally <code>null</code>)
2984             * @param  description the group's description (optionally
2985             *         <code>null</code>)
2986             * @param  params the finder params (optionally <code>null</code>). To
2987             *         include the user's inherited organizations and user groups in the
2988             *         search, add entries having &quot;usersGroups&quot; and
2989             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
2990             *         information see {@link
2991             *         com.liferay.portal.service.persistence.GroupFinder}
2992             * @param  andOperator whether every field must match its keywords, or just
2993             *         one field.
2994             * @param  start the lower bound of the range of groups to return
2995             * @param  end the upper bound of the range of groups to return (not
2996             *         inclusive)
2997             * @param  obc the comparator to order the groups (optionally
2998             *         <code>null</code>)
2999             * @return the matching groups ordered by comparator <code>obc</code>
3000             * @throws SystemException if a system exception occurred
3001             */
3002            @Override
3003            public List<Group> search(
3004                            long companyId, String name, String description,
3005                            LinkedHashMap<String, Object> params, boolean andOperator,
3006                            int start, int end, OrderByComparator obc)
3007                    throws SystemException {
3008    
3009                    return search(
3010                            companyId, getClassNameIds(), GroupConstants.ANY_PARENT_GROUP_ID,
3011                            name, description, params, andOperator, start, end, obc);
3012            }
3013    
3014            /**
3015             * Returns the number of groups belonging to the parent group that match the
3016             * keywords, optionally including the user's inherited organization groups
3017             * and user groups. System and staged groups are not included.
3018             *
3019             * @param  companyId the primary key of the company
3020             * @param  parentGroupId the primary key of the parent group
3021             * @param  keywords the keywords (space separated), which may occur in the
3022             *         sites's name, or description (optionally <code>null</code>)
3023             * @param  params the finder params (optionally <code>null</code>). To
3024             *         include the user's inherited organization groups and user groups
3025             *         in the search, add entries having &quot;usersGroups&quot; and
3026             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
3027             *         information see {@link
3028             *         com.liferay.portal.service.persistence.GroupFinder}
3029             * @return the number of matching groups
3030             * @throws SystemException if a system exception occurred
3031             */
3032            @Override
3033            @ThreadLocalCachable
3034            public int searchCount(
3035                            long companyId, long parentGroupId, String keywords,
3036                            LinkedHashMap<String, Object> params)
3037                    throws SystemException {
3038    
3039                    return searchCount(
3040                            companyId, getClassNameIds(), parentGroupId, keywords, params);
3041            }
3042    
3043            /**
3044             * Returns the number of groups belonging to the parent group and immediate
3045             * organization groups that match the name and description, optionally
3046             * including the user's inherited organization groups and user groups.
3047             * System and staged groups are not included.
3048             *
3049             * @param  companyId the primary key of the company
3050             * @param  parentGroupId the primary key of the parent group
3051             * @param  name the group's name (optionally <code>null</code>)
3052             * @param  description the group's description (optionally
3053             *         <code>null</code>)
3054             * @param  params the finder params (optionally <code>null</code>). To
3055             *         include the user's inherited organization groups and user groups
3056             *         in the search, add entries having &quot;usersGroups&quot; and
3057             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
3058             *         information see {@link
3059             *         com.liferay.portal.service.persistence.GroupFinder}
3060             * @param  andOperator whether every field must match its keywords, or just
3061             *         one field.
3062             * @return the number of matching groups
3063             * @throws SystemException if a system exception occurred
3064             */
3065            @Override
3066            @ThreadLocalCachable
3067            public int searchCount(
3068                            long companyId, long parentGroupId, String name, String description,
3069                            LinkedHashMap<String, Object> params, boolean andOperator)
3070                    throws SystemException {
3071    
3072                    return searchCount(
3073                            companyId, getClassNameIds(), parentGroupId, name, description,
3074                            params, andOperator);
3075            }
3076    
3077            /**
3078             * Returns the number of groups belonging to the parent group that match the
3079             * class name IDs, and keywords, optionally including the user's inherited
3080             * organization groups and user groups. System and staged groups are not
3081             * included.
3082             *
3083             * @param  companyId the primary key of the company
3084             * @param  classNameIds the primary keys of the class names of the entities
3085             *         the groups are related to (optionally <code>null</code>)
3086             * @param  parentGroupId the primary key of the parent group
3087             * @param  keywords the keywords (space separated), which may occur in the
3088             *         sites's name, or description (optionally <code>null</code>)
3089             * @param  params the finder params (optionally <code>null</code>). To
3090             *         include the user's inherited organization groups and user groups
3091             *         in the search, add entries having &quot;usersGroups&quot; and
3092             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
3093             *         information see {@link
3094             *         com.liferay.portal.service.persistence.GroupFinder}
3095             * @return the number of matching groups
3096             * @throws SystemException if a system exception occurred
3097             */
3098            @Override
3099            @ThreadLocalCachable
3100            public int searchCount(
3101                            long companyId, long[] classNameIds, long parentGroupId,
3102                            String keywords, LinkedHashMap<String, Object> params)
3103                    throws SystemException {
3104    
3105                    String[] keywordsArray = getSearchNames(companyId, keywords);
3106    
3107                    boolean andOperator = false;
3108    
3109                    if (Validator.isNull(keywords)) {
3110                            andOperator = true;
3111                    }
3112    
3113                    if (isUseComplexSQL(classNameIds)) {
3114                            return groupFinder.countByC_C_PG_N_D(
3115                                    companyId, classNameIds, parentGroupId, keywordsArray,
3116                                    keywordsArray, params, andOperator);
3117                    }
3118    
3119                    List<Group> groups = doSearch(
3120                            companyId, classNameIds, parentGroupId, keywordsArray,
3121                            keywordsArray, params, andOperator);
3122    
3123                    return groups.size();
3124            }
3125    
3126            /**
3127             * Returns the number of groups belonging to the parent group that match the
3128             * class name IDs, name, and description, optionally including the user's
3129             * inherited organization groups and user groups. System and staged groups
3130             * are not included.
3131             *
3132             * @param  companyId the primary key of the company
3133             * @param  classNameIds the primary keys of the class names of the entities
3134             *         the groups are related to (optionally <code>null</code>)
3135             * @param  parentGroupId the primary key of the parent group
3136             * @param  name the group's name (optionally <code>null</code>)
3137             * @param  description the group's description (optionally
3138             *         <code>null</code>)
3139             * @param  params the finder params (optionally <code>null</code>). To
3140             *         include the user's inherited organization groups and user groups
3141             *         in the search, add entries having &quot;usersGroups&quot; and
3142             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
3143             *         information see {@link
3144             *         com.liferay.portal.service.persistence.GroupFinder}
3145             * @param  andOperator whether every field must match its keywords, or just
3146             *         one field.
3147             * @return the number of matching groups
3148             * @throws SystemException if a system exception occurred
3149             */
3150            @Override
3151            @ThreadLocalCachable
3152            public int searchCount(
3153                            long companyId, long[] classNameIds, long parentGroupId,
3154                            String name, String description,
3155                            LinkedHashMap<String, Object> params, boolean andOperator)
3156                    throws SystemException {
3157    
3158                    String[] names = getSearchNames(companyId, name);
3159                    String[] descriptions = CustomSQLUtil.keywords(description);
3160    
3161                    if (isUseComplexSQL(classNameIds)) {
3162                            return groupFinder.countByC_C_PG_N_D(
3163                                    companyId, classNameIds, parentGroupId, names, descriptions,
3164                                    params, andOperator);
3165                    }
3166    
3167                    List<Group> groups = doSearch(
3168                            companyId, classNameIds, parentGroupId, names, descriptions, params,
3169                            andOperator);
3170    
3171                    return groups.size();
3172            }
3173    
3174            /**
3175             * Returns the number of groups that match the class name IDs, and keywords,
3176             * optionally including the user's inherited organization groups and user
3177             * groups. System and staged groups are not included.
3178             *
3179             * @param  companyId the primary key of the company
3180             * @param  classNameIds the primary keys of the class names of the entities
3181             *         the groups are related to (optionally <code>null</code>)
3182             * @param  keywords the keywords (space separated), which may occur in the
3183             *         sites's name, or description (optionally <code>null</code>)
3184             * @param  params the finder params (optionally <code>null</code>). To
3185             *         include the user's inherited organization groups and user groups
3186             *         in the search, add entries having &quot;usersGroups&quot; and
3187             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
3188             *         information see {@link
3189             *         com.liferay.portal.service.persistence.GroupFinder}
3190             * @return the number of matching groups
3191             * @throws SystemException if a system exception occurred
3192             */
3193            @Override
3194            @ThreadLocalCachable
3195            public int searchCount(
3196                            long companyId, long[] classNameIds, String keywords,
3197                            LinkedHashMap<String, Object> params)
3198                    throws SystemException {
3199    
3200                    return searchCount(
3201                            companyId, classNameIds, GroupConstants.ANY_PARENT_GROUP_ID,
3202                            keywords, params);
3203            }
3204    
3205            /**
3206             * Returns the number of groups that match the class name IDs, name, and
3207             * description, optionally including the user's inherited organization
3208             * groups and user groups. System and staged groups are not included.
3209             *
3210             * @param  companyId the primary key of the company
3211             * @param  classNameIds the primary keys of the class names of the entities
3212             *         the groups are related to (optionally <code>null</code>)
3213             * @param  name the group's name (optionally <code>null</code>)
3214             * @param  description the group's description (optionally
3215             *         <code>null</code>)
3216             * @param  params the finder params (optionally <code>null</code>). To
3217             *         include the user's inherited organization groups and user groups
3218             *         in the search, add entries having &quot;usersGroups&quot; and
3219             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
3220             *         information see {@link
3221             *         com.liferay.portal.service.persistence.GroupFinder}
3222             * @param  andOperator whether every field must match its keywords, or just
3223             *         one field.
3224             * @return the number of matching groups
3225             * @throws SystemException if a system exception occurred
3226             */
3227            @Override
3228            @ThreadLocalCachable
3229            public int searchCount(
3230                            long companyId, long[] classNameIds, String name,
3231                            String description, LinkedHashMap<String, Object> params,
3232                            boolean andOperator)
3233                    throws SystemException {
3234    
3235                    return searchCount(
3236                            companyId, classNameIds, GroupConstants.ANY_PARENT_GROUP_ID, name,
3237                            description, params, andOperator);
3238            }
3239    
3240            /**
3241             * Returns the number of groups that match the keywords, optionally
3242             * including the user's inherited organization groups and user groups.
3243             * System and staged groups are not included.
3244             *
3245             * @param  companyId the primary key of the company
3246             * @param  keywords the keywords (space separated), which may occur in the
3247             *         sites's name, or description (optionally <code>null</code>)
3248             * @param  params the finder params (optionally <code>null</code>). To
3249             *         include the user's inherited organization groups and user groups
3250             *         in the search, add entries having &quot;usersGroups&quot; and
3251             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
3252             *         information see {@link
3253             *         com.liferay.portal.service.persistence.GroupFinder}
3254             * @return the number of matching groups
3255             * @throws SystemException if a system exception occurred
3256             */
3257            @Override
3258            @ThreadLocalCachable
3259            public int searchCount(
3260                            long companyId, String keywords,
3261                            LinkedHashMap<String, Object> params)
3262                    throws SystemException {
3263    
3264                    return searchCount(
3265                            companyId, getClassNameIds(), GroupConstants.ANY_PARENT_GROUP_ID,
3266                            keywords, params);
3267            }
3268    
3269            /**
3270             * Returns the number of groups and immediate organization groups that match
3271             * the name and description, optionally including the user's inherited
3272             * organization groups and user groups. System and staged groups are not
3273             * included.
3274             *
3275             * @param  companyId the primary key of the company
3276             * @param  name the group's name (optionally <code>null</code>)
3277             * @param  description the group's description (optionally
3278             *         <code>null</code>)
3279             * @param  params the finder params (optionally <code>null</code>). To
3280             *         include the user's inherited organization groups and user groups
3281             *         in the search, add entries having &quot;usersGroups&quot; and
3282             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
3283             *         information see {@link
3284             *         com.liferay.portal.service.persistence.GroupFinder}
3285             * @param  andOperator whether every field must match its keywords, or just
3286             *         one field.
3287             * @return the number of matching groups
3288             * @throws SystemException if a system exception occurred
3289             */
3290            @Override
3291            @ThreadLocalCachable
3292            public int searchCount(
3293                            long companyId, String name, String description,
3294                            LinkedHashMap<String, Object> params, boolean andOperator)
3295                    throws SystemException {
3296    
3297                    return searchCount(
3298                            companyId, getClassNameIds(), GroupConstants.ANY_PARENT_GROUP_ID,
3299                            name, description, params, andOperator);
3300            }
3301    
3302            /**
3303             * Sets the groups associated with the role, removing and adding
3304             * associations as necessary.
3305             *
3306             * @param  roleId the primary key of the role
3307             * @param  groupIds the primary keys of the groups
3308             * @throws SystemException if a system exception occurred
3309             */
3310            @Override
3311            public void setRoleGroups(long roleId, long[] groupIds)
3312                    throws SystemException {
3313    
3314                    rolePersistence.setGroups(roleId, groupIds);
3315    
3316                    PermissionCacheUtil.clearCache();
3317            }
3318    
3319            /**
3320             * Removes the groups from the role.
3321             *
3322             * @param  roleId the primary key of the role
3323             * @param  groupIds the primary keys of the groups
3324             * @throws SystemException if a system exception occurred
3325             */
3326            @Override
3327            public void unsetRoleGroups(long roleId, long[] groupIds)
3328                    throws SystemException {
3329    
3330                    rolePersistence.removeGroups(roleId, groupIds);
3331    
3332                    PermissionCacheUtil.clearCache();
3333            }
3334    
3335            /**
3336             * Removes the user from the groups.
3337             *
3338             * @param  userId the primary key of the user
3339             * @param  groupIds the primary keys of the groups
3340             * @throws SystemException if a system exception occurred
3341             */
3342            @Override
3343            public void unsetUserGroups(long userId, long[] groupIds)
3344                    throws SystemException {
3345    
3346                    userGroupRoleLocalService.deleteUserGroupRoles(userId, groupIds);
3347    
3348                    userPersistence.removeGroups(userId, groupIds);
3349    
3350                    PermissionCacheUtil.clearCache(userId);
3351            }
3352    
3353            /**
3354             * Updates the group's asset replacing categories and tag names.
3355             *
3356             * @param  userId the primary key of the user
3357             * @param  group the group
3358             * @param  assetCategoryIds the primary keys of the asset categories
3359             *         (optionally <code>null</code>)
3360             * @param  assetTagNames the asset tag names (optionally <code>null</code>)
3361             * @throws PortalException if a user with the primary key could not be found
3362             * @throws SystemException if a system exception occurred
3363             */
3364            @Override
3365            public void updateAsset(
3366                            long userId, Group group, long[] assetCategoryIds,
3367                            String[] assetTagNames)
3368                    throws PortalException, SystemException {
3369    
3370                    User user = userPersistence.findByPrimaryKey(userId);
3371    
3372                    Company company = companyPersistence.findByPrimaryKey(
3373                            user.getCompanyId());
3374    
3375                    Group companyGroup = company.getGroup();
3376    
3377                    assetEntryLocalService.updateEntry(
3378                            userId, companyGroup.getGroupId(), null, null,
3379                            Group.class.getName(), group.getGroupId(), null, 0,
3380                            assetCategoryIds, assetTagNames, false, null, null, null, null,
3381                            group.getDescriptiveName(), group.getDescription(), null, null,
3382                            null, 0, 0, null, false);
3383            }
3384    
3385            /**
3386             * Updates the group's friendly URL.
3387             *
3388             * @param  groupId the primary key of the group
3389             * @param  friendlyURL the group's new friendlyURL (optionally
3390             *         <code>null</code>)
3391             * @return the group
3392             * @throws PortalException if a group with the primary key could not be
3393             *         found or if a valid friendly URL could not be created for the
3394             *         group
3395             * @throws SystemException if a system exception occurred
3396             */
3397            @Override
3398            public Group updateFriendlyURL(long groupId, String friendlyURL)
3399                    throws PortalException, SystemException {
3400    
3401                    Group group = groupPersistence.findByPrimaryKey(groupId);
3402    
3403                    if (group.isUser()) {
3404                            User user = userPersistence.findByPrimaryKey(group.getClassPK());
3405    
3406                            friendlyURL = StringPool.SLASH + user.getScreenName();
3407    
3408                            if (group.getFriendlyURL().equals(friendlyURL)) {
3409                                    return group;
3410                            }
3411                    }
3412    
3413                    friendlyURL = getFriendlyURL(
3414                            group.getCompanyId(), groupId, group.getClassNameId(),
3415                            group.getClassPK(), StringPool.BLANK, friendlyURL);
3416    
3417                    validateFriendlyURL(
3418                            group.getCompanyId(), group.getGroupId(), group.getClassNameId(),
3419                            group.getClassPK(), friendlyURL);
3420    
3421                    group.setFriendlyURL(friendlyURL);
3422    
3423                    groupPersistence.update(group);
3424    
3425                    return group;
3426            }
3427    
3428            /**
3429             * Updates the group.
3430             *
3431             * @param  groupId the primary key of the group
3432             * @param  parentGroupId the primary key of the parent group
3433             * @param  name the group's new name
3434             * @param  description the group's new description (optionally
3435             *         <code>null</code>)
3436             * @param  type the group's new type. For more information see {@link
3437             *         com.liferay.portal.model.GroupConstants}
3438             * @param  friendlyURL the group's new friendlyURL (optionally
3439             *         <code>null</code>)
3440             * @param  active whether the group is active
3441             * @param  serviceContext the service context to be applied (optionally
3442             *         <code>null</code>). Can set asset category IDs and asset tag
3443             *         names for the group.
3444             * @return the group
3445             * @throws PortalException if a group with the primary key could not be
3446             *         found or if the friendly URL was invalid or could one not be
3447             *         created
3448             * @throws SystemException if a system exception occurred
3449             */
3450            @Override
3451            public Group updateGroup(
3452                            long groupId, long parentGroupId, String name, String description,
3453                            int type, boolean manualMembership, int membershipRestriction,
3454                            String friendlyURL, boolean active, ServiceContext serviceContext)
3455                    throws PortalException, SystemException {
3456    
3457                    Group group = groupPersistence.findByPrimaryKey(groupId);
3458    
3459                    String className = group.getClassName();
3460                    long classNameId = group.getClassNameId();
3461                    long classPK = group.getClassPK();
3462                    friendlyURL = getFriendlyURL(
3463                            group.getCompanyId(), groupId, classNameId, classPK,
3464                            StringPool.BLANK, friendlyURL);
3465    
3466                    if ((classNameId <= 0) || className.equals(Group.class.getName())) {
3467                            validateName(
3468                                    group.getGroupId(), group.getCompanyId(), name, group.isSite());
3469                    }
3470                    else if (className.equals(Organization.class.getName())) {
3471                            Organization organization =
3472                                    organizationPersistence.findByPrimaryKey(classPK);
3473    
3474                            name = getOrgGroupName(organization.getName());
3475                    }
3476                    else if (!GroupConstants.USER_PERSONAL_SITE.equals(name)) {
3477                            name = String.valueOf(classPK);
3478                    }
3479    
3480                    if (PortalUtil.isSystemGroup(group.getName()) &&
3481                            !name.equals(group.getName())) {
3482    
3483                            throw new RequiredGroupException(
3484                                    String.valueOf(group.getGroupId()),
3485                                    RequiredGroupException.SYSTEM_GROUP);
3486                    }
3487    
3488                    validateFriendlyURL(
3489                            group.getCompanyId(), group.getGroupId(), group.getClassNameId(),
3490                            group.getClassPK(), friendlyURL);
3491    
3492                    validateParentGroup(group.getGroupId(), parentGroupId);
3493    
3494                    group.setParentGroupId(parentGroupId);
3495                    group.setTreePath(group.buildTreePath());
3496                    group.setName(name);
3497                    group.setDescription(description);
3498                    group.setType(type);
3499                    group.setManualMembership(manualMembership);
3500                    group.setMembershipRestriction(membershipRestriction);
3501                    group.setFriendlyURL(friendlyURL);
3502                    group.setActive(active);
3503    
3504                    if ((serviceContext != null) && group.isSite()) {
3505                            group.setExpandoBridgeAttributes(serviceContext);
3506                    }
3507    
3508                    groupPersistence.update(group);
3509    
3510                    // Asset
3511    
3512                    if ((serviceContext == null) || !group.isSite()) {
3513                            return group;
3514                    }
3515    
3516                    User user = null;
3517    
3518                    user = userPersistence.fetchByPrimaryKey(group.getCreatorUserId());
3519    
3520                    if (user == null) {
3521                            user = userPersistence.fetchByPrimaryKey(
3522                                    serviceContext.getUserId());
3523                    }
3524    
3525                    if (user == null) {
3526                            user = userLocalService.getDefaultUser(group.getCompanyId());
3527                    }
3528    
3529                    updateAsset(
3530                            user.getUserId(), group, serviceContext.getAssetCategoryIds(),
3531                            serviceContext.getAssetTagNames());
3532    
3533                    return group;
3534            }
3535    
3536            /**
3537             * Updates the group's type settings.
3538             *
3539             * @param  groupId the primary key of the group
3540             * @param  typeSettings the group's new type settings (optionally
3541             *         <code>null</code>)
3542             * @return the group
3543             * @throws PortalException if a group with the primary key could not be
3544             *         found
3545             * @throws SystemException if a system exception occurred
3546             */
3547            @Override
3548            public Group updateGroup(long groupId, String typeSettings)
3549                    throws PortalException, SystemException {
3550    
3551                    Group group = groupPersistence.findByPrimaryKey(groupId);
3552    
3553                    UnicodeProperties oldTypeSettingsProperties =
3554                            group.getTypeSettingsProperties();
3555    
3556                    UnicodeProperties typeSettingsProperties = new UnicodeProperties(true);
3557    
3558                    typeSettingsProperties.fastLoad(typeSettings);
3559    
3560                    String newLanguageIds = typeSettingsProperties.getProperty(
3561                            PropsKeys.LOCALES);
3562    
3563                    if (Validator.isNotNull(newLanguageIds)) {
3564                            String oldLanguageIds = oldTypeSettingsProperties.getProperty(
3565                                    PropsKeys.LOCALES, StringPool.BLANK);
3566    
3567                            String defaultLanguageId = typeSettingsProperties.getProperty(
3568                                    "languageId", LocaleUtil.toLanguageId(LocaleUtil.getDefault()));
3569    
3570                            if (!Validator.equals(oldLanguageIds, newLanguageIds)) {
3571                                    validateLanguageIds(defaultLanguageId, newLanguageIds);
3572    
3573                                    LanguageUtil.resetAvailableGroupLocales(groupId);
3574                            }
3575                    }
3576    
3577                    group.setTypeSettings(typeSettings);
3578    
3579                    groupPersistence.update(group);
3580    
3581                    return group;
3582            }
3583    
3584            /**
3585             * Associates the group with a main site if the group is an organization.
3586             *
3587             * @param  groupId the primary key of the group
3588             * @param  site whether the group is to be associated with a main site
3589             * @return the group
3590             * @throws PortalException if a group with the primary key could not be
3591             *         found
3592             * @throws SystemException if a system exception occurred
3593             */
3594            @Override
3595            public Group updateSite(long groupId, boolean site)
3596                    throws PortalException, SystemException {
3597    
3598                    Group group = groupPersistence.findByPrimaryKey(groupId);
3599    
3600                    if (!group.isOrganization()) {
3601                            return group;
3602                    }
3603    
3604                    group.setSite(site);
3605    
3606                    groupPersistence.update(group);
3607    
3608                    return group;
3609            }
3610    
3611            protected void addControlPanelLayouts(Group group)
3612                    throws PortalException, SystemException {
3613    
3614                    long defaultUserId = userLocalService.getDefaultUserId(
3615                            group.getCompanyId());
3616    
3617                    String friendlyURL = getFriendlyURL(
3618                            PropsValues.CONTROL_PANEL_LAYOUT_FRIENDLY_URL);
3619    
3620                    ServiceContext serviceContext = new ServiceContext();
3621    
3622                    layoutLocalService.addLayout(
3623                            defaultUserId, group.getGroupId(), true,
3624                            LayoutConstants.DEFAULT_PARENT_LAYOUT_ID,
3625                            PropsValues.CONTROL_PANEL_LAYOUT_NAME, StringPool.BLANK,
3626                            StringPool.BLANK, LayoutConstants.TYPE_CONTROL_PANEL, false,
3627                            friendlyURL, serviceContext);
3628            }
3629    
3630            protected void addDefaultGuestPublicLayoutByProperties(Group group)
3631                    throws PortalException, SystemException {
3632    
3633                    List<Portlet> portlets = portletLocalService.getPortlets(
3634                            group.getCompanyId());
3635    
3636                    if (portlets.isEmpty()) {
3637    
3638                            // LPS-38457
3639    
3640                            return;
3641                    }
3642    
3643                    long defaultUserId = userLocalService.getDefaultUserId(
3644                            group.getCompanyId());
3645                    String friendlyURL = getFriendlyURL(
3646                            PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_FRIENDLY_URL);
3647    
3648                    ServiceContext serviceContext = new ServiceContext();
3649    
3650                    Layout layout = layoutLocalService.addLayout(
3651                            defaultUserId, group.getGroupId(), false,
3652                            LayoutConstants.DEFAULT_PARENT_LAYOUT_ID,
3653                            PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_NAME, StringPool.BLANK,
3654                            StringPool.BLANK, LayoutConstants.TYPE_PORTLET, false, friendlyURL,
3655                            serviceContext);
3656    
3657                    LayoutTypePortlet layoutTypePortlet =
3658                            (LayoutTypePortlet)layout.getLayoutType();
3659    
3660                    layoutTypePortlet.setLayoutTemplateId(
3661                            0, PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_TEMPLATE_ID, false);
3662    
3663                    LayoutTemplate layoutTemplate = layoutTypePortlet.getLayoutTemplate();
3664    
3665                    for (String columnId : layoutTemplate.getColumns()) {
3666                            String keyPrefix = PropsKeys.DEFAULT_GUEST_PUBLIC_LAYOUT_PREFIX;
3667    
3668                            String portletIds = PropsUtil.get(keyPrefix.concat(columnId));
3669    
3670                            layoutTypePortlet.addPortletIds(
3671                                    0, StringUtil.split(portletIds), columnId, false);
3672                    }
3673    
3674                    layoutLocalService.updateLayout(
3675                            layout.getGroupId(), layout.isPrivateLayout(), layout.getLayoutId(),
3676                            layout.getTypeSettings());
3677    
3678                    boolean updateLayoutSet = false;
3679    
3680                    LayoutSet layoutSet = layout.getLayoutSet();
3681    
3682                    if (Validator.isNotNull(
3683                                    PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_REGULAR_THEME_ID)) {
3684    
3685                            layoutSet.setThemeId(
3686                                    PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_REGULAR_THEME_ID);
3687    
3688                            updateLayoutSet = true;
3689                    }
3690    
3691                    if (Validator.isNotNull(
3692                                    PropsValues.
3693                                            DEFAULT_GUEST_PUBLIC_LAYOUT_REGULAR_COLOR_SCHEME_ID)) {
3694    
3695                            layoutSet.setColorSchemeId(
3696                                    PropsValues.
3697                                            DEFAULT_GUEST_PUBLIC_LAYOUT_REGULAR_COLOR_SCHEME_ID);
3698    
3699                            updateLayoutSet = true;
3700                    }
3701    
3702                    if (Validator.isNotNull(
3703                                    PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_WAP_THEME_ID)) {
3704    
3705                            layoutSet.setWapThemeId(
3706                                    PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_WAP_THEME_ID);
3707    
3708                            updateLayoutSet = true;
3709                    }
3710    
3711                    if (Validator.isNotNull(
3712                                    PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_WAP_COLOR_SCHEME_ID)) {
3713    
3714                            layoutSet.setWapColorSchemeId(
3715                                    PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_WAP_COLOR_SCHEME_ID);
3716    
3717                            updateLayoutSet = true;
3718                    }
3719    
3720                    if (updateLayoutSet) {
3721                            layoutSetLocalService.updateLayoutSet(layoutSet);
3722                    }
3723            }
3724    
3725            protected void addDefaultGuestPublicLayouts(Group group)
3726                    throws PortalException, SystemException {
3727    
3728                    if (publicLARFile != null) {
3729                            addDefaultGuestPublicLayoutsByLAR(group, publicLARFile);
3730                    }
3731                    else {
3732                            addDefaultGuestPublicLayoutByProperties(group);
3733                    }
3734            }
3735    
3736            protected void addDefaultGuestPublicLayoutsByLAR(Group group, File larFile)
3737                    throws PortalException, SystemException {
3738    
3739                    long defaultUserId = userLocalService.getDefaultUserId(
3740                            group.getCompanyId());
3741    
3742                    Map<String, String[]> parameterMap = new HashMap<String, String[]>();
3743    
3744                    parameterMap.put(
3745                            PortletDataHandlerKeys.CATEGORIES,
3746                            new String[] {Boolean.TRUE.toString()});
3747                    parameterMap.put(
3748                            PortletDataHandlerKeys.PERMISSIONS,
3749                            new String[] {Boolean.TRUE.toString()});
3750                    parameterMap.put(
3751                            PortletDataHandlerKeys.PORTLET_CONFIGURATION,
3752                            new String[] {Boolean.TRUE.toString()});
3753                    parameterMap.put(
3754                            PortletDataHandlerKeys.PORTLET_DATA,
3755                            new String[] {Boolean.TRUE.toString()});
3756                    parameterMap.put(
3757                            PortletDataHandlerKeys.PORTLET_DATA_CONTROL_DEFAULT,
3758                            new String[] {Boolean.TRUE.toString()});
3759    
3760                    layoutLocalService.importLayouts(
3761                            defaultUserId, group.getGroupId(), false, parameterMap, larFile);
3762            }
3763    
3764            protected void deletePortletData(Group group)
3765                    throws PortalException, SystemException {
3766    
3767                    List<Portlet> portlets = portletLocalService.getPortlets(
3768                            group.getCompanyId());
3769    
3770                    for (Portlet portlet : portlets) {
3771                            if (!portlet.isActive()) {
3772                                    continue;
3773                            }
3774    
3775                            PortletDataHandler portletDataHandler =
3776                                    portlet.getPortletDataHandlerInstance();
3777    
3778                            if ((portletDataHandler == null) ||
3779                                    portletDataHandler.isDataPortalLevel()) {
3780    
3781                                    continue;
3782                            }
3783    
3784                            PortletDataContext portletDataContext =
3785                                    PortletDataContextFactoryUtil.createExportPortletDataContext(
3786                                            group.getCompanyId(), group.getGroupId(),
3787                                            (Map<String, String[]>)null, (Date)null, (Date)null,
3788                                            (ZipWriter)null);
3789    
3790                            // For now, we are going to throw an exception if one portlet data
3791                            // handler has an exception to ensure that the transaction is rolled
3792                            // back for data integrity. We may decide that this is not the best
3793                            // behavior in the future because a bad plugin could disallow
3794                            // deletion of groups.
3795    
3796                            //try {
3797                                    portletDataHandler.deleteData(
3798                                            portletDataContext, portlet.getPortletId(), null);
3799                            /*}
3800                            catch (Exception e) {
3801                                    _log.error(
3802                                            "Unable to delete data for portlet " +
3803                                                    portlet.getPortletId() + " in group " +
3804                                                            group.getGroupId());
3805                            }*/
3806                    }
3807            }
3808    
3809            protected List<Group> doSearch(
3810                            long companyId, long[] classNameIds, long parentGroupId,
3811                            String[] names, String[] descriptions,
3812                            LinkedHashMap<String, Object> params, boolean andOperator)
3813                    throws SystemException {
3814    
3815                    boolean parentGroupIdEquals = true;
3816    
3817                    if (parentGroupId == GroupConstants.ANY_PARENT_GROUP_ID) {
3818                            parentGroupIdEquals = false;
3819                    }
3820    
3821                    params = new LinkedHashMap<String, Object>(params);
3822    
3823                    Boolean active = (Boolean)params.remove("active");
3824                    List<Long> excludedGroupIds = (List<Long>)params.remove(
3825                            "excludedGroupIds");
3826                    List<Group> groupsTree = (List<Group>)params.remove("groupsTree");
3827                    Boolean manualMembership = (Boolean)params.remove("manualMembership");
3828                    Integer membershipRestriction = (Integer)params.remove(
3829                            "membershipRestriction");
3830                    Boolean site = (Boolean)params.remove("site");
3831                    List<Integer> types = (List<Integer>)params.remove("types");
3832    
3833                    Collection<Group> groups = new HashSet<Group>();
3834    
3835                    Long userId = (Long)params.remove("usersGroups");
3836    
3837                    for (long classNameId : classNameIds) {
3838                            groups.addAll(groupPersistence.findByC_C(companyId, classNameId));
3839                    }
3840    
3841                    Iterator<Group> iterator = groups.iterator();
3842    
3843                    while (iterator.hasNext()) {
3844                            Group group = iterator.next();
3845    
3846                            // Filter by live group ID
3847    
3848                            long liveGroupId = group.getLiveGroupId();
3849    
3850                            if (liveGroupId != 0) {
3851                                    iterator.remove();
3852    
3853                                    continue;
3854                            }
3855    
3856                            // Filter by parent group ID
3857    
3858                            long groupParentGroupId = group.getParentGroupId();
3859    
3860                            if ((parentGroupIdEquals &&
3861                                     (groupParentGroupId != parentGroupId)) ||
3862                                    (!parentGroupIdEquals &&
3863                                     (groupParentGroupId == parentGroupId))) {
3864    
3865                                    iterator.remove();
3866    
3867                                    continue;
3868                            }
3869    
3870                            // Filter by name and description
3871    
3872                            String name = group.getName();
3873    
3874                            if (name.equals(GroupConstants.CONTROL_PANEL)) {
3875                                    iterator.remove();
3876    
3877                                    continue;
3878                            }
3879    
3880                            boolean containsName = matches(name, names);
3881                            boolean containsDescription = matches(
3882                                    group.getDescription(), descriptions);
3883    
3884                            if ((andOperator && (!containsName || !containsDescription)) ||
3885                                    (!andOperator && (!containsName && !containsDescription))) {
3886    
3887                                    iterator.remove();
3888    
3889                                    continue;
3890                            }
3891    
3892                            // Filter by active
3893    
3894                            if (active != null) {
3895                                    if (active != isLiveGroupActive(group)) {
3896                                            iterator.remove();
3897    
3898                                            continue;
3899                                    }
3900                            }
3901    
3902                            // Filter by excluded group IDs
3903    
3904                            if ((excludedGroupIds != null) &&
3905                                    excludedGroupIds.contains(group.getGroupId())) {
3906    
3907                                    iterator.remove();
3908    
3909                                    continue;
3910                            }
3911    
3912                            // Filter by groups tree
3913    
3914                            if (groupsTree != null) {
3915                                    String treePath = group.getTreePath();
3916    
3917                                    boolean matched = false;
3918    
3919                                    for (Group groupTree : groupsTree) {
3920                                            String groupTreePath = StringUtil.quote(
3921                                                    String.valueOf(groupTree.getGroupId()),
3922                                                    StringPool.SLASH);
3923    
3924                                            if (treePath.contains(groupTreePath)) {
3925                                                    matched = true;
3926    
3927                                                    break;
3928                                            }
3929                                    }
3930    
3931                                    if (!matched) {
3932                                            iterator.remove();
3933    
3934                                            continue;
3935                                    }
3936                            }
3937    
3938                            // Filter by manual membership
3939    
3940                            if ((manualMembership != null) &&
3941                                    (manualMembership != group.isManualMembership())) {
3942    
3943                                    iterator.remove();
3944    
3945                                    continue;
3946                            }
3947    
3948                            // Filter by membership restriction
3949    
3950                            if ((membershipRestriction != null) &&
3951                                    (membershipRestriction != group.getMembershipRestriction())) {
3952    
3953                                    iterator.remove();
3954    
3955                                    continue;
3956                            }
3957    
3958                            // Filter by site
3959    
3960                            if (site != null) {
3961                                    if (site != group.isSite()) {
3962                                            iterator.remove();
3963    
3964                                            continue;
3965                                    }
3966                            }
3967    
3968                            // Filter by type and types
3969    
3970                            int type = group.getType();
3971    
3972                            if (type == 4) {
3973                                    iterator.remove();
3974    
3975                                    continue;
3976                            }
3977    
3978                            if ((types != null) && !types.contains(type)) {
3979                                    iterator.remove();
3980    
3981                                    continue;
3982                            }
3983                    }
3984    
3985                    // Join by role permissions
3986    
3987                    List<?> rolePermissions = (List<?>)params.remove("rolePermissions");
3988    
3989                    if (rolePermissions != null) {
3990                            String resourceName = (String)rolePermissions.get(0);
3991                            Integer resourceScope = (Integer)rolePermissions.get(1);
3992                            String resourceActionId = (String)rolePermissions.get(2);
3993                            Long resourceRoleId = (Long)rolePermissions.get(3);
3994    
3995                            ResourceAction resourceAction =
3996                                    resourceActionLocalService.fetchResourceAction(
3997                                            resourceName, resourceActionId);
3998    
3999                            if (resourceAction != null) {
4000                                    Set<Group> rolePermissionsGroups = new HashSet<Group>();
4001    
4002                                    if (resourceBlockLocalService.isSupported(resourceName)) {
4003                                            List<ResourceTypePermission> resourceTypePermissions =
4004                                                    resourceTypePermissionPersistence.findByRoleId(
4005                                                            resourceRoleId);
4006    
4007                                            for (ResourceTypePermission resourceTypePermission :
4008                                                            resourceTypePermissions) {
4009    
4010                                                    if ((resourceTypePermission.getCompanyId() ==
4011                                                                    companyId) &&
4012                                                            resourceName.equals(
4013                                                                    resourceTypePermission.getName()) &&
4014                                                            ((resourceTypePermission.getActionIds() &
4015                                                              resourceAction.getBitwiseValue()) != 0)) {
4016    
4017                                                            Group group = groupPersistence.fetchByPrimaryKey(
4018                                                                    resourceTypePermission.getGroupId());
4019    
4020                                                            if (group != null) {
4021                                                                    rolePermissionsGroups.add(group);
4022                                                            }
4023                                                    }
4024                                            }
4025                                    }
4026                                    else {
4027                                            List<ResourcePermission> resourcePermissions =
4028                                                    resourcePermissionPersistence.findByC_N_S(
4029                                                            companyId, resourceName, resourceScope);
4030    
4031                                            for (ResourcePermission resourcePermission :
4032                                                            resourcePermissions) {
4033    
4034                                                    if ((resourcePermission.getRoleId() ==
4035                                                                    resourceRoleId) &&
4036                                                            ((resourcePermission.getActionIds() &
4037                                                              resourceAction.getBitwiseValue()) != 0)) {
4038    
4039                                                            Group group = groupPersistence.fetchByPrimaryKey(
4040                                                                    GetterUtil.getLong(
4041                                                                            resourcePermission.getPrimKey()));
4042    
4043                                                            if (group != null) {
4044                                                                    rolePermissionsGroups.add(group);
4045                                                            }
4046                                                    }
4047                                            }
4048                                    }
4049    
4050                                    groups.retainAll(rolePermissionsGroups);
4051                            }
4052                    }
4053    
4054                    if (userId == null) {
4055                            return new ArrayList<Group>(groups);
4056                    }
4057    
4058                    // Join by Users_Groups
4059    
4060                    Set<Group> joinedGroups = new HashSet<Group>(
4061                            userPersistence.getGroups(userId));
4062    
4063                    boolean inherit = GetterUtil.getBoolean(params.remove("inherit"), true);
4064    
4065                    if (inherit) {
4066    
4067                            // Join by Users_Orgs
4068    
4069                            List<Organization> organizations = userPersistence.getOrganizations(
4070                                    userId);
4071    
4072                            for (Organization organization : organizations) {
4073                                    long organizationId = organization.getOrganizationId();
4074    
4075                                    for (Group group : groups) {
4076                                            if (organizationId == group.getClassPK()) {
4077                                                    joinedGroups.add(group);
4078                                            }
4079                                    }
4080                            }
4081    
4082                            // Join by Groups_Orgs and Users_Orgs
4083    
4084                            for (Organization organization : organizations) {
4085                                    joinedGroups.addAll(
4086                                            organizationPersistence.getGroups(
4087                                                    organization.getOrganizationId()));
4088                            }
4089    
4090                            // Join by Groups_UserGroups and Users_UserGroups
4091    
4092                            List<UserGroup> userGroups = userPersistence.getUserGroups(userId);
4093    
4094                            for (UserGroup userGroup : userGroups) {
4095                                    joinedGroups.addAll(
4096                                            userGroupPersistence.getGroups(userGroup.getUserGroupId()));
4097                            }
4098                    }
4099    
4100                    if (_log.isDebugEnabled() && !params.isEmpty()) {
4101                            _log.debug("Unprocessed parameters " + MapUtil.toString(params));
4102                    }
4103    
4104                    // Join by Groups_Roles
4105    
4106                    Long roleId = (Long)params.remove("groupsRoles");
4107    
4108                    if (roleId != null) {
4109                            joinedGroups.retainAll(rolePersistence.getGroups(roleId));
4110                    }
4111    
4112                    if (joinedGroups.size() > groups.size()) {
4113                            groups.retainAll(joinedGroups);
4114    
4115                            return new ArrayList<Group>(groups);
4116                    }
4117                    else {
4118                            joinedGroups.retainAll(groups);
4119    
4120                            return new ArrayList<Group>(joinedGroups);
4121                    }
4122            }
4123    
4124            protected long[] getClassNameIds() {
4125                    if (_classNameIds == null) {
4126                            _classNameIds = new long[] {
4127                                    classNameLocalService.getClassNameId(Group.class),
4128                                    classNameLocalService.getClassNameId(Organization.class)
4129                            };
4130                    }
4131    
4132                    return _classNameIds;
4133            }
4134    
4135            protected String getFriendlyURL(
4136                            long companyId, long groupId, long classNameId, long classPK,
4137                            String friendlyName, String friendlyURL)
4138                    throws PortalException, SystemException {
4139    
4140                    friendlyURL = getFriendlyURL(friendlyURL);
4141    
4142                    if (Validator.isNotNull(friendlyURL)) {
4143                            return friendlyURL;
4144                    }
4145    
4146                    friendlyURL = StringPool.SLASH + getFriendlyURL(friendlyName);
4147    
4148                    String originalFriendlyURL = friendlyURL;
4149    
4150                    for (int i = 1;; i++) {
4151                            try {
4152                                    validateFriendlyURL(
4153                                            companyId, groupId, classNameId, classPK, friendlyURL);
4154    
4155                                    break;
4156                            }
4157                            catch (GroupFriendlyURLException gfurle) {
4158                                    int type = gfurle.getType();
4159    
4160                                    if (type == GroupFriendlyURLException.DUPLICATE) {
4161                                            friendlyURL = originalFriendlyURL + i;
4162                                    }
4163                                    else {
4164                                            friendlyURL = StringPool.SLASH + classPK;
4165    
4166                                            break;
4167                                    }
4168                            }
4169                    }
4170    
4171                    return friendlyURL;
4172            }
4173    
4174            protected String getFriendlyURL(String friendlyURL) {
4175                    return FriendlyURLNormalizerUtil.normalize(friendlyURL);
4176            }
4177    
4178            protected String getOrgGroupName(String name) {
4179                    return name + ORGANIZATION_NAME_SUFFIX;
4180            }
4181    
4182            protected String[] getSearchNames(long companyId, String name)
4183                    throws SystemException {
4184    
4185                    if (Validator.isNull(name)) {
4186                            return new String[] {null};
4187                    }
4188    
4189                    Company company = companyPersistence.fetchByPrimaryKey(companyId);
4190    
4191                    if (company == null) {
4192                            return CustomSQLUtil.keywords(name);
4193                    }
4194    
4195                    Account account = accountPersistence.fetchByPrimaryKey(
4196                            company.getAccountId());
4197    
4198                    if (account == null) {
4199                            return CustomSQLUtil.keywords(name);
4200                    }
4201    
4202                    String companyName = account.getName();
4203    
4204                    if (StringUtil.wildcardMatches(
4205                                    companyName, name, CharPool.UNDERLINE, CharPool.PERCENT,
4206                                    CharPool.BACK_SLASH, false)) {
4207    
4208                            String[] searchNames = CustomSQLUtil.keywords(name);
4209    
4210                            String guestName = StringUtil.quote(
4211                                    StringUtil.toLowerCase(GroupConstants.GUEST),
4212                                    StringPool.PERCENT);
4213    
4214                            return ArrayUtil.append(searchNames, guestName);
4215                    }
4216    
4217                    return CustomSQLUtil.keywords(name);
4218            }
4219    
4220            protected void initImportLARFile() {
4221                    String publicLARFileName = PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUTS_LAR;
4222    
4223                    if (_log.isDebugEnabled()) {
4224                            _log.debug("Reading public LAR file " + publicLARFileName);
4225                    }
4226    
4227                    if (Validator.isNotNull(publicLARFileName)) {
4228                            publicLARFile = new File(publicLARFileName);
4229    
4230                            if (!publicLARFile.exists()) {
4231                                    _log.error(
4232                                            "Public LAR file " + publicLARFile + " does not exist");
4233    
4234                                    publicLARFile = null;
4235                            }
4236                            else {
4237                                    if (_log.isDebugEnabled()) {
4238                                            _log.debug("Using public LAR file " + publicLARFileName);
4239                                    }
4240                            }
4241                    }
4242            }
4243    
4244            protected void initUserPersonalSitePermissions(Group group)
4245                    throws PortalException, SystemException {
4246    
4247                    // User role
4248    
4249                    Role role = roleLocalService.getRole(
4250                            group.getCompanyId(), RoleConstants.USER);
4251    
4252                    setRolePermissions(
4253                            group, role, Layout.class.getName(),
4254                            new String[] {ActionKeys.VIEW});
4255    
4256                    setRolePermissions(
4257                            group, role, "com.liferay.portlet.blogs",
4258                            new String[] {
4259                                    ActionKeys.ADD_ENTRY, ActionKeys.PERMISSIONS,
4260                                    ActionKeys.SUBSCRIBE});
4261    
4262                    // Power User role
4263    
4264                    role = roleLocalService.getRole(
4265                            group.getCompanyId(), RoleConstants.POWER_USER);
4266    
4267                    List<Portlet> portlets = portletLocalService.getPortlets(
4268                            group.getCompanyId(), false, false);
4269    
4270                    for (Portlet portlet : portlets) {
4271                            List<String> actions =
4272                                    ResourceActionsUtil.getPortletResourceActions(
4273                                            portlet.getPortletId());
4274    
4275                            String controlPanelEntryCategory = GetterUtil.getString(
4276                                    portlet.getControlPanelEntryCategory());
4277    
4278                            if (actions.contains(ActionKeys.ACCESS_IN_CONTROL_PANEL) &&
4279                                    controlPanelEntryCategory.startsWith(
4280                                            PortletCategoryKeys.SITE_ADMINISTRATION)) {
4281    
4282                                    setRolePermissions(
4283                                            group, role, portlet.getPortletId(),
4284                                            new String[] {ActionKeys.ACCESS_IN_CONTROL_PANEL});
4285                            }
4286                    }
4287    
4288                    setRolePermissions(
4289                            group, role, Group.class.getName(),
4290                            new String[] {
4291                                    ActionKeys.MANAGE_LAYOUTS, ActionKeys.VIEW_SITE_ADMINISTRATION
4292                            });
4293    
4294                    setRolePermissions(group, role, "com.liferay.portlet.asset");
4295                    setRolePermissions(group, role, "com.liferay.portlet.blogs");
4296                    setRolePermissions(group, role, "com.liferay.portlet.bookmarks");
4297                    setRolePermissions(group, role, "com.liferay.portlet.documentlibrary");
4298                    setRolePermissions(group, role, "com.liferay.portlet.imagegallery");
4299                    setRolePermissions(group, role, "com.liferay.portlet.journal");
4300                    setRolePermissions(group, role, "com.liferay.portlet.messageboards");
4301                    setRolePermissions(group, role, "com.liferay.portlet.polls");
4302                    setRolePermissions(group, role, "com.liferay.portlet.wiki");
4303            }
4304    
4305            protected boolean isParentGroup(long parentGroupId, long groupId)
4306                    throws PortalException, SystemException {
4307    
4308                    // Return true if parentGroupId is among the parent groups of groupId
4309    
4310                    if (groupId == GroupConstants.DEFAULT_PARENT_GROUP_ID) {
4311                            return false;
4312                    }
4313    
4314                    Group group = groupPersistence.findByPrimaryKey(groupId);
4315    
4316                    String treePath = group.getTreePath();
4317    
4318                    if (treePath.contains(
4319                                    StringPool.SLASH + parentGroupId + StringPool.SLASH)) {
4320    
4321                            return true;
4322                    }
4323                    else {
4324                            return false;
4325                    }
4326            }
4327    
4328            protected boolean isStaging(ServiceContext serviceContext) {
4329                    if (serviceContext != null) {
4330                            return ParamUtil.getBoolean(serviceContext, "staging");
4331                    }
4332    
4333                    return false;
4334            }
4335    
4336            protected boolean isUseComplexSQL(long[] classNameIds) {
4337                    if (ArrayUtil.isEmpty(classNameIds)) {
4338                            return true;
4339                    }
4340    
4341                    if (_complexSQLClassNameIds == null) {
4342                            String[] complexSQLClassNames =
4343                                    PropsValues.GROUPS_COMPLEX_SQL_CLASS_NAMES;
4344    
4345                            long[] complexSQLClassNameIds =
4346                                    new long[complexSQLClassNames.length];
4347    
4348                            for (int i = 0; i < complexSQLClassNames.length; i++) {
4349                                    String complexSQLClassName = complexSQLClassNames[i];
4350    
4351                                    complexSQLClassNameIds[i] = PortalUtil.getClassNameId(
4352                                            complexSQLClassName);
4353                            }
4354    
4355                            _complexSQLClassNameIds = complexSQLClassNameIds;
4356                    }
4357    
4358                    for (long classNameId : classNameIds) {
4359                            if (ArrayUtil.contains(_complexSQLClassNameIds, classNameId)) {
4360                                    return true;
4361                            }
4362                    }
4363    
4364                    return false;
4365            }
4366    
4367            protected boolean matches(String s, String[] keywords) {
4368                    if ((keywords == null) ||
4369                            ((keywords.length == 1) && (keywords[0] == null))) {
4370    
4371                            return true;
4372                    }
4373    
4374                    for (String keyword : keywords) {
4375                            if (StringUtil.wildcardMatches(
4376                                            s, keyword, CharPool.UNDERLINE, CharPool.PERCENT,
4377                                            CharPool.BACK_SLASH, false)) {
4378    
4379                                    return true;
4380                            }
4381                    }
4382    
4383                    return false;
4384            }
4385    
4386            protected void setCompanyPermissions(
4387                            Role role, String name, String[] actionIds)
4388                    throws PortalException, SystemException {
4389    
4390                    if (resourceBlockLocalService.isSupported(name)) {
4391                            resourceBlockLocalService.setCompanyScopePermissions(
4392                                    role.getCompanyId(), name, role.getRoleId(),
4393                                    Arrays.asList(actionIds));
4394                    }
4395                    else {
4396                            resourcePermissionLocalService.setResourcePermissions(
4397                                    role.getCompanyId(), name, ResourceConstants.SCOPE_COMPANY,
4398                                    String.valueOf(role.getCompanyId()), role.getRoleId(),
4399                                    actionIds);
4400                    }
4401            }
4402    
4403            protected void setRolePermissions(Group group, Role role, String name)
4404                    throws PortalException, SystemException {
4405    
4406                    List<String> actions = ResourceActionsUtil.getModelResourceActions(
4407                            name);
4408    
4409                    setRolePermissions(
4410                            group, role, name, actions.toArray(new String[actions.size()]));
4411            }
4412    
4413            protected void setRolePermissions(
4414                            Group group, Role role, String name, String[] actionIds)
4415                    throws PortalException, SystemException {
4416    
4417                    if (resourceBlockLocalService.isSupported(name)) {
4418                            resourceBlockLocalService.setGroupScopePermissions(
4419                                    role.getCompanyId(), group.getGroupId(), name, role.getRoleId(),
4420                                    Arrays.asList(actionIds));
4421                    }
4422                    else {
4423                            resourcePermissionLocalService.setResourcePermissions(
4424                                    group.getCompanyId(), name, ResourceConstants.SCOPE_GROUP,
4425                                    String.valueOf(group.getGroupId()), role.getRoleId(),
4426                                    actionIds);
4427                    }
4428            }
4429    
4430            protected List<Group> sort(
4431                    List<Group> groups, int start, int end, OrderByComparator obc) {
4432    
4433                    if (obc == null) {
4434                            obc = new GroupNameComparator(true);
4435                    }
4436    
4437                    Collections.sort(groups, obc);
4438    
4439                    return Collections.unmodifiableList(
4440                            ListUtil.subList(groups, start, end));
4441            }
4442    
4443            protected void unscheduleStaging(Group group) {
4444                    try {
4445    
4446                            // Remote publishing
4447    
4448                            String groupName = StagingUtil.getSchedulerGroupName(
4449                                    DestinationNames.LAYOUTS_REMOTE_PUBLISHER, group.getGroupId());
4450    
4451                            SchedulerEngineHelperUtil.delete(groupName, StorageType.PERSISTED);
4452    
4453                            long liveGroupId = 0;
4454                            long stagingGroupId = 0;
4455    
4456                            if (group.isStagingGroup()) {
4457                                    liveGroupId = group.getLiveGroupId();
4458    
4459                                    stagingGroupId = group.getGroupId();
4460                            }
4461                            else if (group.hasStagingGroup()) {
4462                                    liveGroupId = group.getGroupId();
4463    
4464                                    stagingGroupId = group.getStagingGroup().getGroupId();
4465                            }
4466    
4467                            if ((liveGroupId != 0) && (stagingGroupId != 0)) {
4468    
4469                                    // Publish to live
4470    
4471                                    groupName = StagingUtil.getSchedulerGroupName(
4472                                            DestinationNames.LAYOUTS_LOCAL_PUBLISHER, liveGroupId);
4473    
4474                                    SchedulerEngineHelperUtil.delete(
4475                                            groupName, StorageType.PERSISTED);
4476    
4477                                    // Copy from live
4478    
4479                                    groupName = StagingUtil.getSchedulerGroupName(
4480                                            DestinationNames.LAYOUTS_LOCAL_PUBLISHER, stagingGroupId);
4481    
4482                                    SchedulerEngineHelperUtil.delete(
4483                                            groupName, StorageType.PERSISTED);
4484                            }
4485                    }
4486                    catch (Exception e) {
4487                            _log.error(
4488                                    "Unable to unschedule events for group: " + group.getGroupId());
4489                    }
4490            }
4491    
4492            protected void validateFriendlyURL(
4493                            long companyId, long groupId, long classNameId, long classPK,
4494                            String friendlyURL)
4495                    throws PortalException, SystemException {
4496    
4497                    Company company = companyPersistence.findByPrimaryKey(companyId);
4498    
4499                    if (company.isSystem()) {
4500                            return;
4501                    }
4502    
4503                    if (Validator.isNull(friendlyURL)) {
4504                            return;
4505                    }
4506    
4507                    int exceptionType = LayoutImpl.validateFriendlyURL(friendlyURL);
4508    
4509                    if (exceptionType != -1) {
4510                            throw new GroupFriendlyURLException(exceptionType);
4511                    }
4512    
4513                    Group group = groupPersistence.fetchByC_F(companyId, friendlyURL);
4514    
4515                    if ((group != null) && (group.getGroupId() != groupId)) {
4516                            throw new GroupFriendlyURLException(
4517                                    GroupFriendlyURLException.DUPLICATE);
4518                    }
4519    
4520                    String groupIdFriendlyURL = friendlyURL.substring(1);
4521    
4522                    if (Validator.isNumber(groupIdFriendlyURL)) {
4523                            long groupClassNameId = PortalUtil.getClassNameId(Group.class);
4524    
4525                            if (((classNameId != groupClassNameId) &&
4526                                     !groupIdFriendlyURL.equals(String.valueOf(classPK)) &&
4527                                     !PropsValues.USERS_SCREEN_NAME_ALLOW_NUMERIC) ||
4528                                    ((classNameId == groupClassNameId) &&
4529                                     !groupIdFriendlyURL.equals(String.valueOf(groupId)))) {
4530    
4531                                    GroupFriendlyURLException gfurle =
4532                                            new GroupFriendlyURLException(
4533                                                    GroupFriendlyURLException.POSSIBLE_DUPLICATE);
4534    
4535                                    gfurle.setKeywordConflict(groupIdFriendlyURL);
4536    
4537                                    throw gfurle;
4538                            }
4539                    }
4540    
4541                    String screenName = friendlyURL.substring(1);
4542    
4543                    User user = userPersistence.fetchByC_SN(companyId, screenName);
4544    
4545                    if (user != null) {
4546                            long userClassNameId = PortalUtil.getClassNameId(User.class);
4547    
4548                            if ((classNameId == userClassNameId) &&
4549                                    (classPK == user.getUserId())) {
4550                            }
4551                            else {
4552                                    throw new GroupFriendlyURLException(
4553                                            GroupFriendlyURLException.DUPLICATE);
4554                            }
4555                    }
4556    
4557                    if (StringUtil.count(friendlyURL, StringPool.SLASH) > 1) {
4558                            throw new GroupFriendlyURLException(
4559                                    GroupFriendlyURLException.TOO_DEEP);
4560                    }
4561            }
4562    
4563            protected void validateLanguageIds(
4564                            String defaultLanguageId, String languageIds)
4565                    throws PortalException {
4566    
4567                    Locale[] availableLocales = LanguageUtil.getAvailableLocales();
4568    
4569                    String[] availableLanguageIds = LocaleUtil.toLanguageIds(
4570                            availableLocales);
4571    
4572                    String[] languageIdsArray = StringUtil.split(languageIds);
4573    
4574                    for (String languageId : languageIdsArray) {
4575                            if (!ArrayUtil.contains(availableLanguageIds, languageId)) {
4576                                    LocaleException le = new LocaleException(
4577                                            LocaleException.TYPE_DISPLAY_SETTINGS);
4578    
4579                                    le.setSourceAvailableLocales(availableLocales);
4580                                    le.setTargetAvailableLocales(
4581                                            LocaleUtil.fromLanguageIds(languageIdsArray));
4582    
4583                                    throw le;
4584                            }
4585                    }
4586    
4587                    if (!ArrayUtil.contains(languageIdsArray, defaultLanguageId)) {
4588                            LocaleException le = new LocaleException(
4589                                    LocaleException.TYPE_DEFAULT);
4590    
4591                            le.setSourceAvailableLocales(availableLocales);
4592                            le.setTargetAvailableLocales(
4593                                    LocaleUtil.fromLanguageIds(languageIdsArray));
4594    
4595                            throw le;
4596                    }
4597            }
4598    
4599            protected void validateName(
4600                            long groupId, long companyId, String name, boolean site)
4601                    throws PortalException, SystemException {
4602    
4603                    if (Validator.isNull(name) || Validator.isNumber(name) ||
4604                            name.contains(StringPool.STAR) ||
4605                            name.contains(ORGANIZATION_NAME_SUFFIX)) {
4606    
4607                            throw new GroupNameException();
4608                    }
4609    
4610                    try {
4611                            Group group = groupFinder.findByC_N(companyId, name);
4612    
4613                            if ((groupId <= 0) || (group.getGroupId() != groupId)) {
4614                                    throw new DuplicateGroupException("{groupId=" + groupId + "}");
4615                            }
4616                    }
4617                    catch (NoSuchGroupException nsge) {
4618                    }
4619    
4620                    if (site) {
4621                            Company company = companyLocalService.getCompany(companyId);
4622    
4623                            if (name.equals(company.getName())) {
4624                                    throw new DuplicateGroupException();
4625                            }
4626                    }
4627            }
4628    
4629            protected void validateParentGroup(long groupId, long parentGroupId)
4630                    throws PortalException, SystemException {
4631    
4632                    if (parentGroupId == GroupConstants.DEFAULT_PARENT_GROUP_ID) {
4633                            return;
4634                    }
4635    
4636                    if (groupId == parentGroupId) {
4637                            throw new GroupParentException(
4638                                    GroupParentException.SELF_DESCENDANT);
4639                    }
4640    
4641                    Group group = groupPersistence.fetchByPrimaryKey(groupId);
4642    
4643                    if (group == null) {
4644                            return;
4645                    }
4646    
4647                    if ((groupId > 0) &&
4648                            (parentGroupId != GroupConstants.DEFAULT_PARENT_GROUP_ID)) {
4649    
4650                            // Prevent circular groupal references
4651    
4652                            if (isParentGroup(groupId, parentGroupId)) {
4653                                    throw new GroupParentException(
4654                                            GroupParentException.CHILD_DESCENDANT);
4655                            }
4656                    }
4657    
4658                    Group parentGroup = groupPersistence.findByPrimaryKey(parentGroupId);
4659    
4660                    if (group.isStagingGroup()) {
4661                            Group stagingGroup = parentGroup.getStagingGroup();
4662    
4663                            if (groupId == stagingGroup.getGroupId()) {
4664                                    throw new GroupParentException(
4665                                            GroupParentException.STAGING_DESCENDANT);
4666                            }
4667                    }
4668            }
4669    
4670            protected File publicLARFile;
4671    
4672            private static Log _log = LogFactoryUtil.getLog(
4673                    GroupLocalServiceImpl.class);
4674    
4675            private volatile long[] _classNameIds;
4676            private volatile long[] _complexSQLClassNameIds;
4677            private Map<String, Group> _systemGroupsMap = new HashMap<String, Group>();
4678    
4679    }