001    /**
002     * Copyright (c) 2000-2012 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.NoSuchGroupException;
021    import com.liferay.portal.NoSuchLayoutSetException;
022    import com.liferay.portal.NoSuchUserException;
023    import com.liferay.portal.RequiredGroupException;
024    import com.liferay.portal.kernel.cache.ThreadLocalCachable;
025    import com.liferay.portal.kernel.dao.orm.QueryUtil;
026    import com.liferay.portal.kernel.exception.PortalException;
027    import com.liferay.portal.kernel.exception.SystemException;
028    import com.liferay.portal.kernel.language.LanguageUtil;
029    import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
030    import com.liferay.portal.kernel.log.Log;
031    import com.liferay.portal.kernel.log.LogFactoryUtil;
032    import com.liferay.portal.kernel.messaging.DestinationNames;
033    import com.liferay.portal.kernel.scheduler.SchedulerEngineUtil;
034    import com.liferay.portal.kernel.scheduler.StorageType;
035    import com.liferay.portal.kernel.spring.aop.Skip;
036    import com.liferay.portal.kernel.staging.StagingUtil;
037    import com.liferay.portal.kernel.transaction.Propagation;
038    import com.liferay.portal.kernel.transaction.Transactional;
039    import com.liferay.portal.kernel.util.FileUtil;
040    import com.liferay.portal.kernel.util.FriendlyURLNormalizerUtil;
041    import com.liferay.portal.kernel.util.GetterUtil;
042    import com.liferay.portal.kernel.util.OrderByComparator;
043    import com.liferay.portal.kernel.util.ParamUtil;
044    import com.liferay.portal.kernel.util.PropsKeys;
045    import com.liferay.portal.kernel.util.StringPool;
046    import com.liferay.portal.kernel.util.StringUtil;
047    import com.liferay.portal.kernel.util.UniqueList;
048    import com.liferay.portal.kernel.util.Validator;
049    import com.liferay.portal.model.Account;
050    import com.liferay.portal.model.Company;
051    import com.liferay.portal.model.Group;
052    import com.liferay.portal.model.GroupConstants;
053    import com.liferay.portal.model.Layout;
054    import com.liferay.portal.model.LayoutConstants;
055    import com.liferay.portal.model.LayoutPrototype;
056    import com.liferay.portal.model.LayoutSet;
057    import com.liferay.portal.model.LayoutSetPrototype;
058    import com.liferay.portal.model.LayoutTypePortlet;
059    import com.liferay.portal.model.Organization;
060    import com.liferay.portal.model.Portlet;
061    import com.liferay.portal.model.Resource;
062    import com.liferay.portal.model.ResourceConstants;
063    import com.liferay.portal.model.ResourcePermission;
064    import com.liferay.portal.model.Role;
065    import com.liferay.portal.model.RoleConstants;
066    import com.liferay.portal.model.User;
067    import com.liferay.portal.model.UserGroup;
068    import com.liferay.portal.model.UserPersonalSite;
069    import com.liferay.portal.model.impl.LayoutImpl;
070    import com.liferay.portal.security.permission.ActionKeys;
071    import com.liferay.portal.security.permission.PermissionCacheUtil;
072    import com.liferay.portal.security.permission.ResourceActionsUtil;
073    import com.liferay.portal.service.ServiceContext;
074    import com.liferay.portal.service.base.GroupLocalServiceBaseImpl;
075    import com.liferay.portal.theme.ThemeLoader;
076    import com.liferay.portal.theme.ThemeLoaderFactory;
077    import com.liferay.portal.util.PortalUtil;
078    import com.liferay.portal.util.PortletCategoryKeys;
079    import com.liferay.portal.util.PortletKeys;
080    import com.liferay.portal.util.PropsUtil;
081    import com.liferay.portal.util.PropsValues;
082    import com.liferay.portal.util.comparator.GroupNameComparator;
083    import com.liferay.portlet.blogs.model.BlogsEntry;
084    import com.liferay.portlet.journal.model.JournalArticle;
085    import com.liferay.portlet.messageboards.model.MBCategoryConstants;
086    
087    import java.io.File;
088    
089    import java.util.ArrayList;
090    import java.util.Arrays;
091    import java.util.HashMap;
092    import java.util.LinkedHashMap;
093    import java.util.List;
094    import java.util.Locale;
095    import java.util.Map;
096    
097    /**
098     * The group local service is responsible for accessing, creating, modifying and
099     * deleting groups.
100     *
101     * <p>
102     * Groups are mostly used in Liferay as a resource container for permissioning
103     * and content scoping purposes as described in {@link
104     * com.liferay.portal.model.impl.GroupImpl}.
105     * </p>
106     *
107     * <p>
108     * Groups are also the entity to which LayoutSets are generally associated.
109     * Since LayoutSets are the parent entities of Layouts (i.e. pages), no entity
110     * can have associated pages without also having an associated Group. This
111     * relationship can be depicted as ... Layout -> LayoutSet -> Group[type] [->
112     * Entity]. Note, the Entity part is optional.
113     * </p>
114     *
115     * <p>
116     * Group has a "type" definition that is typically identified by two fields of
117     * the entity - <code>String className</code>, and <code>int type </code>.
118     * </p>
119     *
120     * <p>
121     * The <code>className</code> field helps create the group's association with
122     * other entities (e.g. Organization, User, Company, UserGroup, ... etc.). The
123     * value of <code>className</code> is the full name of the entity's class and
124     * the primary key of the associated entity instance. A site has
125     * <code>className="Group"</code> and has no associated entity.
126     * </p>
127     *
128     * <p>
129     * The <code>type</code> field helps distinguish between a group used strictly
130     * for scoping and a group that also has pages (in which case the type is
131     * <code>SITE</code>). For a list of types, see {@link
132     * com.liferay.portal.model.GroupConstants}.
133     * </p>
134     *
135     * <p>
136     * Here is a listing of how Group is related to some portal entities ...
137     * </p>
138     *
139     * <ul>
140     * <li>
141     * Site is a Group with <code>className="Group"</code>
142     * </li>
143     * <li>
144     * Company has 1 Group (this is the global scope, but never has pages)
145     * </li>
146     * <li>
147     * User has 1 Group (pages are optional based on the behavior configuration for
148     * personal pages)
149     * </li>
150     * <li>
151     * Layout Template (<code>LayoutPrototype</code>) has 1 Group which uses only 1
152     * of it's 2 LayoutSets to store a single page which can later be used to
153     * derive a single page in any Site
154     * </li>
155     * <li>
156     * Site Template (<code>LayoutSetPrototype</code>) has 1 Group which uses only
157     * 1 of it's 2 LayoutSets to store many pages which can later be used to derive
158     * entire Sites or pulled into an existing Site
159     * </li>
160     * <li>
161     * Organization has 1 Group, but can also be associated to a Site at any point
162     * in it's life cycle in order to support having pages
163     * </li>
164     * <li>
165     * UserGroup has 1 Group that can have pages in both of the group's LayoutSets
166     * which are later inherited by users assigned to the UserGroup
167     * </li>
168     * </ul>
169     *
170     * @author Brian Wing Shun Chan
171     * @author Alexander Chow
172     * @author Bruno Farache
173     * @author Wesley Gong
174     */
175    public class GroupLocalServiceImpl extends GroupLocalServiceBaseImpl {
176    
177            public static final String ORGANIZATION_NAME_SUFFIX = " LFR_ORGANIZATION";
178    
179            /**
180             * Constructs a group local service.
181             */
182            public GroupLocalServiceImpl() {
183                    initImportLARFile();
184            }
185    
186            /**
187             * Adds a group.
188             *
189             * @param  userId the primary key of the group's creator/owner
190             * @param  className the entity's class name
191             * @param  classPK the primary key of the entity's instance
192             * @param  liveGroupId the primary key of the live group
193             * @param  name the entity's name
194             * @param  description the group's description (optionally
195             *         <code>null</code>)
196             * @param  type the group's type. For more information see {@link
197             *         com.liferay.portal.model.GroupConstants}
198             * @param  friendlyURL the group's friendlyURL (optionally
199             *         <code>null</code>)
200             * @param  site whether the group is to be associated with a main site
201             * @param  active whether the group is active
202             * @param  serviceContext the service context to be applied (optionally
203             *         <code>null</code>). Can set asset category IDs and asset tag
204             *         names for the group, and whether the group is for staging.
205             * @return the group
206             * @throws PortalException if a creator could not be found, if the group's
207             *         information was invalid, if a layout could not be found, or if a
208             *         valid friendly URL could not be created for the group
209             * @throws SystemException if a system exception occurred
210             */
211            public Group addGroup(
212                            long userId, String className, long classPK, long liveGroupId,
213                            String name, String description, int type, String friendlyURL,
214                            boolean site, boolean active, ServiceContext serviceContext)
215                    throws PortalException, SystemException {
216    
217                    // Group
218    
219                    User user = userPersistence.findByPrimaryKey(userId);
220                    className = GetterUtil.getString(className);
221                    long classNameId = PortalUtil.getClassNameId(className);
222                    String friendlyName = name;
223    
224                    long groupId = 0;
225    
226                    while (true) {
227                            groupId = counterLocalService.increment();
228    
229                            User screenNameUser = userPersistence.fetchByC_SN(
230                                    user.getCompanyId(), String.valueOf(groupId));
231    
232                            if (screenNameUser == null) {
233                                    break;
234                            }
235                    }
236    
237                    boolean staging = isStaging(serviceContext);
238    
239                    long groupClassNameId = PortalUtil.getClassNameId(Group.class);
240    
241                    if ((classNameId <= 0) || className.equals(Group.class.getName())) {
242                            className = Group.class.getName();
243                            classNameId = groupClassNameId;
244                            classPK = groupId;
245                    }
246                    else if (className.equals(Organization.class.getName())) {
247                            name = getOrgGroupName(name);
248                    }
249                    else if (!GroupConstants.USER_PERSONAL_SITE.equals(name)) {
250                            name = String.valueOf(classPK);
251                    }
252    
253                    if (className.equals(Organization.class.getName()) && staging) {
254                            classPK = liveGroupId;
255                    }
256    
257                    long parentGroupId = GroupConstants.DEFAULT_PARENT_GROUP_ID;
258    
259                    if (className.equals(Layout.class.getName())) {
260                            Layout layout = layoutLocalService.getLayout(classPK);
261    
262                            parentGroupId = layout.getGroupId();
263                    }
264    
265                    friendlyURL = getFriendlyURL(
266                            user.getCompanyId(), groupId, classNameId, classPK, friendlyName,
267                            friendlyURL);
268    
269                    if (staging) {
270                            name = name.concat(" (Staging)");
271                            friendlyURL = friendlyURL.concat("-staging");
272                    }
273    
274                    if (className.equals(Group.class.getName())) {
275                            if (!site && (liveGroupId == 0)) {
276                                    throw new IllegalArgumentException();
277                            }
278                    }
279                    else if (!className.equals(Organization.class.getName()) &&
280                                     className.startsWith("com.liferay.portal.model.")) {
281    
282                            if (site) {
283                                    throw new IllegalArgumentException();
284                            }
285                    }
286    
287                    if ((classNameId <= 0) || className.equals(Group.class.getName())) {
288                            validateName(groupId, user.getCompanyId(), name, site);
289                    }
290    
291                    validateFriendlyURL(
292                            user.getCompanyId(), groupId, classNameId, classPK, friendlyURL);
293    
294                    Group group = groupPersistence.create(groupId);
295    
296                    group.setCompanyId(user.getCompanyId());
297                    group.setCreatorUserId(userId);
298                    group.setClassNameId(classNameId);
299                    group.setClassPK(classPK);
300                    group.setParentGroupId(parentGroupId);
301                    group.setLiveGroupId(liveGroupId);
302                    group.setName(name);
303                    group.setDescription(description);
304                    group.setType(type);
305                    group.setFriendlyURL(friendlyURL);
306                    group.setSite(site);
307                    group.setActive(active);
308    
309                    if ((serviceContext != null) && (classNameId == groupClassNameId) &&
310                            !user.isDefaultUser()) {
311    
312                            group.setExpandoBridgeAttributes(serviceContext);
313                    }
314    
315                    groupPersistence.update(group, false);
316    
317                    // Layout sets
318    
319                    layoutSetLocalService.addLayoutSet(groupId, true);
320    
321                    layoutSetLocalService.addLayoutSet(groupId, false);
322    
323                    if ((classNameId == groupClassNameId) && !user.isDefaultUser()) {
324    
325                            // Resources
326    
327                            resourceLocalService.addResources(
328                                    group.getCompanyId(), 0, 0, Group.class.getName(),
329                                    group.getGroupId(), false, false, false);
330    
331                            // Site roles
332    
333                            Role role = roleLocalService.getRole(
334                                    group.getCompanyId(), RoleConstants.SITE_OWNER);
335    
336                            userGroupRoleLocalService.addUserGroupRoles(
337                                    userId, groupId, new long[] {role.getRoleId()});
338    
339                            // User
340    
341                            userLocalService.addGroupUsers(
342                                    group.getGroupId(), new long[] {userId});
343    
344                            // Asset
345    
346                            if (serviceContext != null) {
347                                    updateAsset(
348                                            userId, group, serviceContext.getAssetCategoryIds(),
349                                            serviceContext.getAssetTagNames());
350                            }
351                    }
352                    else if (className.equals(Organization.class.getName()) &&
353                                     !user.isDefaultUser()) {
354    
355                            // Resources
356    
357                            resourceLocalService.addResources(
358                                    group.getCompanyId(), 0, 0, Group.class.getName(),
359                                    group.getGroupId(), false, false, false);
360                    }
361    
362                    return group;
363            }
364    
365            /**
366             * Adds the group using the default live group.
367             *
368             * @param  userId the primary key of the group's creator/owner
369             * @param  className the entity's class name
370             * @param  classPK the primary key of the entity's instance
371             * @param  name the entity's name
372             * @param  description the group's description (optionally
373             *         <code>null</code>)
374             * @param  type the group's type. For more information see {@link
375             *         com.liferay.portal.model.GroupConstants}
376             * @param  friendlyURL the group's friendlyURL
377             * @param  site whether the group is to be associated with a main site
378             * @param  active whether the group is active
379             * @param  serviceContext the service context to be applied (optionally
380             *         <code>null</code>). Can set asset category IDs and asset tag
381             *         names for the group, and whether the group is for staging.
382             * @return the group
383             * @throws PortalException if a creator could not be found, if the group's
384             *         information was invalid, if a layout could not be found, or if a
385             *         valid friendly URL could not be created for the group
386             * @throws SystemException if a system exception occurred
387             */
388            public Group addGroup(
389                            long userId, String className, long classPK, String name,
390                            String description, int type, String friendlyURL, boolean site,
391                            boolean active, ServiceContext serviceContext)
392                    throws PortalException, SystemException {
393    
394                    return addGroup(
395                            userId, className, classPK, GroupConstants.DEFAULT_LIVE_GROUP_ID,
396                            name, description, type, friendlyURL, site, active, serviceContext);
397            }
398    
399            /**
400             * Adds the groups to the role.
401             *
402             * @param  roleId the primary key of the role
403             * @param  groupIds the primary keys of the groups
404             * @throws SystemException if a system exception occurred
405             */
406            public void addRoleGroups(long roleId, long[] groupIds)
407                    throws SystemException {
408    
409                    rolePersistence.addGroups(roleId, groupIds);
410    
411                    PermissionCacheUtil.clearCache();
412            }
413    
414            /**
415             * Adds the user to the groups.
416             *
417             * @param  userId the primary key of the user
418             * @param  groupIds the primary keys of the groups
419             * @throws SystemException if a system exception occurred
420             */
421            public void addUserGroups(long userId, long[] groupIds)
422                    throws SystemException {
423    
424                    userPersistence.addGroups(userId, groupIds);
425    
426                    PermissionCacheUtil.clearCache();
427            }
428    
429            /**
430             * Adds a company group if it does not exist. This method is typically used
431             * when a virtual host is added.
432             *
433             * @param  companyId the primary key of the company
434             * @throws PortalException if a default user for the company could not be
435             *         found, if the group's information was invalid, if a layout could
436             *         not be found, or if a valid friendly URL could not be created for
437             *         the group
438             * @throws SystemException if a system exception occurred
439             */
440            @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
441            public void checkCompanyGroup(long companyId)
442                    throws PortalException, SystemException {
443    
444                    long classNameId = PortalUtil.getClassNameId(Company.class);
445    
446                    int count = groupPersistence.countByC_C_C(
447                            companyId, classNameId, companyId);
448    
449                    if (count == 0) {
450                            long defaultUserId = userLocalService.getDefaultUserId(companyId);
451    
452                            groupLocalService.addGroup(
453                                    defaultUserId, Company.class.getName(), companyId, null, null,
454                                    0, null, false, true, null);
455                    }
456            }
457    
458            /**
459             * Creates systems groups and other related data needed by the system on the
460             * very first startup. Also takes care of creating the control panel groups
461             * and layouts.
462             *
463             * @param  companyId the primary key of the company
464             * @throws PortalException if a new system group could not be created
465             * @throws SystemException if a system exception occurred
466             */
467            @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
468            public void checkSystemGroups(long companyId)
469                    throws PortalException, SystemException {
470    
471                    String companyIdHexString = StringUtil.toHexString(companyId);
472    
473                    for (Group group : groupFinder.findBySystem(companyId)) {
474                            _systemGroupsMap.put(
475                                    companyIdHexString.concat(group.getName()), group);
476                    }
477    
478                    long defaultUserId = userLocalService.getDefaultUserId(companyId);
479    
480                    String[] systemGroups = PortalUtil.getSystemGroups();
481    
482                    for (String name : systemGroups) {
483                            String groupCacheKey = companyIdHexString.concat(name);
484    
485                            Group group = _systemGroupsMap.get(groupCacheKey);
486    
487                            if (group == null) {
488                                    group = groupPersistence.fetchByC_N(companyId, name);
489                            }
490    
491                            if (group == null) {
492                                    String className = null;
493                                    long classPK = 0;
494                                    int type = GroupConstants.TYPE_SITE_OPEN;
495                                    String friendlyURL = null;
496                                    boolean site = true;
497    
498                                    if (name.equals(GroupConstants.CONTROL_PANEL)) {
499                                            type = GroupConstants.TYPE_SITE_PRIVATE;
500                                            friendlyURL = GroupConstants.CONTROL_PANEL_FRIENDLY_URL;
501                                    }
502                                    else if (name.equals(GroupConstants.GUEST)) {
503                                            friendlyURL = "/guest";
504                                    }
505                                    else if (name.equals(GroupConstants.USER_PERSONAL_SITE)) {
506                                            className = UserPersonalSite.class.getName();
507                                            classPK = defaultUserId;
508                                            type = GroupConstants.TYPE_SITE_PRIVATE;
509                                            friendlyURL =
510                                                    GroupConstants.USER_PERSONAL_SITE_FRIENDLY_URL;
511                                            site = false;
512                                    }
513    
514                                    group = groupLocalService.addGroup(
515                                            defaultUserId, className, classPK, name, null, type,
516                                            friendlyURL, site, true, null);
517    
518                                    if (name.equals(GroupConstants.USER_PERSONAL_SITE)) {
519                                            initUserPersonalSitePermissions(group);
520                                    }
521                            }
522    
523                            if (group.isControlPanel()) {
524                                    LayoutSet layoutSet = layoutSetLocalService.getLayoutSet(
525                                            group.getGroupId(), true);
526    
527                                    if (layoutSet.getPageCount() == 0) {
528                                            addControlPanelLayouts(group);
529                                    }
530                            }
531    
532                            if (group.getName().equals(GroupConstants.GUEST)) {
533                                    LayoutSet layoutSet = layoutSetLocalService.getLayoutSet(
534                                            group.getGroupId(), false);
535    
536                                    if (layoutSet.getPageCount() == 0) {
537                                            addDefaultGuestPublicLayouts(group);
538                                    }
539                            }
540    
541                            _systemGroupsMap.put(groupCacheKey, group);
542                    }
543            }
544    
545            /**
546             * Deletes the group and its associated data.
547             *
548             * <p>
549             * The group is unstaged and its assets and resources including layouts,
550             * membership requests, subscriptions, teams, blogs, bookmarks, calendar
551             * events, image gallery, journals, message boards, polls, shopping related
552             * entities, software catalog, and wikis are also deleted.
553             * </p>
554             *
555             * @param  group the group
556             * @throws PortalException if the group was a system group, or if the user
557             *         did not have permission to delete the group or its assets or its
558             *         resources
559             * @throws SystemException if a system exception occurred
560             */
561            @Override
562            public Group deleteGroup(Group group)
563                    throws PortalException, SystemException {
564    
565                    if (PortalUtil.isSystemGroup(group.getName())) {
566                            throw new RequiredGroupException(
567                                    String.valueOf(group.getGroupId()));
568                    }
569    
570                    // Layout set branches
571    
572                    layoutSetBranchLocalService.deleteLayoutSetBranches(
573                            group.getGroupId(), true, true);
574    
575                    layoutSetBranchLocalService.deleteLayoutSetBranches(
576                            group.getGroupId(), false, true);
577    
578                    // Layout sets
579    
580                    ServiceContext serviceContext = new ServiceContext();
581    
582                    try {
583                            layoutSetLocalService.deleteLayoutSet(
584                                    group.getGroupId(), true, serviceContext);
585                    }
586                    catch (NoSuchLayoutSetException nslse) {
587                    }
588    
589                    try {
590                            layoutSetLocalService.deleteLayoutSet(
591                                    group.getGroupId(), false, serviceContext);
592                    }
593                    catch (NoSuchLayoutSetException nslse) {
594                    }
595    
596                    // Group roles
597    
598                    userGroupRoleLocalService.deleteUserGroupRolesByGroupId(
599                            group.getGroupId());
600    
601                    // User group roles
602    
603                    userGroupGroupRoleLocalService.deleteUserGroupGroupRolesByGroupId(
604                            group.getGroupId());
605    
606                    // Membership requests
607    
608                    membershipRequestLocalService.deleteMembershipRequests(
609                            group.getGroupId());
610    
611                    // Subscriptions
612    
613                    subscriptionLocalService.deleteSubscriptions(
614                            group.getCompanyId(), BlogsEntry.class.getName(),
615                            group.getGroupId());
616                    subscriptionLocalService.deleteSubscriptions(
617                            group.getCompanyId(), JournalArticle.class.getName(),
618                            group.getGroupId());
619    
620                    // Teams
621    
622                    teamLocalService.deleteTeams(group.getGroupId());
623    
624                    // Staging
625    
626                    unscheduleStaging(group);
627    
628                    if (group.hasStagingGroup()) {
629                            deleteGroup(group.getStagingGroup().getGroupId());
630                    }
631    
632                    // Themes
633    
634                    ThemeLoader themeLoader = ThemeLoaderFactory.getDefaultThemeLoader();
635    
636                    if (themeLoader != null) {
637                            String themePath =
638                                    themeLoader.getFileStorage() + StringPool.SLASH +
639                                            group.getGroupId();
640    
641                            FileUtil.deltree(themePath + "-private");
642                            FileUtil.deltree(themePath + "-public");
643                    }
644    
645                    // Asset
646    
647                    if (group.isRegularSite()) {
648                            assetEntryLocalService.deleteEntry(
649                                    Group.class.getName(), group.getGroupId());
650                    }
651    
652                    assetVocabularyLocalService.deleteVocabularies(group.getGroupId());
653    
654                    // Blogs
655    
656                    blogsEntryLocalService.deleteEntries(group.getGroupId());
657                    blogsStatsUserLocalService.deleteStatsUserByGroupId(group.getGroupId());
658    
659                    // Bookmarks
660    
661                    bookmarksFolderLocalService.deleteFolders(group.getGroupId());
662    
663                    // Calendar
664    
665                    calEventLocalService.deleteEvents(group.getGroupId());
666    
667                    // Document library
668    
669                    repositoryLocalService.deleteRepositories(group.getGroupId());
670                    dlFileEntryTypeLocalService.deleteFileEntryTypes(group.getGroupId());
671    
672                    // Journal
673    
674                    journalArticleLocalService.deleteArticles(group.getGroupId());
675                    journalTemplateLocalService.deleteTemplates(group.getGroupId());
676                    journalStructureLocalService.deleteStructures(group.getGroupId());
677    
678                    // Message boards
679    
680                    mbBanLocalService.deleteBansByGroupId(group.getGroupId());
681                    mbCategoryLocalService.deleteCategories(group.getGroupId());
682                    mbStatsUserLocalService.deleteStatsUsersByGroupId(group.getGroupId());
683                    mbThreadLocalService.deleteThreads(
684                            group.getGroupId(), MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID);
685    
686                    // Polls
687    
688                    pollsQuestionLocalService.deleteQuestions(group.getGroupId());
689    
690                    // Shopping
691    
692                    shoppingCartLocalService.deleteGroupCarts(group.getGroupId());
693                    shoppingCategoryLocalService.deleteCategories(group.getGroupId());
694                    shoppingCouponLocalService.deleteCoupons(group.getGroupId());
695                    shoppingOrderLocalService.deleteOrders(group.getGroupId());
696    
697                    // Software catalog
698    
699                    scFrameworkVersionLocalService.deleteFrameworkVersions(
700                            group.getGroupId());
701                    scProductEntryLocalService.deleteProductEntries(group.getGroupId());
702    
703                    // Wiki
704    
705                    wikiNodeLocalService.deleteNodes(group.getGroupId());
706    
707                    // Resources
708    
709                    if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) {
710                            List<ResourcePermission> resourcePermissions =
711                                    resourcePermissionPersistence.findByC_P(
712                                            group.getCompanyId(), String.valueOf(group.getGroupId()));
713    
714                            for (ResourcePermission resourcePermission : resourcePermissions) {
715                                    resourcePermissionLocalService.deleteResourcePermission(
716                                            resourcePermission);
717                            }
718                    }
719                    else {
720                            List<Resource> resources = resourceFinder.findByC_P(
721                                    group.getCompanyId(), String.valueOf(group.getGroupId()));
722    
723                            for (Resource resource : resources) {
724                                    resourceLocalService.deleteResource(resource);
725                            }
726                    }
727    
728                    if (!group.isStagingGroup() &&
729                            (group.isOrganization() || group.isRegularSite())) {
730    
731                            resourceLocalService.deleteResource(
732                                    group.getCompanyId(), Group.class.getName(),
733                                    ResourceConstants.SCOPE_INDIVIDUAL, group.getGroupId());
734                    }
735    
736                    // Group
737    
738                    if (group.isOrganization() && group.isSite()) {
739                            group.setSite(false);
740    
741                            groupPersistence.update(group, false);
742                    }
743                    else {
744                            groupPersistence.remove(group);
745                    }
746    
747                    // Permission cache
748    
749                    PermissionCacheUtil.clearCache();
750    
751                    return group;
752            }
753    
754            /**
755             * Deletes the group and its associated data.
756             *
757             * <p>
758             * The group is unstaged and its assets and resources including layouts,
759             * membership requests, subscriptions, teams, blogs, bookmarks, calendar
760             * events, image gallery, journals, message boards, polls, shopping related
761             * entities, software catalog, and wikis are also deleted.
762             * </p>
763             *
764             * @param  groupId the primary key of the group
765             * @throws PortalException if a group with the primary key could not be
766             *         found, if the group was a system group, or if the user did not
767             *         have permission to delete the group, its assets, or its resources
768             * @throws SystemException if a system exception occurred
769             */
770            @Override
771            public Group deleteGroup(long groupId)
772                    throws PortalException, SystemException {
773    
774                    Group group = groupPersistence.findByPrimaryKey(groupId);
775    
776                    return deleteGroup(group);
777            }
778    
779            /**
780             * Returns the group with the matching friendly URL.
781             *
782             * @param  companyId the primary key of the company
783             * @param  friendlyURL the friendly URL
784             * @return the group with the friendly URL, or <code>null</code> if a
785             *         matching group could not be found
786             * @throws SystemException if a system exception occurred
787             */
788            public Group fetchFriendlyURLGroup(long companyId, String friendlyURL)
789                    throws SystemException {
790    
791                    if (Validator.isNull(friendlyURL)) {
792                            return null;
793                    }
794    
795                    friendlyURL = getFriendlyURL(friendlyURL);
796    
797                    return groupPersistence.fetchByC_F(companyId, friendlyURL);
798            }
799    
800            /**
801             * Returns the group with the matching group name.
802             *
803             * @param  companyId the primary key of the company
804             * @param  name the group's name
805             * @return the group with the name and associated company, or
806             *         <code>null</code> if a matching group could not be found
807             * @throws SystemException if a system exception occurred
808             */
809            @Skip
810            public Group fetchGroup(long companyId, String name)
811                    throws SystemException {
812    
813                    Group group = _systemGroupsMap.get(
814                            StringUtil.toHexString(companyId).concat(name));
815    
816                    if (group != null) {
817                            return group;
818                    }
819    
820                    return groupLocalService.loadFetchGroup(companyId, name);
821            }
822    
823            /**
824             * Returns the company group.
825             *
826             * @param  companyId the primary key of the company
827             * @return the group associated with the company
828             * @throws PortalException if a matching group could not be found
829             * @throws SystemException if a system exception occurred
830             */
831            public Group getCompanyGroup(long companyId)
832                    throws PortalException, SystemException {
833    
834                    long classNameId = PortalUtil.getClassNameId(Company.class);
835    
836                    return groupPersistence.findByC_C_C(companyId, classNameId, companyId);
837            }
838    
839            /**
840             * Returns a range of all the groups associated with the company.
841             *
842             * <p>
843             * Useful when paginating results. Returns a maximum of <code>end -
844             * start</code> instances. <code>start</code> and <code>end</code> are not
845             * primary keys, they are indexes in the result set. Thus, <code>0</code>
846             * refers to the first result in the set. Setting both <code>start</code>
847             * and <code>end</code> to {@link
848             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
849             * result set.
850             * </p>
851             *
852             * @param  companyId the primary key of the company
853             * @param  start the lower bound of the range of groups to return
854             * @param  end the upper bound of the range of groups to return (not
855             *         inclusive)
856             * @return the range of groups associated with the company
857             * @throws SystemException if a system exception occurred
858             */
859            public List<Group> getCompanyGroups(long companyId, int start, int end)
860                    throws SystemException {
861    
862                    return groupPersistence.findByCompanyId(companyId, start, end);
863            }
864    
865            /**
866             * Returns the number of groups associated with the company.
867             *
868             * @param  companyId the primary key of the company
869             * @return the number of groups associated with the company
870             * @throws SystemException if a system exception occurred
871             */
872            public int getCompanyGroupsCount(long companyId) throws SystemException {
873                    return groupPersistence.countByCompanyId(companyId);
874            }
875    
876            /**
877             * Returns the group with the matching friendly URL.
878             *
879             * @param  companyId the primary key of the company
880             * @param  friendlyURL the group's friendlyURL
881             * @return the group with the friendly URL
882             * @throws PortalException if a matching group could not be found, or if the
883             *         friendly URL was invalid
884             * @throws SystemException if a system exception occurred
885             */
886            public Group getFriendlyURLGroup(long companyId, String friendlyURL)
887                    throws PortalException, SystemException {
888    
889                    if (Validator.isNull(friendlyURL)) {
890                            throw new NoSuchGroupException();
891                    }
892    
893                    friendlyURL = getFriendlyURL(friendlyURL);
894    
895                    return groupPersistence.findByC_F(companyId, friendlyURL);
896            }
897    
898            /**
899             * Returns the group with the matching primary key.
900             *
901             * @param  groupId the primary key of the group
902             * @return the group with the primary key
903             * @throws PortalException if a group with the primary key could not be
904             *         found
905             * @throws SystemException if a system exception occurred
906             */
907            @Override
908            @ThreadLocalCachable
909            public Group getGroup(long groupId)
910                    throws PortalException, SystemException {
911    
912                    return groupPersistence.findByPrimaryKey(groupId);
913            }
914    
915            /**
916             * Returns the group with the matching group name.
917             *
918             * @param  companyId the primary key of the company
919             * @param  name the group's name
920             * @return the group with the name
921             * @throws PortalException if a matching group could not be found
922             * @throws SystemException if a system exception occurred
923             */
924            @Skip
925            public Group getGroup(long companyId, String name)
926                    throws PortalException, SystemException {
927    
928                    Group group = _systemGroupsMap.get(
929                            StringUtil.toHexString(companyId).concat(name));
930    
931                    if (group != null) {
932                            return group;
933                    }
934    
935                    return groupLocalService.loadGetGroup(companyId, name);
936            }
937    
938            public String getGroupDescriptiveName(Group group, Locale locale)
939                    throws PortalException, SystemException {
940    
941                    String name = group.getName();
942    
943                    if (group.isCompany()) {
944                            name = LanguageUtil.get(locale, "global");
945                    }
946                    else if (group.isControlPanel()) {
947                            name = LanguageUtil.get(locale, "control-panel");
948                    }
949                    else if (group.isLayout()) {
950                            Layout layout = layoutLocalService.getLayout(group.getClassPK());
951    
952                            name = layout.getName(locale);
953                    }
954                    else if (group.isLayoutPrototype()) {
955                            LayoutPrototype layoutPrototype =
956                                    layoutPrototypeLocalService.getLayoutPrototype(
957                                            group.getClassPK());
958    
959                            name = layoutPrototype.getName(locale);
960                    }
961                    else if (group.isLayoutSetPrototype()) {
962                            LayoutSetPrototype layoutSetPrototype =
963                                    layoutSetPrototypePersistence.findByPrimaryKey(
964                                            group.getClassPK());
965    
966                            name = layoutSetPrototype.getName(locale);
967                    }
968                    else if (group.isOrganization()) {
969                            long organizationId = group.getOrganizationId();
970    
971                            Organization organization =
972                                    organizationPersistence.findByPrimaryKey(organizationId);
973    
974                            name = organization.getName();
975                    }
976                    else if (group.isUser()) {
977                            long userId = group.getClassPK();
978    
979                            User user = userPersistence.findByPrimaryKey(userId);
980    
981                            name = user.getFullName();
982                    }
983                    else if (group.isUserGroup()) {
984                            long userGroupId = group.getClassPK();
985    
986                            UserGroup userGroup = userGroupPersistence.findByPrimaryKey(
987                                    userGroupId);
988    
989                            name = userGroup.getName();
990                    }
991                    else if (group.isUserPersonalSite()) {
992                            name = LanguageUtil.get(locale, "user-personal-site");
993                    }
994                    else if (name.equals(GroupConstants.GUEST)) {
995                            Company company = companyPersistence.findByPrimaryKey(
996                                    group.getCompanyId());
997    
998                            Account account = company.getAccount();
999    
1000                            name = account.getName();
1001                    }
1002    
1003                    return name;
1004            }
1005    
1006            public String getGroupDescriptiveName(long groupId, Locale locale)
1007                    throws PortalException, SystemException {
1008    
1009                    Group group = groupPersistence.findByPrimaryKey(groupId);
1010    
1011                    return getGroupDescriptiveName(group, locale);
1012            }
1013    
1014            /**
1015             * Returns the groups with the matching primary keys.
1016             *
1017             * @param  groupIds the primary keys of the groups
1018             * @return the groups with the primary keys
1019             * @throws PortalException if any one of the groups could not be found
1020             * @throws SystemException if a system exception occurred
1021             */
1022            public List<Group> getGroups(long[] groupIds)
1023                    throws PortalException, SystemException {
1024    
1025                    List<Group> groups = new ArrayList<Group>(groupIds.length);
1026    
1027                    for (long groupId : groupIds) {
1028                            Group group = getGroup(groupId);
1029    
1030                            groups.add(group);
1031                    }
1032    
1033                    return groups;
1034            }
1035    
1036            /**
1037             * Returns the group associated with the layout.
1038             *
1039             * @param  companyId the primary key of the company
1040             * @param  plid the primary key of the layout
1041             * @return the group associated with the layout
1042             * @throws PortalException if a matching group could not be found
1043             * @throws SystemException if a system exception occurred
1044             */
1045            public Group getLayoutGroup(long companyId, long plid)
1046                    throws PortalException, SystemException {
1047    
1048                    long classNameId = PortalUtil.getClassNameId(Layout.class);
1049    
1050                    return groupPersistence.findByC_C_C(companyId, classNameId, plid);
1051            }
1052    
1053            /**
1054             * Returns the group associated with the layout prototype.
1055             *
1056             * @param  companyId the primary key of the company
1057             * @param  layoutPrototypeId the primary key of the layout prototype
1058             * @return the group associated with the layout prototype
1059             * @throws PortalException if a matching group could not be found
1060             * @throws SystemException if a system exception occurred
1061             */
1062            public Group getLayoutPrototypeGroup(long companyId, long layoutPrototypeId)
1063                    throws PortalException, SystemException {
1064    
1065                    long classNameId = PortalUtil.getClassNameId(LayoutPrototype.class);
1066    
1067                    return groupPersistence.findByC_C_C(
1068                            companyId, classNameId, layoutPrototypeId);
1069            }
1070    
1071            /**
1072             * Returns the group associated with the layout set prototype.
1073             *
1074             * @param  companyId the primary key of the company
1075             * @param  layoutSetPrototypeId the primary key of the layout set prototype
1076             * @return the group associated with the layout set prototype
1077             * @throws PortalException if a matching group could not be found
1078             * @throws SystemException if a system exception occurred
1079             */
1080            public Group getLayoutSetPrototypeGroup(
1081                            long companyId, long layoutSetPrototypeId)
1082                    throws PortalException, SystemException {
1083    
1084                    long classNameId = PortalUtil.getClassNameId(LayoutSetPrototype.class);
1085    
1086                    return groupPersistence.findByC_C_C(
1087                            companyId, classNameId, layoutSetPrototypeId);
1088            }
1089    
1090            /**
1091             * Returns all live groups.
1092             *
1093             * @return all live groups
1094             * @throws SystemException if a system exception occurred
1095             */
1096            public List<Group> getLiveGroups() throws SystemException {
1097                    return groupFinder.findByLiveGroups();
1098            }
1099    
1100            /**
1101             * Returns a range of all non-system groups of a specified type (className)
1102             * that have no layouts.
1103             *
1104             * <p>
1105             * Useful when paginating results. Returns a maximum of <code>end -
1106             * start</code> instances. <code>start</code> and <code>end</code> are not
1107             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1108             * refers to the first result in the set. Setting both <code>start</code>
1109             * and <code>end</code> to {@link
1110             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1111             * result set.
1112             * </p>
1113             *
1114             * @param  className the entity's class name
1115             * @param  privateLayout whether to include groups with private layout sets
1116             *         or non-private layout sets
1117             * @param  start the lower bound of the range of groups to return
1118             * @param  end the upper bound of the range of groups to return (not
1119             *         inclusive)
1120             * @return the range of matching groups
1121             * @throws SystemException if a system exception occurred
1122             */
1123            public List<Group> getNoLayoutsGroups(
1124                            String className, boolean privateLayout, int start, int end)
1125                    throws SystemException {
1126    
1127                    long classNameId = PortalUtil.getClassNameId(className);
1128    
1129                    return groupFinder.findByNoLayouts(
1130                            classNameId, privateLayout, start, end);
1131            }
1132    
1133            /**
1134             * Returns all non-system groups having <code>null</code> or empty friendly
1135             * URLs.
1136             *
1137             * @return the non-system groups having <code>null</code> or empty friendly
1138             *         URLs
1139             * @throws SystemException if a system exception occurred
1140             */
1141            public List<Group> getNullFriendlyURLGroups() throws SystemException {
1142                    return groupFinder.findByNullFriendlyURL();
1143            }
1144    
1145            /**
1146             * Returns the specified organization group.
1147             *
1148             * @param  companyId the primary key of the company
1149             * @param  organizationId the primary key of the organization
1150             * @return the group associated with the organization
1151             * @throws PortalException if a matching group could not be found
1152             * @throws SystemException if a system exception occurred
1153             */
1154            public Group getOrganizationGroup(long companyId, long organizationId)
1155                    throws PortalException, SystemException {
1156    
1157                    long classNameId = PortalUtil.getClassNameId(Organization.class);
1158    
1159                    return groupPersistence.findByC_C_C(
1160                            companyId, classNameId, organizationId);
1161            }
1162    
1163            /**
1164             * Returns the specified organization groups.
1165             *
1166             * @param  organizations the organizations
1167             * @return the groups associated with the organizations
1168             */
1169            public List<Group> getOrganizationsGroups(
1170                    List<Organization> organizations) {
1171    
1172                    List<Group> organizationGroups = new ArrayList<Group>();
1173    
1174                    for (int i = 0; i < organizations.size(); i++) {
1175                            Organization organization = organizations.get(i);
1176    
1177                            Group group = organization.getGroup();
1178    
1179                            organizationGroups.add(group);
1180                    }
1181    
1182                    return organizationGroups;
1183            }
1184    
1185            /**
1186             * Returns all the groups related to the organizations.
1187             *
1188             * @param  organizations the organizations
1189             * @return the groups related to the organizations
1190             * @throws SystemException if a system exception occurred
1191             */
1192            public List<Group> getOrganizationsRelatedGroups(
1193                            List<Organization> organizations)
1194                    throws SystemException {
1195    
1196                    List<Group> organizationGroups = new ArrayList<Group>();
1197    
1198                    for (int i = 0; i < organizations.size(); i++) {
1199                            Organization organization = organizations.get(i);
1200    
1201                            List<Group> groups = organizationPersistence.getGroups(
1202                                    organization.getOrganizationId());
1203    
1204                            organizationGroups.addAll(groups);
1205                    }
1206    
1207                    return organizationGroups;
1208            }
1209    
1210            /**
1211             * Returns all the groups associated with the role.
1212             *
1213             * @param  roleId the primary key of the role
1214             * @return the groups associated with the role
1215             * @throws SystemException if a system exception occurred
1216             */
1217            public List<Group> getRoleGroups(long roleId) throws SystemException {
1218                    return rolePersistence.getGroups(roleId);
1219            }
1220    
1221            /**
1222             * Returns the staging group.
1223             *
1224             * @param  liveGroupId the primary key of the live group
1225             * @return the staging group
1226             * @throws PortalException if a matching staging group could not be found
1227             * @throws SystemException if a system exception occurred
1228             */
1229            public Group getStagingGroup(long liveGroupId)
1230                    throws PortalException, SystemException {
1231    
1232                    return groupPersistence.findByLiveGroupId(liveGroupId);
1233            }
1234    
1235            /**
1236             * Returns the group associated with the user.
1237             *
1238             * @param  companyId the primary key of the company
1239             * @param  userId the primary key of the user
1240             * @return the group associated with the user
1241             * @throws PortalException if a matching group could not be found
1242             * @throws SystemException if a system exception occurred
1243             */
1244            public Group getUserGroup(long companyId, long userId)
1245                    throws PortalException, SystemException {
1246    
1247                    long classNameId = PortalUtil.getClassNameId(User.class);
1248    
1249                    return groupPersistence.findByC_C_C(companyId, classNameId, userId);
1250            }
1251    
1252            /**
1253             * Returns the specified "user group" group. That is, the group that
1254             * represents the {@link com.liferay.portal.model.UserGroup} entity.
1255             *
1256             * @param  companyId the primary key of the company
1257             * @param  userGroupId the primary key of the user group
1258             * @return the group associated with the user group
1259             * @throws PortalException if a matching group could not be found
1260             * @throws SystemException if a system exception occurred
1261             */
1262            public Group getUserGroupGroup(long companyId, long userGroupId)
1263                    throws PortalException, SystemException {
1264    
1265                    long classNameId = PortalUtil.getClassNameId(UserGroup.class);
1266    
1267                    return groupPersistence.findByC_C_C(
1268                            companyId, classNameId, userGroupId);
1269            }
1270    
1271            /**
1272             * Returns all the user's site groups and immediate organization groups.
1273             * System and staged groups are not included.
1274             *
1275             * @param  userId the primary key of the user
1276             * @return the user's groups and organization groups
1277             * @throws PortalException if a user with the primary key could not be found
1278             * @throws SystemException if a system exception occurred
1279             */
1280            public List<Group> getUserGroups(long userId)
1281                    throws PortalException, SystemException {
1282    
1283                    return getUserGroups(userId, false);
1284            }
1285    
1286            /**
1287             * Returns all the user's site groups and immediate organization groups,
1288             * optionally including the user's inherited organization groups and user
1289             * groups. System and staged groups are not included.
1290             *
1291             * @param  userId the primary key of the user
1292             * @param  inherit whether to include the user's inherited organization
1293             *         groups and user groups
1294             * @return the user's groups and immediate organization groups
1295             * @throws PortalException if a user with the primary key could not be found
1296             * @throws SystemException if a system exception occurred
1297             */
1298            public List<Group> getUserGroups(long userId, boolean inherit)
1299                    throws PortalException, SystemException {
1300    
1301                    return getUserGroups(
1302                            userId, inherit, QueryUtil.ALL_POS, QueryUtil.ALL_POS);
1303            }
1304    
1305            /**
1306             * Returns a name ordered range of all the user's site groups and immediate
1307             * organization groups, optionally including the user's inherited
1308             * organization groups and user groups. System and staged groups are not
1309             * included.
1310             *
1311             * <p>
1312             * Useful when paginating results. Returns a maximum of <code>end -
1313             * start</code> instances. <code>start</code> and <code>end</code> are not
1314             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1315             * refers to the first result in the set. Setting both <code>start</code>
1316             * and <code>end</code> to {@link
1317             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1318             * result set.
1319             * </p>
1320             *
1321             * @param  userId the primary key of the user
1322             * @param  inherit whether to include the user's inherited organization
1323             *         groups and user groups
1324             * @param  start the lower bound of the range of groups to return
1325             * @param  end the upper bound of the range of groups to return (not
1326             *         inclusive)
1327             * @return the range of the user's groups and immediate organization groups
1328             *         ordered by name
1329             * @throws PortalException if a user with the primary key could not be found
1330             * @throws SystemException if a system exception occurred
1331             */
1332            public List<Group> getUserGroups(
1333                            long userId, boolean inherit, int start, int end)
1334                    throws PortalException, SystemException {
1335    
1336                    if (inherit) {
1337                            User user = userPersistence.findByPrimaryKey(userId);
1338    
1339                            LinkedHashMap<String, Object> groupParams =
1340                                    new LinkedHashMap<String, Object>();
1341    
1342                            groupParams.put("usersGroups", new Long(userId));
1343    
1344                            return search(
1345                                    user.getCompanyId(), null, null, groupParams, start, end);
1346                    }
1347                    else {
1348                            return userPersistence.getGroups(userId, start, end);
1349                    }
1350            }
1351    
1352            /**
1353             * Returns a name ordered range of all the user's site groups and immediate
1354             * organization groups. System and staged groups are not included.
1355             *
1356             * <p>
1357             * Useful when paginating results. Returns a maximum of <code>end -
1358             * start</code> instances. <code>start</code> and <code>end</code> are not
1359             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1360             * refers to the first result in the set. Setting both <code>start</code>
1361             * and <code>end</code> to {@link
1362             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1363             * result set.
1364             * </p>
1365             *
1366             * @param  userId the primary key of the user
1367             * @param  start the lower bound of the range of groups to return
1368             * @param  end the upper bound of the range of groups to return (not
1369             *         inclusive)
1370             * @return the range of the user's groups and organization groups ordered by
1371             *         name
1372             * @throws PortalException if a user with the primary key could not be found
1373             * @throws SystemException if a system exception occurred
1374             */
1375            public List<Group> getUserGroups(long userId, int start, int end)
1376                    throws PortalException, SystemException {
1377    
1378                    return getUserGroups(userId, false, start, end);
1379            }
1380    
1381            /**
1382             * Returns the groups associated with the user groups.
1383             *
1384             * @param  userGroups the user groups
1385             * @return the groups associated with the user groups
1386             * @throws PortalException if any one of the user group's group could not be
1387             *         found
1388             * @throws SystemException if a system exception occurred
1389             */
1390            public List<Group> getUserGroupsGroups(List<UserGroup> userGroups)
1391                    throws PortalException, SystemException {
1392    
1393                    List<Group> userGroupGroups = new ArrayList<Group>();
1394    
1395                    for (int i = 0; i < userGroups.size(); i++) {
1396                            UserGroup userGroup = userGroups.get(i);
1397    
1398                            Group group = userGroup.getGroup();
1399    
1400                            userGroupGroups.add(group);
1401                    }
1402    
1403                    return userGroupGroups;
1404            }
1405    
1406            /**
1407             * Returns all the groups related to the user groups.
1408             *
1409             * @param  userGroups the user groups
1410             * @return the groups related to the user groups
1411             * @throws SystemException if a system exception occurred
1412             */
1413            public List<Group> getUserGroupsRelatedGroups(List<UserGroup> userGroups)
1414                    throws SystemException {
1415    
1416                    List<Group> userGroupGroups = new ArrayList<Group>();
1417    
1418                    for (int i = 0; i < userGroups.size(); i++) {
1419                            UserGroup userGroup = userGroups.get(i);
1420    
1421                            List<Group> groups = userGroupPersistence.getGroups(
1422                                    userGroup.getUserGroupId());
1423    
1424                            userGroupGroups.addAll(groups);
1425                    }
1426    
1427                    return userGroupGroups;
1428            }
1429    
1430            /**
1431             * Returns the range of all groups associated with the user's organization
1432             * groups, including the ancestors of the organization groups, unless portal
1433             * property <code>organizations.membership.strict</code> is set to
1434             * <code>true</code>.
1435             *
1436             * <p>
1437             * Useful when paginating results. Returns a maximum of <code>end -
1438             * start</code> instances. <code>start</code> and <code>end</code> are not
1439             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1440             * refers to the first result in the set. Setting both <code>start</code>
1441             * and <code>end</code> to {@link
1442             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1443             * result set.
1444             * </p>
1445             *
1446             * @param  userId the primary key of the user
1447             * @param  start the lower bound of the range of groups to consider
1448             * @param  end the upper bound of the range of groups to consider (not
1449             *         inclusive)
1450             * @return the range of groups associated with the user's organization
1451             *         groups
1452             * @throws PortalException if a user with the primary key could not be found
1453             *         or if another portal exception occurred
1454             * @throws SystemException if a system exception occurred
1455             */
1456            public List<Group> getUserOrganizationsGroups(
1457                            long userId, int start, int end)
1458                    throws PortalException, SystemException {
1459    
1460                    List<Group> userOrgsGroups = new UniqueList<Group>();
1461    
1462                    List<Organization> userOrgs =
1463                            organizationLocalService.getUserOrganizations(userId, start, end);
1464    
1465                    for (Organization organization : userOrgs) {
1466                            userOrgsGroups.add(0, organization.getGroup());
1467    
1468                            if (!PropsValues.ORGANIZATIONS_MEMBERSHIP_STRICT) {
1469                                    for (Organization ancestorOrganization :
1470                                                    organization.getAncestors()) {
1471    
1472                                            userOrgsGroups.add(0, ancestorOrganization.getGroup());
1473                                    }
1474                            }
1475                    }
1476    
1477                    return userOrgsGroups;
1478            }
1479    
1480            /**
1481             * Returns <code>true</code> if the group is associated with the role.
1482             *
1483             * @param  roleId the primary key of the role
1484             * @param  groupId the primary key of the group
1485             * @return <code>true</code> if the group is associated with the role;
1486             *         <code>false</code> otherwise
1487             * @throws SystemException if a system exception occurred
1488             */
1489            public boolean hasRoleGroup(long roleId, long groupId)
1490                    throws SystemException {
1491    
1492                    return rolePersistence.containsGroup(roleId, groupId);
1493            }
1494    
1495            /**
1496             * Returns <code>true</code> if the live group has a staging group.
1497             *
1498             * @param  liveGroupId the primary key of the live group
1499             * @return <code>true</code> if the live group has a staging group;
1500             *         <code>false</code> otherwise
1501             * @throws SystemException if a system exception occurred
1502             */
1503            public boolean hasStagingGroup(long liveGroupId) throws SystemException {
1504                    if (groupPersistence.fetchByLiveGroupId(liveGroupId) != null) {
1505                            return true;
1506                    }
1507                    else {
1508                            return false;
1509                    }
1510            }
1511    
1512            /**
1513             * Returns <code>true</code> if the user is immediately associated with the
1514             * group, or associated with the group via the user's organizations,
1515             * inherited organizations, or user groups.
1516             *
1517             * @param  userId the primary key of the user
1518             * @param  groupId the primary key of the group
1519             * @return <code>true</code> if the user is associated with the group;
1520             *         <code>false</code> otherwise
1521             * @throws SystemException if a system exception occurred
1522             */
1523            public boolean hasUserGroup(long userId, long groupId)
1524                    throws SystemException {
1525    
1526                    return hasUserGroup(userId, groupId, true);
1527            }
1528    
1529            /**
1530             * Returns <code>true</code> if the user is immediately associated with the
1531             * group, or optionally if the user is associated with the group via the
1532             * user's organizations, inherited organizations, or user groups.
1533             *
1534             * @param  userId the primary key of the user
1535             * @param  groupId the primary key of the group
1536             * @param  inherit whether to include organization groups and user groups to
1537             *         which the user belongs in the determination
1538             * @return <code>true</code> if the user is associated with the group;
1539             *         <code>false</code> otherwise
1540             * @throws SystemException if a system exception occurred
1541             */
1542            public boolean hasUserGroup(long userId, long groupId, boolean inherit)
1543                    throws SystemException {
1544    
1545                    if (groupFinder.countByG_U(groupId, userId, inherit) > 0) {
1546                            return true;
1547                    }
1548                    else {
1549                            return false;
1550                    }
1551            }
1552    
1553            public Group loadFetchGroup(long companyId, String name)
1554                    throws SystemException {
1555    
1556                    return groupPersistence.fetchByC_N(companyId, name);
1557            }
1558    
1559            public Group loadGetGroup(long companyId, String name)
1560                    throws PortalException, SystemException {
1561    
1562                    return groupPersistence.findByC_N(companyId, name);
1563            }
1564    
1565            public List<Group> search(
1566                            long companyId, LinkedHashMap<String, Object> params, int start,
1567                            int end)
1568                    throws SystemException {
1569    
1570                    return groupFinder.findByCompanyId(
1571                            companyId, params, start, end, new GroupNameComparator(true));
1572            }
1573    
1574            /**
1575             * Returns a name ordered range of all the groups that match the class name
1576             * IDs, name, and description, optionally including the user's inherited
1577             * organization groups and user groups. System and staged groups are not
1578             * included.
1579             *
1580             * <p>
1581             * Useful when paginating results. Returns a maximum of <code>end -
1582             * start</code> instances. <code>start</code> and <code>end</code> are not
1583             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1584             * refers to the first result in the set. Setting both <code>start</code>
1585             * and <code>end</code> to {@link
1586             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1587             * result set.
1588             * </p>
1589             *
1590             * @param  companyId the primary key of the company
1591             * @param  classNameIds the class names of entities to include in the search
1592             *         (optionally <code>null</code>)
1593             * @param  name the group's name (optionally <code>null</code>)
1594             * @param  description the group's description (optionally
1595             *         <code>null</code>)
1596             * @param  params the finder params (optionally <code>null</code>). To
1597             *         include a user's organizations, inherited organizations, and user
1598             *         groups in the search, add an entry with key
1599             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
1600             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
1601             *         For more information see {@link
1602             *         com.liferay.portal.service.persistence.GroupFinder}
1603             *         com.liferay.portal.service.persistence.GroupFinder}
1604             * @param  start the lower bound of the range of groups to return
1605             * @param  end the upper bound of the range of groups to return (not
1606             *         inclusive)
1607             * @return the matching groups ordered by name
1608             * @throws SystemException if a system exception occurred
1609             */
1610            public List<Group> search(
1611                            long companyId, long[] classNameIds, String name,
1612                            String description, LinkedHashMap<String, Object> params, int start,
1613                            int end)
1614                    throws SystemException {
1615    
1616                    return search(
1617                            companyId, classNameIds, name, description, params, start, end,
1618                            null);
1619            }
1620    
1621            /**
1622             * Returns an ordered range of all the groups that match the class name IDs,
1623             * name, and description, optionally including the user's inherited
1624             * organization groups and user groups. System and staged groups are not
1625             * included.
1626             *
1627             * <p>
1628             * Useful when paginating results. Returns a maximum of <code>end -
1629             * start</code> instances. <code>start</code> and <code>end</code> are not
1630             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1631             * refers to the first result in the set. Setting both <code>start</code>
1632             * and <code>end</code> to {@link
1633             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1634             * result set.
1635             * </p>
1636             *
1637             * @param  companyId the primary key of the company
1638             * @param  classNameIds the group's class name IDs (optionally
1639             *         <code>null</code>)
1640             * @param  name the group's name (optionally <code>null</code>)
1641             * @param  description the group's description (optionally
1642             *         <code>null</code>)
1643             * @param  params the finder params (optionally <code>null</code>). To
1644             *         include a user's organizations, inherited organizations, and user
1645             *         groups in the search, add an entry with key
1646             *         &quot;usersGroups&quot; mapped to the user's ID and an entry with
1647             *         key &quot;inherit&quot; mapped to a non-<code>null</code> object.
1648             *         For more information see {@link
1649             *         com.liferay.portal.service.persistence.GroupFinder}
1650             * @param  start the lower bound of the range of groups to return
1651             * @param  end the upper bound of the range of groups to return (not
1652             *         inclusive)
1653             * @param  obc the comparator to order the groups (optionally
1654             *         <code>null</code>)
1655             * @return the matching groups ordered by comparator <code>obc</code>
1656             * @throws SystemException if a system exception occurred
1657             */
1658            public List<Group> search(
1659                            long companyId, long[] classNameIds, String name,
1660                            String description, LinkedHashMap<String, Object> params, int start,
1661                            int end, OrderByComparator obc)
1662                    throws SystemException {
1663    
1664                    if (obc == null) {
1665                            obc = new GroupNameComparator(true);
1666                    }
1667    
1668                    String realName = getRealName(companyId, name);
1669    
1670                    return groupFinder.findByC_C_N_D(
1671                            companyId, classNameIds, name, realName, description, params, start,
1672                            end, obc);
1673            }
1674    
1675            /**
1676             * Returns a name ordered range of all the site groups and organization
1677             * groups that match the name and description, optionally including the
1678             * user's inherited organization groups and user groups. System and staged
1679             * groups are not included.
1680             *
1681             * <p>
1682             * Useful when paginating results. Returns a maximum of <code>end -
1683             * start</code> instances. <code>start</code> and <code>end</code> are not
1684             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1685             * refers to the first result in the set. Setting both <code>start</code>
1686             * and <code>end</code> to {@link
1687             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1688             * result set.
1689             * </p>
1690             *
1691             * @param  companyId the primary key of the company
1692             * @param  name the group's name (optionally <code>null</code>)
1693             * @param  description the group's description (optionally
1694             *         <code>null</code>)
1695             * @param  params the finder params (optionally <code>null</code>). To
1696             *         include the user's inherited organizations and user groups in the
1697             *         search, add entries having &quot;usersGroups&quot; and
1698             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
1699             *         information see {@link
1700             *         com.liferay.portal.service.persistence.GroupFinder}
1701             * @param  start the lower bound of the range of groups to return
1702             * @param  end the upper bound of the range of groups to return (not
1703             *         inclusive)
1704             * @return the matching groups ordered by name
1705             * @throws SystemException if a system exception occurred
1706             */
1707            public List<Group> search(
1708                            long companyId, String name, String description,
1709                            LinkedHashMap<String, Object> params, int start, int end)
1710                    throws SystemException {
1711    
1712                    return search(companyId, name, description, params, start, end, null);
1713            }
1714    
1715            /**
1716             * Returns an ordered range of all the site groups and organization groups
1717             * that match the name and description, optionally including the user's
1718             * inherited organization groups and user groups. System and staged groups
1719             * are not included.
1720             *
1721             * <p>
1722             * Useful when paginating results. Returns a maximum of <code>end -
1723             * start</code> instances. <code>start</code> and <code>end</code> are not
1724             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1725             * refers to the first result in the set. Setting both <code>start</code>
1726             * and <code>end</code> to {@link
1727             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1728             * result set.
1729             * </p>
1730             *
1731             * @param  companyId the primary key of the company
1732             * @param  name the group's name (optionally <code>null</code>)
1733             * @param  description the group's description (optionally
1734             *         <code>null</code>)
1735             * @param  params the finder params (optionally <code>null</code>). To
1736             *         include the user's inherited organizations and user groups in the
1737             *         search, add entries having &quot;usersGroups&quot; and
1738             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
1739             *         information see {@link
1740             *         com.liferay.portal.service.persistence.GroupFinder}
1741             * @param  start the lower bound of the range of groups to return
1742             * @param  end the upper bound of the range of groups to return (not
1743             *         inclusive)
1744             * @param  obc the comparator to order the groups (optionally
1745             *         <code>null</code>)
1746             * @return the matching groups ordered by comparator <code>obc</code>
1747             * @throws SystemException if a system exception occurred
1748             */
1749            public List<Group> search(
1750                            long companyId, String name, String description,
1751                            LinkedHashMap<String, Object> params, int start, int end,
1752                            OrderByComparator obc)
1753                    throws SystemException {
1754    
1755                    if (obc == null) {
1756                            obc = new GroupNameComparator(true);
1757                    }
1758    
1759                    String realName = getRealName(companyId, name);
1760    
1761                    return groupFinder.findByC_N_D(
1762                            companyId, name, realName, description, params, start, end, obc);
1763            }
1764    
1765            /**
1766             * Returns the number of groups that match the class name IDs, name, and
1767             * description, optionally including the user's inherited organization
1768             * groups and user groups. System and staged groups are not included.
1769             *
1770             * @param  companyId the primary key of the company
1771             * @param  classNameIds the class names of entities to include in the search
1772             *         (optionally <code>null</code>)
1773             * @param  name the group's name (optionally <code>null</code>)
1774             * @param  description the group's description (optionally
1775             *         <code>null</code>)
1776             * @param  params the finder params (optionally <code>null</code>). To
1777             *         include the user's inherited organization groups and user groups
1778             *         in the search, add entries having &quot;usersGroups&quot; and
1779             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
1780             *         information see {@link
1781             *         com.liferay.portal.service.persistence.GroupFinder}
1782             * @return the number of matching groups
1783             * @throws SystemException if a system exception occurred
1784             */
1785            @ThreadLocalCachable
1786            public int searchCount(
1787                            long companyId, long[] classNameIds, String name,
1788                            String description, LinkedHashMap<String, Object> params)
1789                    throws SystemException {
1790    
1791                    String realName = getRealName(companyId, name);
1792    
1793                    return groupFinder.countByC_C_N_D(
1794                            companyId, classNameIds, name, realName, description, params);
1795            }
1796    
1797            /**
1798             * Returns the number of groups and immediate organization groups that match
1799             * the name and description, optionally including the user's inherited
1800             * organization groups and user groups. System and staged groups are not
1801             * included.
1802             *
1803             * @param  companyId the primary key of the company
1804             * @param  name the group's name (optionally <code>null</code>)
1805             * @param  description the group's description (optionally
1806             *         <code>null</code>)
1807             * @param  params the finder params (optionally <code>null</code>). To
1808             *         include the user's inherited organization groups and user groups
1809             *         in the search, add entries having &quot;usersGroups&quot; and
1810             *         &quot;inherit&quot; as keys mapped to the the user's ID. For more
1811             *         information see {@link
1812             *         com.liferay.portal.service.persistence.GroupFinder}
1813             * @return the number of matching groups
1814             * @throws SystemException if a system exception occurred
1815             */
1816            @ThreadLocalCachable
1817            public int searchCount(
1818                            long companyId, String name, String description,
1819                            LinkedHashMap<String, Object> params)
1820                    throws SystemException {
1821    
1822                    String realName = getRealName(companyId, name);
1823    
1824                    return groupFinder.countByC_N_D(
1825                            companyId, name, realName, description, params);
1826            }
1827    
1828            /**
1829             * Sets the groups associated with the role, removing and adding
1830             * associations as necessary.
1831             *
1832             * @param  roleId the primary key of the role
1833             * @param  groupIds the primary keys of the groups
1834             * @throws SystemException if a system exception occurred
1835             */
1836            public void setRoleGroups(long roleId, long[] groupIds)
1837                    throws SystemException {
1838    
1839                    rolePersistence.setGroups(roleId, groupIds);
1840    
1841                    PermissionCacheUtil.clearCache();
1842            }
1843    
1844            /**
1845             * Removes the groups from the role.
1846             *
1847             * @param  roleId the primary key of the role
1848             * @param  groupIds the primary keys of the groups
1849             * @throws SystemException if a system exception occurred
1850             */
1851            public void unsetRoleGroups(long roleId, long[] groupIds)
1852                    throws SystemException {
1853    
1854                    rolePersistence.removeGroups(roleId, groupIds);
1855    
1856                    PermissionCacheUtil.clearCache();
1857            }
1858    
1859            /**
1860             * Removes the user from the groups.
1861             *
1862             * @param  userId the primary key of the user
1863             * @param  groupIds the primary keys of the groups
1864             * @throws SystemException if a system exception occurred
1865             */
1866            public void unsetUserGroups(long userId, long[] groupIds)
1867                    throws SystemException {
1868    
1869                    userGroupRoleLocalService.deleteUserGroupRoles(userId, groupIds);
1870    
1871                    userPersistence.removeGroups(userId, groupIds);
1872    
1873                    PermissionCacheUtil.clearCache();
1874            }
1875    
1876            /**
1877             * Updates the group's asset replacing categories and tag names.
1878             *
1879             * @param  userId the primary key of the user
1880             * @param  group the group
1881             * @param  assetCategoryIds the primary keys of the asset categories
1882             *         (optionally <code>null</code>)
1883             * @param  assetTagNames the asset tag names (optionally <code>null</code>)
1884             * @throws PortalException if a user with the primary key could not be found
1885             * @throws SystemException if a system exception occurred
1886             */
1887            public void updateAsset(
1888                            long userId, Group group, long[] assetCategoryIds,
1889                            String[] assetTagNames)
1890                    throws PortalException, SystemException {
1891    
1892                    User user = userPersistence.findByPrimaryKey(userId);
1893    
1894                    Company company = companyPersistence.findByPrimaryKey(
1895                            user.getCompanyId());
1896    
1897                    Group companyGroup = company.getGroup();
1898    
1899                    assetEntryLocalService.updateEntry(
1900                            userId, companyGroup.getGroupId(), Group.class.getName(),
1901                            group.getGroupId(), null, 0, assetCategoryIds, assetTagNames, false,
1902                            null, null, null, null, null, group.getDescriptiveName(),
1903                            group.getDescription(), null, null, null, 0, 0, null, false);
1904            }
1905    
1906            /**
1907             * Updates the group's friendly URL.
1908             *
1909             * @param  groupId the primary key of the group
1910             * @param  friendlyURL the group's new friendlyURL (optionally
1911             *         <code>null</code>)
1912             * @return the group
1913             * @throws PortalException if a group with the primary key could not be
1914             *         found or if a valid friendly URL could not be created for the
1915             *         group
1916             * @throws SystemException if a system exception occurred
1917             */
1918            public Group updateFriendlyURL(long groupId, String friendlyURL)
1919                    throws PortalException, SystemException {
1920    
1921                    Group group = groupPersistence.findByPrimaryKey(groupId);
1922    
1923                    if (group.isUser()) {
1924                            User user = userPersistence.findByPrimaryKey(group.getClassPK());
1925    
1926                            friendlyURL = StringPool.SLASH + user.getScreenName();
1927    
1928                            if (group.getFriendlyURL().equals(friendlyURL)) {
1929                                    return group;
1930                            }
1931                    }
1932    
1933                    friendlyURL = getFriendlyURL(
1934                            group.getCompanyId(), groupId, group.getClassNameId(),
1935                            group.getClassPK(), StringPool.BLANK, friendlyURL);
1936    
1937                    validateFriendlyURL(
1938                            group.getCompanyId(), group.getGroupId(), group.getClassNameId(),
1939                            group.getClassPK(), friendlyURL);
1940    
1941                    group.setFriendlyURL(friendlyURL);
1942    
1943                    groupPersistence.update(group, false);
1944    
1945                    return group;
1946            }
1947    
1948            /**
1949             * Updates the group's type settings.
1950             *
1951             * @param  groupId the primary key of the group
1952             * @param  typeSettings the group's new type settings (optionally
1953             *         <code>null</code>)
1954             * @return the group
1955             * @throws PortalException if a group with the primary key could not be
1956             *         found
1957             * @throws SystemException if a system exception occurred
1958             */
1959            public Group updateGroup(long groupId, String typeSettings)
1960                    throws PortalException, SystemException {
1961    
1962                    Group group = groupPersistence.findByPrimaryKey(groupId);
1963    
1964                    group.setTypeSettings(typeSettings);
1965    
1966                    groupPersistence.update(group, false);
1967    
1968                    return group;
1969            }
1970    
1971            /**
1972             * Updates the group.
1973             *
1974             * @param  groupId the primary key of the group
1975             * @param  name the group's new name
1976             * @param  description the group's new description (optionally
1977             *         <code>null</code>)
1978             * @param  type the group's new type. For more information see {@link
1979             *         com.liferay.portal.model.GroupConstants}
1980             * @param  friendlyURL the group's new friendlyURL (optionally
1981             *         <code>null</code>)
1982             * @param  active whether the group is active
1983             * @param  serviceContext the service context to be applied (optionally
1984             *         <code>null</code>). Can set asset category IDs and asset tag
1985             *         names for the group.
1986             * @return the group
1987             * @throws PortalException if a group with the primary key could not be
1988             *         found or if the friendly URL was invalid or could one not be
1989             *         created
1990             * @throws SystemException if a system exception occurred
1991             */
1992            public Group updateGroup(
1993                            long groupId, String name, String description, int type,
1994                            String friendlyURL, boolean active, ServiceContext serviceContext)
1995                    throws PortalException, SystemException {
1996    
1997                    Group group = groupPersistence.findByPrimaryKey(groupId);
1998    
1999                    String className = group.getClassName();
2000                    long classNameId = group.getClassNameId();
2001                    long classPK = group.getClassPK();
2002                    friendlyURL = getFriendlyURL(
2003                            group.getCompanyId(), groupId, classNameId, classPK,
2004                            StringPool.BLANK, friendlyURL);
2005    
2006                    if ((classNameId <= 0) || className.equals(Group.class.getName())) {
2007                            validateName(
2008                                    group.getGroupId(), group.getCompanyId(), name, group.isSite());
2009                    }
2010                    else if (className.equals(Organization.class.getName())) {
2011                            Organization organization =
2012                                    organizationPersistence.findByPrimaryKey(classPK);
2013    
2014                            name = getOrgGroupName(organization.getName());
2015                    }
2016                    else if (!GroupConstants.USER_PERSONAL_SITE.equals(name)) {
2017                            name = String.valueOf(classPK);
2018                    }
2019    
2020                    if (PortalUtil.isSystemGroup(group.getName()) &&
2021                            !group.getName().equals(name)) {
2022    
2023                            throw new RequiredGroupException();
2024                    }
2025    
2026                    validateFriendlyURL(
2027                            group.getCompanyId(), group.getGroupId(), group.getClassNameId(),
2028                            group.getClassPK(), friendlyURL);
2029    
2030                    group.setName(name);
2031                    group.setDescription(description);
2032                    group.setType(type);
2033                    group.setFriendlyURL(friendlyURL);
2034                    group.setActive(active);
2035    
2036                    if ((serviceContext != null) && group.isSite()) {
2037                            group.setExpandoBridgeAttributes(serviceContext);
2038                    }
2039    
2040                    groupPersistence.update(group, false);
2041    
2042                    // Asset
2043    
2044                    if ((serviceContext != null) && group.isSite()) {
2045                            User user = null;
2046    
2047                            try {
2048                                    user = userPersistence.findByPrimaryKey(
2049                                            group.getCreatorUserId());
2050    
2051                            }
2052                            catch (NoSuchUserException nsue1) {
2053                                    try {
2054                                            user = userPersistence.findByPrimaryKey(
2055                                                    serviceContext.getUserId());
2056                                    }
2057                                    catch (NoSuchUserException nsue2) {
2058                                            user = userLocalService.getDefaultUser(
2059                                                    group.getCompanyId());
2060                                    }
2061                            }
2062    
2063                            updateAsset(
2064                                    user.getUserId(), group, serviceContext.getAssetCategoryIds(),
2065                                    serviceContext.getAssetTagNames());
2066                    }
2067    
2068                    return group;
2069            }
2070    
2071            /**
2072             * Associates the group with a main site if the group is an organization.
2073             *
2074             * @param  groupId the primary key of the group
2075             * @param  site whether the group is to be associated with a main site
2076             * @return the group
2077             * @throws PortalException if a group with the primary key could not be
2078             *         found
2079             * @throws SystemException if a system exception occurred
2080             */
2081            public Group updateSite(long groupId, boolean site)
2082                    throws PortalException, SystemException {
2083    
2084                    Group group = groupPersistence.findByPrimaryKey(groupId);
2085    
2086                    if (!group.isOrganization()) {
2087                            return group;
2088                    }
2089    
2090                    group.setSite(site);
2091    
2092                    groupPersistence.update(group, false);
2093    
2094                    return group;
2095            }
2096    
2097            protected void addControlPanelLayouts(Group group)
2098                    throws PortalException, SystemException {
2099    
2100                    long defaultUserId = userLocalService.getDefaultUserId(
2101                            group.getCompanyId());
2102    
2103                    String friendlyURL = getFriendlyURL(
2104                            PropsValues.CONTROL_PANEL_LAYOUT_FRIENDLY_URL);
2105    
2106                    ServiceContext serviceContext = new ServiceContext();
2107    
2108                    layoutLocalService.addLayout(
2109                            defaultUserId, group.getGroupId(), true,
2110                            LayoutConstants.DEFAULT_PARENT_LAYOUT_ID,
2111                            PropsValues.CONTROL_PANEL_LAYOUT_NAME, StringPool.BLANK,
2112                            StringPool.BLANK, LayoutConstants.TYPE_CONTROL_PANEL, false,
2113                            friendlyURL, serviceContext);
2114            }
2115    
2116            protected void addDefaultGuestPublicLayoutByProperties(Group group)
2117                    throws PortalException, SystemException {
2118    
2119                    long defaultUserId = userLocalService.getDefaultUserId(
2120                            group.getCompanyId());
2121                    String friendlyURL = getFriendlyURL(
2122                            PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_FRIENDLY_URL);
2123    
2124                    ServiceContext serviceContext = new ServiceContext();
2125    
2126                    Layout layout = layoutLocalService.addLayout(
2127                            defaultUserId, group.getGroupId(), false,
2128                            LayoutConstants.DEFAULT_PARENT_LAYOUT_ID,
2129                            PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_NAME, StringPool.BLANK,
2130                            StringPool.BLANK, LayoutConstants.TYPE_PORTLET, false, friendlyURL,
2131                            serviceContext);
2132    
2133                    LayoutTypePortlet layoutTypePortlet =
2134                            (LayoutTypePortlet)layout.getLayoutType();
2135    
2136                    layoutTypePortlet.setLayoutTemplateId(
2137                            0, PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_TEMPLATE_ID, false);
2138    
2139                    for (int i = 0; i < 10; i++) {
2140                            String columnId = "column-" + i;
2141                            String portletIds = PropsUtil.get(
2142                                    PropsKeys.DEFAULT_GUEST_PUBLIC_LAYOUT_COLUMN + i);
2143    
2144                            layoutTypePortlet.addPortletIds(
2145                                    0, StringUtil.split(portletIds), columnId, false);
2146                    }
2147    
2148                    layoutLocalService.updateLayout(
2149                            layout.getGroupId(), layout.isPrivateLayout(), layout.getLayoutId(),
2150                            layout.getTypeSettings());
2151    
2152                    boolean updateLayoutSet = false;
2153    
2154                    LayoutSet layoutSet = layout.getLayoutSet();
2155    
2156                    if (Validator.isNotNull(
2157                                    PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_REGULAR_THEME_ID)) {
2158    
2159                            layoutSet.setThemeId(
2160                                    PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_REGULAR_THEME_ID);
2161    
2162                            updateLayoutSet = true;
2163                    }
2164    
2165                    if (Validator.isNotNull(
2166                                    PropsValues.
2167                                            DEFAULT_GUEST_PUBLIC_LAYOUT_REGULAR_COLOR_SCHEME_ID)) {
2168    
2169                            layoutSet.setColorSchemeId(
2170                                    PropsValues.
2171                                            DEFAULT_GUEST_PUBLIC_LAYOUT_REGULAR_COLOR_SCHEME_ID);
2172    
2173                            updateLayoutSet = true;
2174                    }
2175    
2176                    if (Validator.isNotNull(
2177                                    PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_WAP_THEME_ID)) {
2178    
2179                            layoutSet.setWapThemeId(
2180                                    PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_WAP_THEME_ID);
2181    
2182                            updateLayoutSet = true;
2183                    }
2184    
2185                    if (Validator.isNotNull(
2186                                    PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_WAP_COLOR_SCHEME_ID)) {
2187    
2188                            layoutSet.setWapColorSchemeId(
2189                                    PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUT_WAP_COLOR_SCHEME_ID);
2190    
2191                            updateLayoutSet = true;
2192                    }
2193    
2194                    if (updateLayoutSet) {
2195                            layoutSetLocalService.updateLayoutSet(layoutSet);
2196                    }
2197            }
2198    
2199            protected void addDefaultGuestPublicLayouts(Group group)
2200                    throws PortalException, SystemException {
2201    
2202                    if (publicLARFile != null) {
2203                            addDefaultGuestPublicLayoutsByLAR(group, publicLARFile);
2204                    }
2205                    else {
2206                            addDefaultGuestPublicLayoutByProperties(group);
2207                    }
2208            }
2209    
2210            protected void addDefaultGuestPublicLayoutsByLAR(Group group, File larFile)
2211                    throws PortalException, SystemException {
2212    
2213                    long defaultUserId = userLocalService.getDefaultUserId(
2214                            group.getCompanyId());
2215    
2216                    Map<String, String[]> parameterMap = new HashMap<String, String[]>();
2217    
2218                    parameterMap.put(
2219                            PortletDataHandlerKeys.CATEGORIES,
2220                            new String[] {Boolean.TRUE.toString()});
2221                    parameterMap.put(
2222                            PortletDataHandlerKeys.PERMISSIONS,
2223                            new String[] {Boolean.TRUE.toString()});
2224                    parameterMap.put(
2225                            PortletDataHandlerKeys.PORTLET_DATA,
2226                            new String[] {Boolean.TRUE.toString()});
2227                    parameterMap.put(
2228                            PortletDataHandlerKeys.PORTLET_DATA_CONTROL_DEFAULT,
2229                            new String[] {Boolean.TRUE.toString()});
2230                    parameterMap.put(
2231                            PortletDataHandlerKeys.PORTLET_SETUP,
2232                            new String[] {Boolean.TRUE.toString()});
2233                    parameterMap.put(
2234                            PortletDataHandlerKeys.USER_PERMISSIONS,
2235                            new String[] {Boolean.FALSE.toString()});
2236    
2237                    layoutLocalService.importLayouts(
2238                            defaultUserId, group.getGroupId(), false, parameterMap, larFile);
2239            }
2240    
2241            protected String getFriendlyURL(
2242                            long companyId, long groupId, long classNameId, long classPK,
2243                            String friendlyName, String friendlyURL)
2244                    throws PortalException, SystemException {
2245    
2246                    friendlyURL = getFriendlyURL(friendlyURL);
2247    
2248                    if (Validator.isNotNull(friendlyURL)) {
2249                            return friendlyURL;
2250                    }
2251    
2252                    friendlyURL = StringPool.SLASH + getFriendlyURL(friendlyName);
2253    
2254                    String originalFriendlyURL = friendlyURL;
2255    
2256                    for (int i = 1;; i++) {
2257                            try {
2258                                    validateFriendlyURL(
2259                                            companyId, groupId, classNameId, classPK, friendlyURL);
2260    
2261                                    break;
2262                            }
2263                            catch (GroupFriendlyURLException gfurle) {
2264                                    int type = gfurle.getType();
2265    
2266                                    if (type == GroupFriendlyURLException.DUPLICATE) {
2267                                            friendlyURL = originalFriendlyURL + i;
2268                                    }
2269                                    else {
2270                                            friendlyURL = StringPool.SLASH + classPK;
2271    
2272                                            break;
2273                                    }
2274                            }
2275                    }
2276    
2277                    return friendlyURL;
2278            }
2279    
2280            protected String getFriendlyURL(String friendlyURL) {
2281                    return FriendlyURLNormalizerUtil.normalize(friendlyURL);
2282            }
2283    
2284            protected String getOrgGroupName(String name) {
2285                    return name + ORGANIZATION_NAME_SUFFIX;
2286            }
2287    
2288            protected String getRealName(long companyId, String name)
2289                    throws SystemException {
2290    
2291                    if (Validator.isNull(name)) {
2292                            return name;
2293                    }
2294    
2295                    String realName = name;
2296    
2297                    try {
2298                            Company company = companyLocalService.getCompany(companyId);
2299    
2300                            Account account = company.getAccount();
2301    
2302                            String companyName = account.getName();
2303    
2304                            name = StringUtil.replace(
2305                                    name, StringPool.PERCENT, StringPool.BLANK);
2306    
2307                            if (companyName.indexOf(name) != -1) {
2308                                    realName =
2309                                            StringPool.PERCENT + GroupConstants.GUEST +
2310                                                    StringPool.PERCENT;
2311                            }
2312                    }
2313                    catch (PortalException pe) {
2314                    }
2315    
2316                    return realName;
2317            }
2318    
2319            protected void initImportLARFile() {
2320                    String publicLARFileName = PropsValues.DEFAULT_GUEST_PUBLIC_LAYOUTS_LAR;
2321    
2322                    if (_log.isDebugEnabled()) {
2323                            _log.debug("Reading public LAR file " + publicLARFileName);
2324                    }
2325    
2326                    if (Validator.isNotNull(publicLARFileName)) {
2327                            publicLARFile = new File(publicLARFileName);
2328    
2329                            if (!publicLARFile.exists()) {
2330                                    _log.error(
2331                                            "Public LAR file " + publicLARFile + " does not exist");
2332    
2333                                    publicLARFile = null;
2334                            }
2335                            else {
2336                                    if (_log.isDebugEnabled()) {
2337                                            _log.debug("Using public LAR file " + publicLARFileName);
2338                                    }
2339                            }
2340                    }
2341            }
2342    
2343            protected void initUserPersonalSitePermissions(Group group)
2344                    throws PortalException, SystemException {
2345    
2346                    // User role
2347    
2348                    Role role = roleLocalService.getRole(
2349                            group.getCompanyId(), RoleConstants.USER);
2350    
2351                    setCompanyPermissions(
2352                            role, PortletKeys.PORTAL,
2353                            new String[] {ActionKeys.VIEW_CONTROL_PANEL});
2354    
2355                    List<Portlet> portlets = portletLocalService.getPortlets(
2356                            group.getCompanyId(), false, false);
2357    
2358                    for (Portlet portlet : portlets) {
2359                            setRolePermissions(
2360                                    group, role, portlet.getPortletId(),
2361                                    new String[] {ActionKeys.VIEW});
2362                    }
2363    
2364                    setRolePermissions(
2365                            group, role, Layout.class.getName(),
2366                            new String[] {ActionKeys.VIEW});
2367    
2368                    setRolePermissions(
2369                            group, role, "com.liferay.portlet.blogs",
2370                            new String[] {
2371                                    ActionKeys.ADD_ENTRY, ActionKeys.PERMISSIONS,
2372                                    ActionKeys.SUBSCRIBE});
2373    
2374                    setRolePermissions(
2375                            group, role, "com.liferay.portlet.calendar",
2376                            new String[] {
2377                                    ActionKeys.ADD_EVENT, ActionKeys.EXPORT_ALL_EVENTS,
2378                                    ActionKeys.PERMISSIONS});
2379    
2380                    // Power User role
2381    
2382                    role = roleLocalService.getRole(
2383                            group.getCompanyId(), RoleConstants.POWER_USER);
2384    
2385                    for (Portlet portlet : portlets) {
2386                            List<String> actions =
2387                                    ResourceActionsUtil.getPortletResourceActions(
2388                                            portlet.getPortletId());
2389    
2390                            String controlPanelEntryCategory = GetterUtil.getString(
2391                                    portlet.getControlPanelEntryCategory());
2392    
2393                            if (actions.contains(ActionKeys.ACCESS_IN_CONTROL_PANEL) &&
2394                                    controlPanelEntryCategory.equals(PortletCategoryKeys.CONTENT)) {
2395    
2396                                    setRolePermissions(
2397                                            group, role, portlet.getPortletId(),
2398                                            new String[] {ActionKeys.ACCESS_IN_CONTROL_PANEL});
2399                            }
2400                    }
2401    
2402                    setRolePermissions(
2403                            group, role, Group.class.getName(),
2404                            new String[] {ActionKeys.MANAGE_LAYOUTS});
2405    
2406                    setRolePermissions(group, role, "com.liferay.portlet.asset");
2407                    setRolePermissions(group, role, "com.liferay.portlet.blogs");
2408                    setRolePermissions(group, role, "com.liferay.portlet.bookmarks");
2409                    setRolePermissions(group, role, "com.liferay.portlet.calendar");
2410                    setRolePermissions(group, role, "com.liferay.portlet.documentlibrary");
2411                    setRolePermissions(group, role, "com.liferay.portlet.imagegallery");
2412                    setRolePermissions(group, role, "com.liferay.portlet.messageboards");
2413                    setRolePermissions(group, role, "com.liferay.portlet.polls");
2414                    setRolePermissions(group, role, "com.liferay.portlet.wiki");
2415            }
2416    
2417            protected boolean isStaging(ServiceContext serviceContext) {
2418                    if (serviceContext != null) {
2419                            return ParamUtil.getBoolean(serviceContext, "staging");
2420                    }
2421    
2422                    return false;
2423            }
2424    
2425            protected void setCompanyPermissions(
2426                            Role role, String name, String[] actionIds)
2427                    throws PortalException, SystemException {
2428    
2429                    if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) {
2430                            if (resourceBlockLocalService.isSupported(name)) {
2431                                    resourceBlockLocalService.setCompanyScopePermissions(
2432                                            role.getCompanyId(), name, role.getRoleId(),
2433                                            Arrays.asList(actionIds));
2434                            }
2435                            else {
2436                                    resourcePermissionLocalService.setResourcePermissions(
2437                                            role.getCompanyId(), name, ResourceConstants.SCOPE_COMPANY,
2438                                            String.valueOf(role.getCompanyId()), role.getRoleId(),
2439                                            actionIds);
2440                            }
2441                    }
2442                    else {
2443                            permissionLocalService.setRolePermissions(
2444                                    role.getRoleId(), role.getCompanyId(), name,
2445                                    ResourceConstants.SCOPE_COMPANY,
2446                                    String.valueOf(role.getCompanyId()), actionIds);
2447                    }
2448            }
2449    
2450            protected void setRolePermissions(Group group, Role role, String name)
2451                    throws PortalException, SystemException {
2452    
2453                    List<String> actions = ResourceActionsUtil.getModelResourceActions(
2454                            name);
2455    
2456                    setRolePermissions(
2457                            group, role, name, actions.toArray(new String[actions.size()]));
2458            }
2459    
2460            protected void setRolePermissions(
2461                            Group group, Role role, String name, String[] actionIds)
2462                    throws PortalException, SystemException {
2463    
2464                    if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) {
2465                            if (resourceBlockLocalService.isSupported(name)) {
2466                                    resourceBlockLocalService.setGroupScopePermissions(
2467                                            role.getCompanyId(), group.getGroupId(), name,
2468                                            role.getRoleId(), Arrays.asList(actionIds));
2469                            }
2470                            else {
2471                                    resourcePermissionLocalService.setResourcePermissions(
2472                                            group.getCompanyId(), name, ResourceConstants.SCOPE_GROUP,
2473                                            String.valueOf(group.getGroupId()), role.getRoleId(),
2474                                            actionIds);
2475                            }
2476                    }
2477                    else {
2478                            permissionLocalService.setRolePermissions(
2479                                    role.getRoleId(), group.getCompanyId(), name,
2480                                    ResourceConstants.SCOPE_GROUP,
2481                                    String.valueOf(group.getGroupId()), actionIds);
2482                    }
2483            }
2484    
2485            protected void unscheduleStaging(Group group) {
2486                    try {
2487    
2488                            // Remote publishing
2489    
2490                            String groupName = StagingUtil.getSchedulerGroupName(
2491                                    DestinationNames.LAYOUTS_REMOTE_PUBLISHER, group.getGroupId());
2492    
2493                            SchedulerEngineUtil.delete(groupName, StorageType.PERSISTED);
2494    
2495                            long liveGroupId = 0;
2496                            long stagingGroupId = 0;
2497    
2498                            if (group.isStagingGroup()) {
2499                                    liveGroupId = group.getLiveGroupId();
2500    
2501                                    stagingGroupId = group.getGroupId();
2502                            }
2503                            else if (group.hasStagingGroup()) {
2504                                    liveGroupId = group.getGroupId();
2505    
2506                                    stagingGroupId = group.getStagingGroup().getGroupId();
2507                            }
2508    
2509                            if ((liveGroupId != 0) && (stagingGroupId != 0)) {
2510    
2511                                    // Publish to live
2512    
2513                                    groupName = StagingUtil.getSchedulerGroupName(
2514                                            DestinationNames.LAYOUTS_LOCAL_PUBLISHER, liveGroupId);
2515    
2516                                    SchedulerEngineUtil.delete(groupName, StorageType.PERSISTED);
2517    
2518                                    // Copy from live
2519    
2520                                    groupName = StagingUtil.getSchedulerGroupName(
2521                                            DestinationNames.LAYOUTS_LOCAL_PUBLISHER, stagingGroupId);
2522    
2523                                    SchedulerEngineUtil.delete(groupName, StorageType.PERSISTED);
2524                            }
2525                    }
2526                    catch (Exception e) {
2527                            _log.error(
2528                                    "Unable to unschedule events for group: " + group.getGroupId());
2529                    }
2530            }
2531    
2532            protected void validateFriendlyURL(
2533                            long companyId, long groupId, long classNameId, long classPK,
2534                            String friendlyURL)
2535                    throws PortalException, SystemException {
2536    
2537                    Company company = companyPersistence.findByPrimaryKey(companyId);
2538    
2539                    if (company.isSystem()) {
2540                            return;
2541                    }
2542    
2543                    if (Validator.isNull(friendlyURL)) {
2544                            return;
2545                    }
2546    
2547                    int exceptionType = LayoutImpl.validateFriendlyURL(friendlyURL);
2548    
2549                    if (exceptionType != -1) {
2550                            throw new GroupFriendlyURLException(exceptionType);
2551                    }
2552    
2553                    Group group = groupPersistence.fetchByC_F(companyId, friendlyURL);
2554    
2555                    if ((group != null) && (group.getGroupId() != groupId)) {
2556                            throw new GroupFriendlyURLException(
2557                                    GroupFriendlyURLException.DUPLICATE);
2558                    }
2559    
2560                    String groupIdFriendlyURL = friendlyURL.substring(1);
2561    
2562                    if (Validator.isNumber(groupIdFriendlyURL)) {
2563                            long groupClassNameId = PortalUtil.getClassNameId(Group.class);
2564    
2565                            if (((classNameId != groupClassNameId) &&
2566                                     !groupIdFriendlyURL.equals(String.valueOf(classPK)) &&
2567                                     !PropsValues.USERS_SCREEN_NAME_ALLOW_NUMERIC) ||
2568                                    ((classNameId == groupClassNameId) &&
2569                                     !groupIdFriendlyURL.equals(String.valueOf(groupId)))) {
2570    
2571                                    GroupFriendlyURLException gfurle =
2572                                            new GroupFriendlyURLException(
2573                                                    GroupFriendlyURLException.POSSIBLE_DUPLICATE);
2574    
2575                                    gfurle.setKeywordConflict(groupIdFriendlyURL);
2576    
2577                                    throw gfurle;
2578                            }
2579                    }
2580    
2581                    String screenName = friendlyURL.substring(1);
2582    
2583                    User user = userPersistence.fetchByC_SN(companyId, screenName);
2584    
2585                    if (user != null) {
2586                            long userClassNameId = PortalUtil.getClassNameId(User.class);
2587    
2588                            if ((classNameId == userClassNameId) &&
2589                                    (classPK == user.getUserId())) {
2590                            }
2591                            else {
2592                                    throw new GroupFriendlyURLException(
2593                                            GroupFriendlyURLException.DUPLICATE);
2594                            }
2595                    }
2596    
2597                    if (StringUtil.count(friendlyURL, StringPool.SLASH) > 1) {
2598                            throw new GroupFriendlyURLException(
2599                                    GroupFriendlyURLException.TOO_DEEP);
2600                    }
2601            }
2602    
2603            protected void validateName(
2604                            long groupId, long companyId, String name, boolean site)
2605                    throws PortalException, SystemException {
2606    
2607                    if (Validator.isNull(name) || Validator.isNumber(name) ||
2608                            name.contains(StringPool.STAR) ||
2609                            name.contains(ORGANIZATION_NAME_SUFFIX)) {
2610    
2611                            throw new GroupNameException();
2612                    }
2613    
2614                    try {
2615                            Group group = groupFinder.findByC_N(companyId, name);
2616    
2617                            if ((groupId <= 0) || (group.getGroupId() != groupId)) {
2618                                    throw new DuplicateGroupException();
2619                            }
2620                    }
2621                    catch (NoSuchGroupException nsge) {
2622                    }
2623    
2624                    if (site) {
2625                            Company company = companyLocalService.getCompany(companyId);
2626    
2627                            if (name.equals(company.getName())) {
2628                                    throw new DuplicateGroupException();
2629                            }
2630                    }
2631            }
2632    
2633            protected File publicLARFile;
2634    
2635            private static Log _log = LogFactoryUtil.getLog(
2636                    GroupLocalServiceImpl.class);
2637    
2638            private Map<String, Group> _systemGroupsMap = new HashMap<String, Group>();
2639    
2640    }