001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.service.impl;
016    
017    import com.liferay.portal.DuplicateOrganizationException;
018    import com.liferay.portal.OrganizationNameException;
019    import com.liferay.portal.OrganizationParentException;
020    import com.liferay.portal.OrganizationTypeException;
021    import com.liferay.portal.RequiredOrganizationException;
022    import com.liferay.portal.kernel.cache.ThreadLocalCachable;
023    import com.liferay.portal.kernel.configuration.Filter;
024    import com.liferay.portal.kernel.dao.orm.QueryUtil;
025    import com.liferay.portal.kernel.exception.PortalException;
026    import com.liferay.portal.kernel.exception.SystemException;
027    import com.liferay.portal.kernel.search.Hits;
028    import com.liferay.portal.kernel.search.Indexer;
029    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
030    import com.liferay.portal.kernel.search.QueryConfig;
031    import com.liferay.portal.kernel.search.SearchContext;
032    import com.liferay.portal.kernel.search.Sort;
033    import com.liferay.portal.kernel.util.ArrayUtil;
034    import com.liferay.portal.kernel.util.GetterUtil;
035    import com.liferay.portal.kernel.util.ListUtil;
036    import com.liferay.portal.kernel.util.OrderByComparator;
037    import com.liferay.portal.kernel.util.PropsKeys;
038    import com.liferay.portal.kernel.util.StringPool;
039    import com.liferay.portal.kernel.util.Validator;
040    import com.liferay.portal.kernel.workflow.WorkflowConstants;
041    import com.liferay.portal.model.Company;
042    import com.liferay.portal.model.Group;
043    import com.liferay.portal.model.GroupConstants;
044    import com.liferay.portal.model.LayoutSet;
045    import com.liferay.portal.model.ListTypeConstants;
046    import com.liferay.portal.model.Organization;
047    import com.liferay.portal.model.OrganizationConstants;
048    import com.liferay.portal.model.ResourceConstants;
049    import com.liferay.portal.model.Role;
050    import com.liferay.portal.model.RoleConstants;
051    import com.liferay.portal.model.User;
052    import com.liferay.portal.model.UserGroupRole;
053    import com.liferay.portal.model.impl.OrganizationImpl;
054    import com.liferay.portal.security.permission.PermissionCacheUtil;
055    import com.liferay.portal.service.ServiceContext;
056    import com.liferay.portal.service.base.OrganizationLocalServiceBaseImpl;
057    import com.liferay.portal.util.PropsUtil;
058    import com.liferay.portal.util.PropsValues;
059    import com.liferay.portal.util.comparator.OrganizationNameComparator;
060    
061    import java.io.Serializable;
062    
063    import java.util.ArrayList;
064    import java.util.Collections;
065    import java.util.HashMap;
066    import java.util.HashSet;
067    import java.util.Iterator;
068    import java.util.LinkedHashMap;
069    import java.util.List;
070    import java.util.Map;
071    import java.util.Set;
072    
073    /**
074     * The implementation of the organization local service.
075     *
076     * @author Brian Wing Shun Chan
077     * @author Jorge Ferrer
078     * @author Julio Camarero
079     * @author Hugo Huijser
080     * @author Juan Fernández
081     */
082    public class OrganizationLocalServiceImpl
083            extends OrganizationLocalServiceBaseImpl {
084    
085            /**
086             * Adds the organizations to the group.
087             *
088             * @param  groupId the primary key of the group
089             * @param  organizationIds the primary keys of the organizations
090             * @throws PortalException if a group or organization with the primary key
091             *         could not be found
092             * @throws SystemException if a system exception occurred
093             */
094            public void addGroupOrganizations(long groupId, long[] organizationIds)
095                    throws PortalException, SystemException {
096    
097                    groupPersistence.addOrganizations(groupId, organizationIds);
098    
099                    PermissionCacheUtil.clearCache();
100            }
101    
102            /**
103             * Adds an organization.
104             *
105             * <p>
106             * This method handles the creation and bookkeeping of the organization
107             * including its resources, metadata, and internal data structures. It is
108             * not necessary to make a subsequent call to {@link
109             * #addOrganizationResources(long, Organization)}.
110             * </p>
111             *
112             * @param  userId the primary key of the creator/owner of the organization
113             * @param  parentOrganizationId the primary key of the organization's parent
114             *         organization
115             * @param  name the organization's name
116             * @param  type the organization's type
117             * @param  recursable whether the permissions of the organization are to be
118             *         inherited by its sub-organizations
119             * @param  regionId the primary key of the organization's region
120             * @param  countryId the primary key of the organization's country
121             * @param  statusId the organization's workflow status
122             * @param  comments the comments about the organization
123             * @param  site whether the organization is to be associated with a main
124             *         site
125             * @param  serviceContext the organization's service context (optionally
126             *         <code>null</code>). Can set asset category IDs, asset tag names,
127             *         and expando bridge attributes for the organization.
128             * @return the organization
129             * @throws PortalException if a creator or parent organization with the
130             *         primary key could not be found or if the organization's
131             *         information was invalid
132             * @throws SystemException if a system exception occurred
133             */
134            public Organization addOrganization(
135                            long userId, long parentOrganizationId, String name, String type,
136                            boolean recursable, long regionId, long countryId, int statusId,
137                            String comments, boolean site, ServiceContext serviceContext)
138                    throws PortalException, SystemException {
139    
140                    // Organization
141    
142                    User user = userPersistence.findByPrimaryKey(userId);
143                    parentOrganizationId = getParentOrganizationId(
144                            user.getCompanyId(), parentOrganizationId);
145                    recursable = true;
146    
147                    validate(
148                            user.getCompanyId(), parentOrganizationId, name, type, countryId,
149                            statusId);
150    
151                    long organizationId = counterLocalService.increment();
152    
153                    Organization organization = organizationPersistence.create(
154                            organizationId);
155    
156                    organization.setCompanyId(user.getCompanyId());
157                    organization.setParentOrganizationId(parentOrganizationId);
158    
159                    String treePath = organization.buildTreePath();
160    
161                    organization.setTreePath(treePath);
162    
163                    organization.setName(name);
164                    organization.setType(type);
165                    organization.setRecursable(recursable);
166                    organization.setRegionId(regionId);
167                    organization.setCountryId(countryId);
168                    organization.setStatusId(statusId);
169                    organization.setComments(comments);
170                    organization.setExpandoBridgeAttributes(serviceContext);
171    
172                    organizationPersistence.update(organization);
173    
174                    // Group
175    
176                    long parentGroupId = GroupConstants.DEFAULT_PARENT_GROUP_ID;
177    
178                    if (parentOrganizationId !=
179                                    OrganizationConstants.DEFAULT_PARENT_ORGANIZATION_ID) {
180    
181                            Organization parentOrganization =
182                                    organizationPersistence.fetchByPrimaryKey(parentOrganizationId);
183    
184                            if (parentOrganization != null) {
185                                    parentGroupId = parentOrganization.getGroupId();
186                            }
187                    }
188    
189                    Group group = groupLocalService.addGroup(
190                            userId, parentGroupId, Organization.class.getName(), organizationId,
191                            GroupConstants.DEFAULT_LIVE_GROUP_ID, name, null,
192                            GroupConstants.TYPE_SITE_PRIVATE, null, site, true, null);
193    
194                    // Role
195    
196                    Role role = roleLocalService.getRole(
197                            organization.getCompanyId(), RoleConstants.ORGANIZATION_OWNER);
198    
199                    userGroupRoleLocalService.addUserGroupRoles(
200                            userId, group.getGroupId(), new long[] {role.getRoleId()});
201    
202                    // Resources
203    
204                    addOrganizationResources(userId, organization);
205    
206                    // Asset
207    
208                    if (serviceContext != null) {
209                            updateAsset(
210                                    userId, organization, serviceContext.getAssetCategoryIds(),
211                                    serviceContext.getAssetTagNames());
212                    }
213    
214                    // Indexer
215    
216                    if ((serviceContext == null) || serviceContext.isIndexingEnabled()) {
217                            Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
218                                    Organization.class);
219    
220                            indexer.reindex(organization);
221                    }
222    
223                    return organization;
224            }
225    
226            /**
227             * Adds a resource for each type of permission available on the
228             * organization.
229             *
230             * @param  userId the primary key of the creator/owner of the organization
231             * @param  organization the organization
232             * @throws PortalException if a portal exception occurred
233             * @throws SystemException if a system exception occurred
234             */
235            public void addOrganizationResources(long userId, Organization organization)
236                    throws PortalException, SystemException {
237    
238                    String name = Organization.class.getName();
239    
240                    resourceLocalService.addResources(
241                            organization.getCompanyId(), 0, userId, name,
242                            organization.getOrganizationId(), false, false, false);
243            }
244    
245            /**
246             * Assigns the password policy to the organizations, removing any other
247             * currently assigned password policies.
248             *
249             * @param  passwordPolicyId the primary key of the password policy
250             * @param  organizationIds the primary keys of the organizations
251             * @throws SystemException if a system exception occurred
252             */
253            public void addPasswordPolicyOrganizations(
254                            long passwordPolicyId, long[] organizationIds)
255                    throws SystemException {
256    
257                    passwordPolicyRelLocalService.addPasswordPolicyRels(
258                            passwordPolicyId, Organization.class.getName(), organizationIds);
259            }
260    
261            /**
262             * Deletes the logo of the organization.
263             *
264             * @param  organizationId the primary key of the organization
265             * @throws PortalException if an organization or parent organization with
266             *         the primary key could not be found or if the organization's logo
267             *         could not be found
268             * @throws SystemException if a system exception occurred
269             */
270            public void deleteLogo(long organizationId)
271                    throws PortalException, SystemException {
272    
273                    Organization organization = getOrganization(organizationId);
274    
275                    Group group = organization.getGroup();
276    
277                    LayoutSet publicLayoutSet = layoutSetLocalService.getLayoutSet(
278                            group.getGroupId(), false);
279    
280                    if (publicLayoutSet.isLogo()) {
281                            long logoId = publicLayoutSet.getLogoId();
282    
283                            publicLayoutSet.setLogo(false);
284                            publicLayoutSet.setLogoId(0);
285    
286                            layoutSetPersistence.update(publicLayoutSet);
287    
288                            imageLocalService.deleteImage(logoId);
289                    }
290    
291                    LayoutSet privateLayoutSet = layoutSetLocalService.getLayoutSet(
292                            group.getGroupId(), true);
293    
294                    if (privateLayoutSet.isLogo()) {
295                            long logoId = privateLayoutSet.getLogoId();
296    
297                            privateLayoutSet.setLogo(false);
298                            privateLayoutSet.setLogoId(0);
299    
300                            layoutSetPersistence.update(privateLayoutSet);
301    
302                            if (imageLocalService.getImage(logoId) != null) {
303                                    imageLocalService.deleteImage(logoId);
304                            }
305                    }
306            }
307    
308            /**
309             * Deletes the organization. The organization's associated resources and
310             * assets are also deleted.
311             *
312             * @param  organizationId the primary key of the organization
313             * @return the deleted organization
314             * @throws PortalException if an organization with the primary key could not
315             *         be found, if the organization had a workflow in approved status,
316             *         or if the organization was a parent organization
317             * @throws SystemException if a system exception occurred
318             */
319            @Override
320            public Organization deleteOrganization(long organizationId)
321                    throws PortalException, SystemException {
322    
323                    Organization organization = organizationPersistence.findByPrimaryKey(
324                            organizationId);
325    
326                    return deleteOrganization(organization);
327            }
328    
329            /**
330             * Deletes the organization. The organization's associated resources and
331             * assets are also deleted.
332             *
333             * @param  organization the organization
334             * @return the deleted organization
335             * @throws PortalException if the organization had a workflow in approved
336             *         status or if the organization was a parent organization
337             * @throws SystemException if a system exception occurred
338             */
339            @Override
340            public Organization deleteOrganization(Organization organization)
341                    throws PortalException, SystemException {
342    
343                    if ((userLocalService.getOrganizationUsersCount(
344                                    organization.getOrganizationId(),
345                                    WorkflowConstants.STATUS_APPROVED) > 0) ||
346                            (organizationPersistence.countByC_P(
347                                    organization.getCompanyId(),
348                                    organization.getOrganizationId()) > 0)) {
349    
350                            throw new RequiredOrganizationException();
351                    }
352    
353                    // Asset
354    
355                    assetEntryLocalService.deleteEntry(
356                            Organization.class.getName(), organization.getOrganizationId());
357    
358                    // Addresses
359    
360                    addressLocalService.deleteAddresses(
361                            organization.getCompanyId(), Organization.class.getName(),
362                            organization.getOrganizationId());
363    
364                    // Email addresses
365    
366                    emailAddressLocalService.deleteEmailAddresses(
367                            organization.getCompanyId(), Organization.class.getName(),
368                            organization.getOrganizationId());
369    
370                    // Expando
371    
372                    expandoValueLocalService.deleteValues(
373                            Organization.class.getName(), organization.getOrganizationId());
374    
375                    // Password policy relation
376    
377                    passwordPolicyRelLocalService.deletePasswordPolicyRel(
378                            Organization.class.getName(), organization.getOrganizationId());
379    
380                    // Phone
381    
382                    phoneLocalService.deletePhones(
383                            organization.getCompanyId(), Organization.class.getName(),
384                            organization.getOrganizationId());
385    
386                    // Website
387    
388                    websiteLocalService.deleteWebsites(
389                            organization.getCompanyId(), Organization.class.getName(),
390                            organization.getOrganizationId());
391    
392                    // Group
393    
394                    Group group = organization.getGroup();
395    
396                    if (group.isSite()) {
397                            group.setSite(false);
398    
399                            groupPersistence.update(group);
400                    }
401    
402                    groupLocalService.deleteGroup(group);
403    
404                    // Resources
405    
406                    String name = Organization.class.getName();
407    
408                    resourceLocalService.deleteResource(
409                            organization.getCompanyId(), name,
410                            ResourceConstants.SCOPE_INDIVIDUAL,
411                            organization.getOrganizationId());
412    
413                    // Organization
414    
415                    organizationPersistence.remove(organization);
416    
417                    // Permission cache
418    
419                    PermissionCacheUtil.clearCache();
420    
421                    return organization;
422            }
423    
424            /**
425             * Returns all the organizations belonging to the group.
426             *
427             * @param  groupId the primary key of the group
428             * @return the organizations belonging to the group
429             * @throws SystemException if a system exception occurred
430             */
431            public List<Organization> getGroupOrganizations(long groupId)
432                    throws SystemException {
433    
434                    return groupPersistence.getOrganizations(groupId);
435            }
436    
437            /**
438             * Returns the organization with the name.
439             *
440             * @param  companyId the primary key of the organization's company
441             * @param  name the organization's name
442             * @return the organization with the name
443             * @throws PortalException if the organization with the name could not be
444             *         found
445             * @throws SystemException if a system exception occurred
446             */
447            public Organization getOrganization(long companyId, String name)
448                    throws PortalException, SystemException {
449    
450                    return organizationPersistence.findByC_N(companyId, name);
451            }
452    
453            /**
454             * Returns the primary key of the organization with the name.
455             *
456             * @param  companyId the primary key of the organization's company
457             * @param  name the organization's name
458             * @return the primary key of the organization with the name, or
459             *         <code>0</code> if the organization could not be found
460             * @throws SystemException if a system exception occurred
461             */
462            public long getOrganizationId(long companyId, String name)
463                    throws SystemException {
464    
465                    Organization organization = organizationPersistence.fetchByC_N(
466                            companyId, name);
467    
468                    if (organization != null) {
469                            return organization.getOrganizationId();
470                    }
471                    else {
472                            return 0;
473                    }
474            }
475    
476            public List<Organization> getOrganizations(
477                            long userId, int start, int end, OrderByComparator obc)
478                    throws PortalException, SystemException {
479    
480                    User user = userPersistence.findByPrimaryKey(userId);
481    
482                    List<Organization> organizations = ListUtil.copy(
483                            userPersistence.getOrganizations(userId));
484    
485                    Iterator<Organization> iterator = organizations.iterator();
486    
487                    while (iterator.hasNext()) {
488                            Organization organization = iterator.next();
489    
490                            if ((organization.getCompanyId() != user.getCompanyId()) ||
491                                    (organization.getParentOrganization() == null)) {
492    
493                                    iterator.remove();
494                            }
495                    }
496    
497                    if (organizations.isEmpty()) {
498                            return organizations;
499                    }
500    
501                    if (obc == null) {
502                            obc = new OrganizationNameComparator(true);
503                    }
504    
505                    Collections.sort(organizations, obc);
506    
507                    if ((start != QueryUtil.ALL_POS) || (end != QueryUtil.ALL_POS)) {
508                            organizations = ListUtil.subList(organizations, start, end);
509                    }
510    
511                    return organizations;
512            }
513    
514            /**
515             * Returns all the organizations belonging to the parent organization.
516             *
517             * @param  companyId the primary key of the organization's company
518             * @param  parentOrganizationId the primary key of the organization's parent
519             *         organization
520             * @return the organizations belonging to the parent organization
521             * @throws SystemException if a system exception occurred
522             */
523            public List<Organization> getOrganizations(
524                            long companyId, long parentOrganizationId)
525                    throws SystemException {
526    
527                    return getOrganizations(
528                            companyId, parentOrganizationId, QueryUtil.ALL_POS,
529                            QueryUtil.ALL_POS);
530            }
531    
532            /**
533             * Returns a range of all the organizations belonging to the parent
534             * organization.
535             *
536             * <p>
537             * Useful when paginating results. Returns a maximum of <code>end -
538             * start</code> instances. <code>start</code> and <code>end</code> are not
539             * primary keys, they are indexes in the result set. Thus, <code>0</code>
540             * refers to the first result in the set. Setting both <code>start</code>
541             * and <code>end</code> to {@link
542             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
543             * result set.
544             * </p>
545             *
546             * @param  companyId the primary key of the organization's company
547             * @param  parentOrganizationId the primary key of the organization's parent
548             *         organization
549             * @param  start the lower bound of the range of organizations to return
550             * @param  end the upper bound of the range of organizations to return (not
551             *         inclusive)
552             * @return the range of organizations belonging to the parent organization
553             * @throws SystemException if a system exception occurred
554             * @see    com.liferay.portal.service.persistence.OrganizationPersistence#findByC_P(
555             *         long, long, int, int)
556             */
557            public List<Organization> getOrganizations(
558                            long companyId, long parentOrganizationId, int start, int end)
559                    throws SystemException {
560    
561                    if (parentOrganizationId ==
562                                    OrganizationConstants.ANY_PARENT_ORGANIZATION_ID) {
563    
564                            return organizationPersistence.findByCompanyId(
565                                    companyId, start, end);
566                    }
567                    else {
568                            return organizationPersistence.findByC_P(
569                                    companyId, parentOrganizationId, start, end);
570                    }
571            }
572    
573            /**
574             * Returns the organizations with the primary keys.
575             *
576             * @param  organizationIds the primary keys of the organizations
577             * @return the organizations with the primary keys
578             * @throws PortalException if any one of the organizations could not be
579             *         found
580             * @throws SystemException if a system exception occurred
581             */
582            public List<Organization> getOrganizations(long[] organizationIds)
583                    throws PortalException, SystemException {
584    
585                    List<Organization> organizations = new ArrayList<Organization>(
586                            organizationIds.length);
587    
588                    for (long organizationId : organizationIds) {
589                            Organization organization = getOrganization(organizationId);
590    
591                            organizations.add(organization);
592                    }
593    
594                    return organizations;
595            }
596    
597            /**
598             * Returns the number of organizations belonging to the parent organization.
599             *
600             * @param  companyId the primary key of the organization's company
601             * @param  parentOrganizationId the primary key of the organization's parent
602             *         organization
603             * @return the number of organizations belonging to the parent organization
604             * @throws SystemException if a system exception occurred
605             */
606            public int getOrganizationsCount(long companyId, long parentOrganizationId)
607                    throws SystemException {
608    
609                    if (parentOrganizationId ==
610                                    OrganizationConstants.ANY_PARENT_ORGANIZATION_ID) {
611    
612                            return organizationPersistence.countByCompanyId(companyId);
613                    }
614                    else {
615                            return organizationPersistence.countByC_P(
616                                    companyId, parentOrganizationId);
617                    }
618            }
619    
620            /**
621             * Returns the parent organizations in order by closest ancestor. The list
622             * starts with the organization itself.
623             *
624             * @param  organizationId the primary key of the organization
625             * @return the parent organizations in order by closest ancestor
626             * @throws PortalException if an organization with the primary key could not
627             *         be found
628             * @throws SystemException if a system exception occurred
629             */
630            public List<Organization> getParentOrganizations(long organizationId)
631                    throws PortalException, SystemException {
632    
633                    if (organizationId ==
634                                    OrganizationConstants.DEFAULT_PARENT_ORGANIZATION_ID) {
635    
636                            return new ArrayList<Organization>();
637                    }
638    
639                    Organization organization = organizationPersistence.findByPrimaryKey(
640                            organizationId);
641    
642                    return getParentOrganizations(organization, true);
643            }
644    
645            /**
646             * Returns the sub-organizations of the organizations.
647             *
648             * @param  organizations the organizations from which to get
649             *         sub-organizations
650             * @return the sub-organizations of the organizations
651             * @throws SystemException if a system exception occurred
652             */
653            public List<Organization> getSuborganizations(
654                            List<Organization> organizations)
655                    throws SystemException {
656    
657                    List<Organization> allSuborganizations = new ArrayList<Organization>();
658    
659                    for (int i = 0; i < organizations.size(); i++) {
660                            Organization organization = organizations.get(i);
661    
662                            List<Organization> suborganizations =
663                                    organizationPersistence.findByC_P(
664                                            organization.getCompanyId(),
665                                            organization.getOrganizationId());
666    
667                            addSuborganizations(allSuborganizations, suborganizations);
668                    }
669    
670                    return allSuborganizations;
671            }
672    
673            /**
674             * Returns the intersection of <code>allOrganizations</code> and
675             * <code>availableOrganizations</code>.
676             *
677             * @param  allOrganizations the organizations to check for availability
678             * @param  availableOrganizations the available organizations
679             * @return the intersection of <code>allOrganizations</code> and
680             *         <code>availableOrganizations</code>
681             */
682            public List<Organization> getSubsetOrganizations(
683                    List<Organization> allOrganizations,
684                    List<Organization> availableOrganizations) {
685    
686                    List<Organization> subsetOrganizations = new ArrayList<Organization>();
687    
688                    for (Organization organization : allOrganizations) {
689                            if (availableOrganizations.contains(organization)) {
690                                    subsetOrganizations.add(organization);
691                            }
692                    }
693    
694                    return subsetOrganizations;
695            }
696    
697            /**
698             * Returns all the organizations associated with the user.
699             *
700             * @param  userId the primary key of the user
701             * @return the organizations associated with the user
702             * @throws PortalException if a user with the primary key could not be found
703             * @throws SystemException if a system exception occurred
704             */
705            public List<Organization> getUserOrganizations(long userId)
706                    throws PortalException, SystemException {
707    
708                    return getUserOrganizations(
709                            userId, QueryUtil.ALL_POS, QueryUtil.ALL_POS);
710            }
711    
712            /**
713             * Returns all the organizations associated with the user. If
714             * includeAdministrative is <code>true</code>, the result includes those
715             * organizations that are not directly associated to the user but he is an
716             * administrator or an owner of the organization.
717             *
718             * @param  userId the primary key of the user
719             * @param  includeAdministrative whether to includes organizations that are
720             *         indirectly associated to the user because he is an administrator
721             *         or an owner of the organization
722             * @return the organizations associated with the user
723             * @throws PortalException if a user with the primary key could not be found
724             * @throws SystemException if a system exception occurred
725             */
726            public List<Organization> getUserOrganizations(
727                            long userId, boolean includeAdministrative)
728                    throws PortalException, SystemException {
729    
730                    if (!includeAdministrative) {
731                            return getUserOrganizations(userId);
732                    }
733    
734                    Set<Organization> organizations = new HashSet<Organization>();
735    
736                    List<UserGroupRole> userGroupRoles =
737                            userGroupRoleLocalService.getUserGroupRoles(userId);
738    
739                    for (UserGroupRole userGroupRole : userGroupRoles) {
740                            Role role = userGroupRole.getRole();
741    
742                            String roleName = role.getName();
743    
744                            if (roleName.equals(RoleConstants.ORGANIZATION_ADMINISTRATOR) ||
745                                    roleName.equals(RoleConstants.ORGANIZATION_OWNER)) {
746    
747                                    Group group = userGroupRole.getGroup();
748    
749                                    Organization organization =
750                                            organizationPersistence.findByPrimaryKey(
751                                                    group.getOrganizationId());
752    
753                                    organizations.add(organization);
754                            }
755                    }
756    
757                    organizations.addAll(getUserOrganizations(userId));
758    
759                    return new ArrayList<Organization>(organizations);
760            }
761    
762            /**
763             * Returns a range of all the organizations associated with the user.
764             *
765             * <p>
766             * Useful when paginating results. Returns a maximum of <code>end -
767             * start</code> instances. <code>start</code> and <code>end</code> are not
768             * primary keys, they are indexes in the result set. Thus, <code>0</code>
769             * refers to the first result in the set. Setting both <code>start</code>
770             * and <code>end</code> to {@link
771             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
772             * result set.
773             * </p>
774             *
775             * @param  userId the primary key of the user
776             * @param  start the lower bound of the range of organizations to return
777             * @param  end the upper bound of the range of organizations to return (not
778             *         inclusive)
779             * @return the range organizations associated with the user
780             * @throws PortalException if a user with the primary key could not be found
781             * @throws SystemException if a system exception occurred
782             */
783            public List<Organization> getUserOrganizations(
784                            long userId, int start, int end)
785                    throws PortalException, SystemException {
786    
787                    return userPersistence.getOrganizations(userId, start, end);
788            }
789    
790            /**
791             * Returns the number of organizations associated with the user.
792             *
793             * @param  userId the primary key of the user
794             * @return the number of organizations associated with the user
795             * @throws SystemException if a system exception occurred
796             */
797            @ThreadLocalCachable
798            public int getUserOrganizationsCount(long userId) throws SystemException {
799                    return userPersistence.getOrganizationsSize(userId);
800            }
801    
802            /**
803             * Returns <code>true</code> if the organization belongs to the group.
804             *
805             * @param  groupId the primary key of the group
806             * @param  organizationId the primary key of the organization
807             * @return <code>true</code> if the organization belongs to the group;
808             *         <code>false</code> otherwise
809             * @throws SystemException if a system exception occurred
810             */
811            public boolean hasGroupOrganization(long groupId, long organizationId)
812                    throws SystemException {
813    
814                    return groupPersistence.containsOrganization(groupId, organizationId);
815            }
816    
817            /**
818             * Returns <code>true</code> if the password policy has been assigned to the
819             * organization.
820             *
821             * @param  passwordPolicyId the primary key of the password policy
822             * @param  organizationId the primary key of the organization
823             * @return <code>true</code> if the password policy has been assigned to the
824             *         organization; <code>false</code> otherwise
825             * @throws SystemException if a system exception occurred
826             */
827            public boolean hasPasswordPolicyOrganization(
828                            long passwordPolicyId, long organizationId)
829                    throws SystemException {
830    
831                    return passwordPolicyRelLocalService.hasPasswordPolicyRel(
832                            passwordPolicyId, Organization.class.getName(), organizationId);
833            }
834    
835            /**
836             * Returns <code>true</code> if the user is a member of the organization.
837             * This method is usually called to determine if the user has view access to
838             * a resource belonging to the organization.
839             *
840             * @param  userId the primary key of the user
841             * @param  organizationId the primary key of the organization
842             * @return <code>true</code> if the user has access to the organization;
843             *         <code>false</code> otherwise
844             * @throws SystemException if a system exception occurred
845             */
846            public boolean hasUserOrganization(long userId, long organizationId)
847                    throws SystemException {
848    
849                    return userPersistence.containsOrganization(userId, organizationId);
850            }
851    
852            /**
853             * Returns <code>true</code> if the user is a member of the organization,
854             * optionally focusing on sub-organizations or the specified organization.
855             * This method is usually called to determine if the user has view access to
856             * a resource belonging to the organization.
857             *
858             * <p>
859             *
860             * <ol>
861             * <li>
862             * If <code>inheritSuborganizations=<code>false</code></code>:
863             * the method checks whether the user belongs to the organization specified
864             * by <code>organizationId</code>. The parameter
865             * <code>includeSpecifiedOrganization</code> is ignored.
866             * </li>
867             * <li>
868             * The parameter <code>includeSpecifiedOrganization</code> is
869             * ignored unless <code>inheritSuborganizations</code> is also
870             * <code>true</code>.
871             * </li>
872             * <li>
873             * If <code>inheritSuborganizations=<code>true</code></code> and
874             * <code>includeSpecifiedOrganization=<code>false</code></code>: the method
875             * checks
876             * whether the user belongs to one of the child organizations of the one
877             * specified by <code>organizationId</code>.
878             * </li>
879             * <li>
880             * If <code>inheritSuborganizations=<code>true</code></code> and
881             * <code>includeSpecifiedOrganization=<code>true</code></code>: the method
882             * checks whether
883             * the user belongs to the organization specified by
884             * <code>organizationId</code> or any of
885             * its child organizations.
886             * </li>
887             * </ol>
888             *
889             * <p>
890             *
891             * @param  userId the primary key of the organization's user
892             * @param  organizationId the primary key of the organization
893             * @param  inheritSuborganizations if <code>true</code> sub-organizations
894             *         are considered in the determination
895             * @param  includeSpecifiedOrganization if <code>true</code> the
896             *         organization specified by <code>organizationId</code> is
897             *         considered in the determination
898             * @return <code>true</code> if the user has access to the organization;
899             *         <code>false</code> otherwise
900             * @throws PortalException if an organization with the primary key could not
901             *         be found
902             * @throws SystemException if a system exception occurred
903             * @see    com.liferay.portal.service.persistence.OrganizationFinder
904             */
905            public boolean hasUserOrganization(
906                            long userId, long organizationId, boolean inheritSuborganizations,
907                            boolean includeSpecifiedOrganization)
908                    throws PortalException, SystemException {
909    
910                    if (!inheritSuborganizations) {
911                            return userPersistence.containsOrganization(userId, organizationId);
912                    }
913    
914                    LinkedHashMap<String, Object> params =
915                            new LinkedHashMap<String, Object>();
916    
917                    List<Organization> organizationsTree = new ArrayList<Organization>();
918    
919                    Organization organization = organizationPersistence.findByPrimaryKey(
920                            organizationId);
921    
922                    if (!includeSpecifiedOrganization) {
923                            organizationsTree.add(organization);
924                    }
925                    else {
926                            organizationsTree.add(organization.getParentOrganization());
927                    }
928    
929                    params.put("usersOrgsTree", organizationsTree);
930    
931                    if (userFinder.countByUser(userId, params) > 0) {
932                            return true;
933                    }
934    
935                    return false;
936            }
937    
938            /**
939             * Rebuilds the organizations tree.
940             *
941             * <p>
942             * Only call this method if the tree has become stale through operations
943             * other than normal CRUD. Under normal circumstances the tree is
944             * automatically rebuilt whenever necessary.
945             * </p>
946             *
947             * @param  companyId the primary key of the organization's company
948             * @throws PortalException if an organization with the primary key could not
949             *         be found
950             * @throws SystemException if a system exception occurred
951             */
952            public void rebuildTree(long companyId)
953                    throws PortalException, SystemException {
954    
955                    List<Organization> organizations =
956                            organizationPersistence.findByCompanyId(companyId);
957    
958                    for (Organization organization : organizations) {
959                            String treePath = organization.buildTreePath();
960    
961                            organization.setTreePath(treePath);
962    
963                            organizationPersistence.update(organization);
964                    }
965            }
966    
967            /**
968             * Returns a range of all the organizations of the company.
969             *
970             * <p>
971             * Useful when paginating results. Returns a maximum of <code>end -
972             * start</code> instances. <code>start</code> and <code>end</code> are not
973             * primary keys, they are indexes in the result set. Thus, <code>0</code>
974             * refers to the first result in the set. Setting both <code>start</code>
975             * and <code>end</code> to {@link
976             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
977             * result set.
978             * </p>
979             *
980             * @param  companyId the primary key of the company
981             * @param  params the finder parameters (optionally <code>null</code>). For
982             *         more information see {@link
983             *         com.liferay.portlet.usersadmin.util.OrganizationIndexer}
984             * @param  start the lower bound of the range of organizations to return
985             * @param  end the upper bound of the range of organizations to return (not
986             *         inclusive)
987             * @return the range of all the organizations of the company
988             * @throws SystemException if a system exception occurred
989             */
990            public List<Organization> search(
991                            long companyId, LinkedHashMap<String, Object> params, int start,
992                            int end)
993                    throws SystemException {
994    
995                    return organizationFinder.findByCompanyId(
996                            companyId, params, start, end,
997                            new OrganizationNameComparator(true));
998            }
999    
1000            /**
1001             * Returns an ordered range of all the organizations that match the
1002             * keywords, using the indexer. It is preferable to use this method instead
1003             * of the non-indexed version whenever possible for performance reasons.
1004             *
1005             * <p>
1006             * Useful when paginating results. Returns a maximum of <code>end -
1007             * start</code> instances. <code>start</code> and <code>end</code> are not
1008             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1009             * refers to the first result in the set. Setting both <code>start</code>
1010             * and <code>end</code> to {@link
1011             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1012             * result set.
1013             * </p>
1014             *
1015             * @param  companyId the primary key of the organization's company
1016             * @param  parentOrganizationId the primary key of the organization's parent
1017             *         organization
1018             * @param  keywords the keywords (space separated), which may occur in the
1019             *         organization's name, street, city, zipcode, type, region or
1020             *         country (optionally <code>null</code>)
1021             * @param  params the finder parameters (optionally <code>null</code>). For
1022             *         more information see {@link
1023             *         com.liferay.portlet.usersadmin.util.OrganizationIndexer}
1024             * @param  start the lower bound of the range of organizations to return
1025             * @param  end the upper bound of the range of organizations to return (not
1026             *         inclusive)
1027             * @param  sort the field and direction by which to sort (optionally
1028             *         <code>null</code>)
1029             * @return the matching organizations ordered by name
1030             * @throws SystemException if a system exception occurred
1031             * @see    com.liferay.portlet.usersadmin.util.OrganizationIndexer
1032             */
1033            public Hits search(
1034                            long companyId, long parentOrganizationId, String keywords,
1035                            LinkedHashMap<String, Object> params, int start, int end, Sort sort)
1036                    throws SystemException {
1037    
1038                    String name = null;
1039                    String type = null;
1040                    String street = null;
1041                    String city = null;
1042                    String zip = null;
1043                    String region = null;
1044                    String country = null;
1045                    boolean andOperator = false;
1046    
1047                    if (Validator.isNotNull(keywords)) {
1048                            name = keywords;
1049                            type = keywords;
1050                            street = keywords;
1051                            city = keywords;
1052                            zip = keywords;
1053                            region = keywords;
1054                            country = keywords;
1055                    }
1056                    else {
1057                            andOperator = true;
1058                    }
1059    
1060                    if (params != null) {
1061                            params.put("keywords", keywords);
1062                    }
1063    
1064                    return search(
1065                            companyId, parentOrganizationId, name, type, street, city, zip,
1066                            region, country, params, andOperator, start, end, sort);
1067            }
1068    
1069            /**
1070             * Returns a name ordered range of all the organizations that match the
1071             * keywords, type, region, and country, without using the indexer. It is
1072             * preferable to use the indexed version {@link #search(long, long, String,
1073             * LinkedHashMap, int, int, Sort)} instead of this method wherever possible
1074             * for performance reasons.
1075             *
1076             * <p>
1077             * Useful when paginating results. Returns a maximum of <code>end -
1078             * start</code> instances. <code>start</code> and <code>end</code> are not
1079             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1080             * refers to the first result in the set. Setting both <code>start</code>
1081             * and <code>end</code> to {@link
1082             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1083             * result set.
1084             * </p>
1085             *
1086             * @param  companyId the primary key of the organization's company
1087             * @param  parentOrganizationId the primary key of the organization's parent
1088             *         organization
1089             * @param  keywords the keywords (space separated), which may occur in the
1090             *         organization's name, street, city, or zipcode (optionally
1091             *         <code>null</code>)
1092             * @param  type the organization's type (optionally <code>null</code>)
1093             * @param  regionId the primary key of the organization's region (optionally
1094             *         <code>null</code>)
1095             * @param  countryId the primary key of the organization's country
1096             *         (optionally <code>null</code>)
1097             * @param  params the finder params. For more information see {@link
1098             *         com.liferay.portal.service.persistence.OrganizationFinder}
1099             * @param  start the lower bound of the range of organizations to return
1100             * @param  end the upper bound of the range of organizations to return (not
1101             *         inclusive)
1102             * @return the matching organizations ordered by name
1103             * @throws SystemException if a system exception occurred
1104             * @see    com.liferay.portal.service.persistence.OrganizationFinder
1105             */
1106            public List<Organization> search(
1107                            long companyId, long parentOrganizationId, String keywords,
1108                            String type, Long regionId, Long countryId,
1109                            LinkedHashMap<String, Object> params, int start, int end)
1110                    throws SystemException {
1111    
1112                    return search(
1113                            companyId, parentOrganizationId, keywords, type, regionId,
1114                            countryId, params, start, end,
1115                            new OrganizationNameComparator(true));
1116            }
1117    
1118            /**
1119             * Returns an ordered range of all the organizations that match the
1120             * keywords, type, region, and country, without using the indexer. It is
1121             * preferable to use the indexed version {@link #search(long, long, String,
1122             * String, String, String, String, String, String, LinkedHashMap, boolean,
1123             * int, int, Sort)} instead of this method wherever possible for performance
1124             * reasons.
1125             *
1126             * <p>
1127             * Useful when paginating results. Returns a maximum of <code>end -
1128             * start</code> instances. <code>start</code> and <code>end</code> are not
1129             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1130             * refers to the first result in the set. Setting both <code>start</code>
1131             * and <code>end</code> to {@link
1132             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1133             * result set.
1134             * </p>
1135             *
1136             * @param  companyId the primary key of the organization's company
1137             * @param  parentOrganizationId the primary key of the organization's parent
1138             *         organization
1139             * @param  keywords the keywords (space separated), which may occur in the
1140             *         organization's name, street, city, or zipcode (optionally
1141             *         <code>null</code>)
1142             * @param  type the organization's type (optionally <code>null</code>)
1143             * @param  regionId the primary key of the organization's region (optionally
1144             *         <code>null</code>)
1145             * @param  countryId the primary key of the organization's country
1146             *         (optionally <code>null</code>)
1147             * @param  params the finder params. For more information see {@link
1148             *         com.liferay.portal.service.persistence.OrganizationFinder}
1149             * @param  start the lower bound of the range of organizations to return
1150             * @param  end the upper bound of the range of organizations to return (not
1151             *         inclusive)
1152             * @param  obc the comparator to order the organizations (optionally
1153             *         <code>null</code>)
1154             * @return the matching organizations ordered by comparator <code>obc</code>
1155             * @throws SystemException if a system exception occurred
1156             * @see    com.liferay.portal.service.persistence.OrganizationFinder
1157             */
1158            public List<Organization> search(
1159                            long companyId, long parentOrganizationId, String keywords,
1160                            String type, Long regionId, Long countryId,
1161                            LinkedHashMap<String, Object> params, int start, int end,
1162                            OrderByComparator obc)
1163                    throws SystemException {
1164    
1165                    String parentOrganizationIdComparator = StringPool.EQUAL;
1166    
1167                    if (parentOrganizationId ==
1168                                    OrganizationConstants.ANY_PARENT_ORGANIZATION_ID) {
1169    
1170                            parentOrganizationIdComparator = StringPool.NOT_EQUAL;
1171                    }
1172    
1173                    return organizationFinder.findByKeywords(
1174                            companyId, parentOrganizationId, parentOrganizationIdComparator,
1175                            keywords, type, regionId, countryId, params, start, end, obc);
1176            }
1177    
1178            /**
1179             * Returns a name ordered range of all the organizations with the type,
1180             * region, and country, and whose name, street, city, and zipcode match the
1181             * keywords specified for them, without using the indexer. It is preferable
1182             * to use the indexed version {@link #search(long, long, String, String,
1183             * String, String, String, String, String, LinkedHashMap, boolean, int, int,
1184             * Sort)} instead of this method wherever possible for performance reasons.
1185             *
1186             * <p>
1187             * Useful when paginating results. Returns a maximum of <code>end -
1188             * start</code> instances. <code>start</code> and <code>end</code> are not
1189             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1190             * refers to the first result in the set. Setting both <code>start</code>
1191             * and <code>end</code> to {@link
1192             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1193             * result set.
1194             * </p>
1195             *
1196             * @param  companyId the primary key of the organization's company
1197             * @param  parentOrganizationId the primary key of the organization's parent
1198             * @param  name the name keywords (space separated, optionally
1199             *         <code>null</code>)
1200             * @param  type the organization's type (optionally <code>null</code>)
1201             * @param  street the street keywords (optionally <code>null</code>)
1202             * @param  city the city keywords (optionally <code>null</code>)
1203             * @param  zip the zipcode keywords (optionally <code>null</code>)
1204             * @param  regionId the primary key of the organization's region (optionally
1205             *         <code>null</code>)
1206             * @param  countryId the primary key of the organization's country
1207             *         (optionally <code>null</code>)
1208             * @param  params the finder parameters (optionally <code>null</code>). For
1209             *         more information see {@link
1210             *         com.liferay.portal.service.persistence.OrganizationFinder}
1211             * @param  andOperator whether every field must match its keywords, or just
1212             *         one field. For example, &quot;organizations with the name
1213             *         'Employees' and city 'Chicago'&quot; vs &quot;organizations with
1214             *         the name 'Employees' or the city 'Chicago'&quot;.
1215             * @param  start the lower bound of the range of organizations to return
1216             * @param  end the upper bound of the range of organizations to return (not
1217             *         inclusive)
1218             * @return the matching organizations ordered by name
1219             * @throws SystemException if a system exception occurred
1220             * @see    com.liferay.portal.service.persistence.OrganizationFinder
1221             */
1222            public List<Organization> search(
1223                            long companyId, long parentOrganizationId, String name, String type,
1224                            String street, String city, String zip, Long regionId,
1225                            Long countryId, LinkedHashMap<String, Object> params,
1226                            boolean andOperator, int start, int end)
1227                    throws SystemException {
1228    
1229                    return search(
1230                            companyId, parentOrganizationId, name, type, street, city, zip,
1231                            regionId, countryId, params, andOperator, start, end,
1232                            new OrganizationNameComparator(true));
1233            }
1234    
1235            /**
1236             * Returns an ordered range of all the organizations with the type, region,
1237             * and country, and whose name, street, city, and zipcode match the keywords
1238             * specified for them, without using the indexer. It is preferable to use
1239             * the indexed version {@link #search(long, long, String, String, String,
1240             * String, String, String, String, LinkedHashMap, boolean, int, int, Sort)}
1241             * instead of this method wherever possible for performance reasons.
1242             *
1243             * <p>
1244             * Useful when paginating results. Returns a maximum of <code>end -
1245             * start</code> instances. <code>start</code> and <code>end</code> are not
1246             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1247             * refers to the first result in the set. Setting both <code>start</code>
1248             * and <code>end</code> to {@link
1249             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1250             * result set.
1251             * </p>
1252             *
1253             * @param  companyId the primary key of the organization's company
1254             * @param  parentOrganizationId the primary key of the organization's parent
1255             *         organization
1256             * @param  name the name keywords (space separated, optionally
1257             *         <code>null</code>)
1258             * @param  type the organization's type (optionally <code>null</code>)
1259             * @param  street the street keywords (optionally <code>null</code>)
1260             * @param  city the city keywords (optionally <code>null</code>)
1261             * @param  zip the zipcode keywords (optionally <code>null</code>)
1262             * @param  regionId the primary key of the organization's region (optionally
1263             *         <code>null</code>)
1264             * @param  countryId the primary key of the organization's country
1265             *         (optionally <code>null</code>)
1266             * @param  params the finder parameters (optionally <code>null</code>). For
1267             *         more information see {@link
1268             *         com.liferay.portal.service.persistence.OrganizationFinder}
1269             * @param  andOperator whether every field must match its keywords, or just
1270             *         one field. For example, &quot;organizations with the name
1271             *         'Employees' and city 'Chicago'&quot; vs &quot;organizations with
1272             *         the name 'Employees' or the city 'Chicago'&quot;.
1273             * @param  start the lower bound of the range of organizations to return
1274             * @param  end the upper bound of the range of organizations to return (not
1275             *         inclusive)
1276             * @param  obc the comparator to order the organizations (optionally
1277             *         <code>null</code>)
1278             * @return the matching organizations ordered by comparator <code>obc</code>
1279             * @throws SystemException if a system exception occurred
1280             * @see    com.liferay.portal.service.persistence.OrganizationFinder
1281             */
1282            public List<Organization> search(
1283                            long companyId, long parentOrganizationId, String name, String type,
1284                            String street, String city, String zip, Long regionId,
1285                            Long countryId, LinkedHashMap<String, Object> params,
1286                            boolean andOperator, int start, int end, OrderByComparator obc)
1287                    throws SystemException {
1288    
1289                    String parentOrganizationIdComparator = StringPool.EQUAL;
1290    
1291                    if (parentOrganizationId ==
1292                                    OrganizationConstants.ANY_PARENT_ORGANIZATION_ID) {
1293    
1294                            parentOrganizationIdComparator = StringPool.NOT_EQUAL;
1295                    }
1296    
1297                    return organizationFinder.findByC_PO_N_T_S_C_Z_R_C(
1298                            companyId, parentOrganizationId, parentOrganizationIdComparator,
1299                            name, type, street, city, zip, regionId, countryId, params,
1300                            andOperator, start, end, obc);
1301            }
1302    
1303            /**
1304             * Returns an ordered range of all the organizations whose name, type, or
1305             * location fields match the keywords specified for them, using the indexer.
1306             * It is preferable to use this method instead of the non-indexed version
1307             * whenever possible for performance reasons.
1308             *
1309             * <p>
1310             * Useful when paginating results. Returns a maximum of <code>end -
1311             * start</code> instances. <code>start</code> and <code>end</code> are not
1312             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1313             * refers to the first result in the set. Setting both <code>start</code>
1314             * and <code>end</code> to {@link
1315             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1316             * result set.
1317             * </p>
1318             *
1319             * @param  companyId the primary key of the organization's company
1320             * @param  parentOrganizationId the primary key of the organization's parent
1321             *         organization
1322             * @param  name the name keywords (space separated, optionally
1323             *         <code>null</code>)
1324             * @param  type the type keywords (optionally <code>null</code>)
1325             * @param  street the street keywords (optionally <code>null</code>)
1326             * @param  city the city keywords (optionally <code>null</code>)
1327             * @param  zip the zipcode keywords (optionally <code>null</code>)
1328             * @param  region the region keywords (optionally <code>null</code>)
1329             * @param  country the country keywords (optionally <code>null</code>)
1330             * @param  params the finder parameters (optionally <code>null</code>). For
1331             *         more information see {@link
1332             *         com.liferay.portlet.usersadmin.util.OrganizationIndexer}.
1333             * @param  andSearch whether every field must match its keywords or just one
1334             *         field
1335             * @param  start the lower bound of the range of organizations to return
1336             * @param  end the upper bound of the range of organizations to return (not
1337             *         inclusive)
1338             * @param  sort the field and direction by which to sort (optionally
1339             *         <code>null</code>)
1340             * @return the matching organizations ordered by <code>sort</code>
1341             * @throws SystemException if a system exception occurred
1342             * @see    com.liferay.portlet.usersadmin.util.OrganizationIndexer
1343             */
1344            public Hits search(
1345                            long companyId, long parentOrganizationId, String name, String type,
1346                            String street, String city, String zip, String region,
1347                            String country, LinkedHashMap<String, Object> params,
1348                            boolean andSearch, int start, int end, Sort sort)
1349                    throws SystemException {
1350    
1351                    try {
1352                            SearchContext searchContext = new SearchContext();
1353    
1354                            searchContext.setAndSearch(andSearch);
1355    
1356                            Map<String, Serializable> attributes =
1357                                    new HashMap<String, Serializable>();
1358    
1359                            attributes.put("city", city);
1360                            attributes.put("country", country);
1361                            attributes.put("name", name);
1362                            attributes.put("params", params);
1363    
1364                            if (parentOrganizationId !=
1365                                            OrganizationConstants.ANY_PARENT_ORGANIZATION_ID) {
1366    
1367                                    attributes.put(
1368                                            "parentOrganizationId",
1369                                            String.valueOf(parentOrganizationId));
1370                            }
1371    
1372                            attributes.put("region", region);
1373                            attributes.put("street", street);
1374                            attributes.put("type", type);
1375                            attributes.put("zip", zip);
1376    
1377                            searchContext.setAttributes(attributes);
1378    
1379                            searchContext.setCompanyId(companyId);
1380                            searchContext.setEnd(end);
1381    
1382                            if (params != null) {
1383                                    String keywords = (String)params.remove("keywords");
1384    
1385                                    if (Validator.isNotNull(keywords)) {
1386                                            searchContext.setKeywords(keywords);
1387                                    }
1388                            }
1389    
1390                            QueryConfig queryConfig = new QueryConfig();
1391    
1392                            queryConfig.setHighlightEnabled(false);
1393                            queryConfig.setScoreEnabled(false);
1394    
1395                            searchContext.setQueryConfig(queryConfig);
1396    
1397                            if (sort != null) {
1398                                    searchContext.setSorts(new Sort[] {sort});
1399                            }
1400    
1401                            searchContext.setStart(start);
1402    
1403                            Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
1404                                    Organization.class);
1405    
1406                            return indexer.search(searchContext);
1407                    }
1408                    catch (Exception e) {
1409                            throw new SystemException(e);
1410                    }
1411            }
1412    
1413            /**
1414             * Returns the number of organizations that match the keywords, type,
1415             * region, and country.
1416             *
1417             * @param  companyId the primary key of the organization's company
1418             * @param  parentOrganizationId the primary key of the organization's parent
1419             *         organization
1420             * @param  keywords the keywords (space separated), which may occur in the
1421             *         organization's name, street, city, or zipcode (optionally
1422             *         <code>null</code>)
1423             * @param  type the organization's type (optionally <code>null</code>)
1424             * @param  regionId the primary key of the organization's region (optionally
1425             *         <code>null</code>)
1426             * @param  countryId the primary key of the organization's country
1427             *         (optionally <code>null</code>)
1428             * @param  params the finder parameters (optionally <code>null</code>). For
1429             *         more information see {@link
1430             *         com.liferay.portal.service.persistence.OrganizationFinder}
1431             * @return the number of matching organizations
1432             * @throws SystemException if a system exception occurred
1433             * @see    com.liferay.portal.service.persistence.OrganizationFinder
1434             */
1435            public int searchCount(
1436                            long companyId, long parentOrganizationId, String keywords,
1437                            String type, Long regionId, Long countryId,
1438                            LinkedHashMap<String, Object> params)
1439                    throws SystemException {
1440    
1441                    String parentOrganizationIdComparator = StringPool.EQUAL;
1442    
1443                    if (parentOrganizationId ==
1444                                    OrganizationConstants.ANY_PARENT_ORGANIZATION_ID) {
1445    
1446                            parentOrganizationIdComparator = StringPool.NOT_EQUAL;
1447                    }
1448    
1449                    return organizationFinder.countByKeywords(
1450                            companyId, parentOrganizationId, parentOrganizationIdComparator,
1451                            keywords, type, regionId, countryId, params);
1452            }
1453    
1454            /**
1455             * Returns the number of organizations with the type, region, and country,
1456             * and whose name, street, city, and zipcode match the keywords specified
1457             * for them.
1458             *
1459             * @param  companyId the primary key of the organization's company
1460             * @param  parentOrganizationId the primary key of the organization's parent
1461             *         organization
1462             * @param  name the name keywords (space separated, optionally
1463             *         <code>null</code>)
1464             * @param  type the organization's type (optionally <code>null</code>)
1465             * @param  street the street keywords (optionally <code>null</code>)
1466             * @param  city the city keywords (optionally <code>null</code>)
1467             * @param  zip the zipcode keywords (optionally <code>null</code>)
1468             * @param  regionId the primary key of the organization's region (optionally
1469             *         <code>null</code>)
1470             * @param  countryId the primary key of the organization's country
1471             *         (optionally <code>null</code>)
1472             * @param  params the finder parameters (optionally <code>null</code>). For
1473             *         more information see {@link
1474             *         com.liferay.portal.service.persistence.OrganizationFinder}
1475             * @param  andOperator whether every field must match its keywords, or just
1476             *         one field. For example, &quot;organizations with the name
1477             *         'Employees' and city 'Chicago'&quot; vs &quot;organizations with
1478             *         the name 'Employees' or the city 'Chicago'&quot;.
1479             * @return the number of matching organizations
1480             * @throws SystemException if a system exception occurred
1481             * @see    com.liferay.portal.service.persistence.OrganizationFinder
1482             */
1483            public int searchCount(
1484                            long companyId, long parentOrganizationId, String name, String type,
1485                            String street, String city, String zip, Long regionId,
1486                            Long countryId, LinkedHashMap<String, Object> params,
1487                            boolean andOperator)
1488                    throws SystemException {
1489    
1490                    String parentOrganizationIdComparator = StringPool.EQUAL;
1491    
1492                    if (parentOrganizationId ==
1493                                    OrganizationConstants.ANY_PARENT_ORGANIZATION_ID) {
1494    
1495                            parentOrganizationIdComparator = StringPool.NOT_EQUAL;
1496                    }
1497    
1498                    return organizationFinder.countByC_PO_N_T_S_C_Z_R_C(
1499                            companyId, parentOrganizationId, parentOrganizationIdComparator,
1500                            name, type, street, city, zip, regionId, countryId, params,
1501                            andOperator);
1502            }
1503    
1504            /**
1505             * Sets the organizations in the group, removing and adding organizations to
1506             * the group as necessary.
1507             *
1508             * @param  groupId the primary key of the group
1509             * @param  organizationIds the primary keys of the organizations
1510             * @throws PortalException if a portal exception occurred
1511             * @throws SystemException if a system exception occurred
1512             */
1513            public void setGroupOrganizations(long groupId, long[] organizationIds)
1514                    throws PortalException, SystemException {
1515    
1516                    groupPersistence.setOrganizations(groupId, organizationIds);
1517    
1518                    PermissionCacheUtil.clearCache();
1519            }
1520    
1521            /**
1522             * Removes the organizations from the group.
1523             *
1524             * @param  groupId the primary key of the group
1525             * @param  organizationIds the primary keys of the organizations
1526             * @throws PortalException if a portal exception occurred
1527             * @throws SystemException if a system exception occurred
1528             */
1529            public void unsetGroupOrganizations(long groupId, long[] organizationIds)
1530                    throws PortalException, SystemException {
1531    
1532                    groupPersistence.removeOrganizations(groupId, organizationIds);
1533    
1534                    PermissionCacheUtil.clearCache();
1535            }
1536    
1537            /**
1538             * Removes the organizations from the password policy.
1539             *
1540             * @param  passwordPolicyId the primary key of the password policy
1541             * @param  organizationIds the primary keys of the organizations
1542             * @throws SystemException if a system exception occurred
1543             */
1544            public void unsetPasswordPolicyOrganizations(
1545                            long passwordPolicyId, long[] organizationIds)
1546                    throws SystemException {
1547    
1548                    passwordPolicyRelLocalService.deletePasswordPolicyRels(
1549                            passwordPolicyId, Organization.class.getName(), organizationIds);
1550            }
1551    
1552            /**
1553             * Updates the organization's asset with the new asset categories and tag
1554             * names, removing and adding asset categories and tag names as necessary.
1555             *
1556             * @param  userId the primary key of the user
1557             * @param  organization the organization
1558             * @param  assetCategoryIds the primary keys of the asset categories
1559             * @param  assetTagNames the asset tag names
1560             * @throws PortalException if a user with the primary key could not be found
1561             * @throws SystemException if a system exception occurred
1562             */
1563            public void updateAsset(
1564                            long userId, Organization organization, long[] assetCategoryIds,
1565                            String[] assetTagNames)
1566                    throws PortalException, SystemException {
1567    
1568                    User user = userPersistence.findByPrimaryKey(userId);
1569    
1570                    Company company = companyPersistence.findByPrimaryKey(
1571                            user.getCompanyId());
1572    
1573                    Group companyGroup = company.getGroup();
1574    
1575                    assetEntryLocalService.updateEntry(
1576                            userId, companyGroup.getGroupId(), null, null,
1577                            Organization.class.getName(), organization.getOrganizationId(),
1578                            null, 0, assetCategoryIds, assetTagNames, false, null, null, null,
1579                            null, organization.getName(), StringPool.BLANK, null, null, null, 0,
1580                            0, null, false);
1581            }
1582    
1583            /**
1584             * Updates the organization.
1585             *
1586             * @param  companyId the primary key of the organization's company
1587             * @param  organizationId the primary key of the organization
1588             * @param  parentOrganizationId the primary key of organization's parent
1589             *         organization
1590             * @param  name the organization's name
1591             * @param  type the organization's type
1592             * @param  recursable whether permissions of the organization are to be
1593             *         inherited by its sub-organizations
1594             * @param  regionId the primary key of the organization's region
1595             * @param  countryId the primary key of the organization's country
1596             * @param  statusId the organization's workflow status
1597             * @param  comments the comments about the organization
1598             * @param  site whether the organization is to be associated with a main
1599             *         site
1600             * @param  serviceContext the organization's service context (optionally
1601             *         <code>null</code>). Can set asset category IDs and asset tag
1602             *         names for the organization, and merge expando bridge attributes
1603             *         for the organization.
1604             * @return the organization
1605             * @throws PortalException if an organization or parent organization with
1606             *         the primary key could not be found or if the new information was
1607             *         invalid
1608             * @throws SystemException if a system exception occurred
1609             */
1610            public Organization updateOrganization(
1611                            long companyId, long organizationId, long parentOrganizationId,
1612                            String name, String type, boolean recursable, long regionId,
1613                            long countryId, int statusId, String comments, boolean site,
1614                            ServiceContext serviceContext)
1615                    throws PortalException, SystemException {
1616    
1617                    // Organization
1618    
1619                    parentOrganizationId = getParentOrganizationId(
1620                            companyId, parentOrganizationId);
1621                    recursable = true;
1622    
1623                    validate(
1624                            companyId, organizationId, parentOrganizationId, name, type,
1625                            countryId, statusId);
1626    
1627                    Organization organization = organizationPersistence.findByPrimaryKey(
1628                            organizationId);
1629    
1630                    long oldParentOrganizationId = organization.getParentOrganizationId();
1631                    String oldName = organization.getName();
1632    
1633                    organization.setParentOrganizationId(parentOrganizationId);
1634    
1635                    String treePath = organization.buildTreePath();
1636    
1637                    organization.setTreePath(treePath);
1638    
1639                    organization.setName(name);
1640                    organization.setType(type);
1641                    organization.setRecursable(recursable);
1642                    organization.setRegionId(regionId);
1643                    organization.setCountryId(countryId);
1644                    organization.setStatusId(statusId);
1645                    organization.setComments(comments);
1646                    organization.setExpandoBridgeAttributes(serviceContext);
1647    
1648                    organizationPersistence.update(organization);
1649    
1650                    // Group
1651    
1652                    Group group = organization.getGroup();
1653    
1654                    long parentGroupId = group.getParentGroupId();
1655    
1656                    boolean organizationGroup = isOrganizationGroup(
1657                            oldParentOrganizationId, group.getParentGroupId());
1658    
1659                    if (organizationGroup) {
1660                            if (parentOrganizationId !=
1661                                            OrganizationConstants.DEFAULT_PARENT_ORGANIZATION_ID) {
1662    
1663                                    Organization parentOrganization =
1664                                            organizationPersistence.fetchByPrimaryKey(
1665                                                    parentOrganizationId);
1666    
1667                                    parentGroupId = parentOrganization.getGroupId();
1668                            }
1669                            else {
1670                                    parentGroupId = GroupConstants.DEFAULT_PARENT_GROUP_ID;
1671                            }
1672                    }
1673    
1674                    if (!oldName.equals(name) || organizationGroup) {
1675                            groupLocalService.updateGroup(
1676                                    group.getGroupId(), parentGroupId, name, group.getDescription(),
1677                                    group.getType(), group.getFriendlyURL(), group.isActive(),
1678                                    null);
1679                    }
1680    
1681                    if (group.isSite() != site) {
1682                            groupLocalService.updateSite(group.getGroupId(), site);
1683                    }
1684    
1685                    // Asset
1686    
1687                    if (serviceContext != null) {
1688                            updateAsset(
1689                                    serviceContext.getUserId(), organization,
1690                                    serviceContext.getAssetCategoryIds(),
1691                                    serviceContext.getAssetTagNames());
1692                    }
1693    
1694                    // Indexer
1695    
1696                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
1697                            Organization.class);
1698    
1699                    if (oldParentOrganizationId != parentOrganizationId) {
1700                            long[] organizationIds = getReindexOrganizationIds(organization);
1701    
1702                            indexer.reindex(organizationIds);
1703                    }
1704                    else {
1705                            indexer.reindex(organization);
1706                    }
1707    
1708                    return organization;
1709            }
1710    
1711            protected void addSuborganizations(
1712                            List<Organization> allSuborganizations,
1713                            List<Organization> organizations)
1714                    throws SystemException {
1715    
1716                    for (Organization organization : organizations) {
1717                            if (!allSuborganizations.contains(organization)) {
1718                                    allSuborganizations.add(organization);
1719    
1720                                    List<Organization> suborganizations =
1721                                            organizationPersistence.findByC_P(
1722                                                    organization.getCompanyId(),
1723                                                    organization.getOrganizationId());
1724    
1725                                    addSuborganizations(allSuborganizations, suborganizations);
1726                            }
1727                    }
1728            }
1729    
1730            protected long getParentOrganizationId(
1731                            long companyId, long parentOrganizationId)
1732                    throws SystemException {
1733    
1734                    if (parentOrganizationId !=
1735                                    OrganizationConstants.DEFAULT_PARENT_ORGANIZATION_ID) {
1736    
1737                            // Ensure parent organization exists and belongs to the proper
1738                            // company
1739    
1740                            Organization parentOrganization =
1741                                    organizationPersistence.fetchByPrimaryKey(parentOrganizationId);
1742    
1743                            if ((parentOrganization == null) ||
1744                                    (companyId != parentOrganization.getCompanyId())) {
1745    
1746                                    parentOrganizationId =
1747                                            OrganizationConstants.DEFAULT_PARENT_ORGANIZATION_ID;
1748                            }
1749                    }
1750    
1751                    return parentOrganizationId;
1752            }
1753    
1754            protected List<Organization> getParentOrganizations(
1755                            Organization organization, boolean lastOrganization)
1756                    throws PortalException, SystemException {
1757    
1758                    List<Organization> organizations = new ArrayList<Organization>();
1759    
1760                    if (!lastOrganization) {
1761                            organizations.add(organization);
1762                    }
1763    
1764                    long parentOrganizationId = organization.getParentOrganizationId();
1765    
1766                    if (parentOrganizationId ==
1767                                    OrganizationConstants.DEFAULT_PARENT_ORGANIZATION_ID) {
1768    
1769                            return organizations;
1770                    }
1771    
1772                    Organization parentOrganization =
1773                            organizationPersistence.findByPrimaryKey(parentOrganizationId);
1774    
1775                    List<Organization> parentOrganizatons = getParentOrganizations(
1776                            parentOrganization, false);
1777    
1778                    organizations.addAll(parentOrganizatons);
1779    
1780                    return organizations;
1781            }
1782    
1783            protected long[] getReindexOrganizationIds(Organization organization)
1784                    throws PortalException, SystemException {
1785    
1786                    List<Organization> organizationsTree = new ArrayList<Organization>();
1787    
1788                    organizationsTree.add(organization);
1789    
1790                    LinkedHashMap<String, Object> params =
1791                            new LinkedHashMap<String, Object>();
1792    
1793                    params.put("organizationsTree", organizationsTree);
1794    
1795                    List<Organization> organizations = search(
1796                            organization.getCompanyId(), params, QueryUtil.ALL_POS,
1797                            QueryUtil.ALL_POS);
1798    
1799                    long[] organizationIds = new long[organizations.size()];
1800    
1801                    for (int i = 0; i < organizations.size(); i++) {
1802                            Organization curOrganization = organizations.get(i);
1803    
1804                            String treePath = curOrganization.buildTreePath();
1805    
1806                            curOrganization.setTreePath(treePath.toString());
1807    
1808                            organizationPersistence.update(curOrganization);
1809    
1810                            organizationIds[i] = curOrganization.getOrganizationId();
1811                    }
1812    
1813                    if (!ArrayUtil.contains(
1814                                    organizationIds, organization.getOrganizationId())) {
1815    
1816                            organizationIds = ArrayUtil.append(
1817                                    organizationIds, organization.getOrganizationId());
1818                    }
1819    
1820                    return organizationIds;
1821            }
1822    
1823            protected boolean isOrganizationGroup(long organizationId, long groupId)
1824                    throws SystemException {
1825    
1826                    if ((organizationId ==
1827                                    OrganizationConstants.DEFAULT_PARENT_ORGANIZATION_ID) &&
1828                            (groupId == GroupConstants.DEFAULT_PARENT_GROUP_ID)) {
1829    
1830                            return true;
1831                    }
1832    
1833                    if (organizationId !=
1834                                    OrganizationConstants.DEFAULT_PARENT_ORGANIZATION_ID) {
1835    
1836                            Organization organization =
1837                                    organizationPersistence.fetchByPrimaryKey(organizationId);
1838    
1839                            if (organization.getGroupId() == groupId) {
1840                                    return true;
1841                            }
1842                    }
1843    
1844                    return false;
1845            }
1846    
1847            protected boolean isParentOrganization(
1848                            long parentOrganizationId, long organizationId)
1849                    throws PortalException, SystemException {
1850    
1851                    // Return true if parentOrganizationId is among the parent organizatons
1852                    // of organizationId
1853    
1854                    Organization parentOrganization =
1855                            organizationPersistence.findByPrimaryKey(parentOrganizationId);
1856    
1857                    List<Organization> parentOrganizations = getParentOrganizations(
1858                            organizationId);
1859    
1860                    if (parentOrganizations.contains(parentOrganization)) {
1861                            return true;
1862                    }
1863                    else {
1864                            return false;
1865                    }
1866            }
1867    
1868            protected void validate(
1869                            long companyId, long organizationId, long parentOrganizationId,
1870                            String name, String type, long countryId, int statusId)
1871                    throws PortalException, SystemException {
1872    
1873                    if (!ArrayUtil.contains(PropsValues.ORGANIZATIONS_TYPES, type)) {
1874                            throw new OrganizationTypeException(
1875                                    "Invalid organization type " + type);
1876                    }
1877    
1878                    if (parentOrganizationId ==
1879                                    OrganizationConstants.DEFAULT_PARENT_ORGANIZATION_ID) {
1880    
1881                            if (!OrganizationImpl.isRootable(type)) {
1882                                    throw new OrganizationParentException(
1883                                            "Organization of type " + type + " cannot be a root");
1884                            }
1885                    }
1886                    else {
1887                            Organization parentOrganization =
1888                                    organizationPersistence.fetchByPrimaryKey(parentOrganizationId);
1889    
1890                            if (parentOrganization == null) {
1891                                    throw new OrganizationParentException(
1892                                            "Organization " + parentOrganizationId + " doesn't exist");
1893                            }
1894    
1895                            String[] childrenTypes = OrganizationImpl.getChildrenTypes(
1896                                    parentOrganization.getType());
1897    
1898                            if (childrenTypes.length == 0) {
1899                                    throw new OrganizationParentException(
1900                                            "Organization of type " + type + " cannot have children");
1901                            }
1902    
1903                            if ((companyId != parentOrganization.getCompanyId()) ||
1904                                    (parentOrganizationId == organizationId)) {
1905    
1906                                    throw new OrganizationParentException();
1907                            }
1908    
1909                            if (!ArrayUtil.contains(childrenTypes, type)) {
1910                                    throw new OrganizationParentException(
1911                                            "Type " + type + " not allowed as child of " +
1912                                                    parentOrganization.getType());
1913                            }
1914                    }
1915    
1916                    if ((organizationId > 0) &&
1917                            (parentOrganizationId !=
1918                                    OrganizationConstants.DEFAULT_PARENT_ORGANIZATION_ID)) {
1919    
1920                            // Prevent circular organizational references
1921    
1922                            if (isParentOrganization(organizationId, parentOrganizationId)) {
1923                                    throw new OrganizationParentException();
1924                            }
1925                    }
1926    
1927                    if (Validator.isNull(name)) {
1928                            throw new OrganizationNameException();
1929                    }
1930                    else {
1931                            Organization organization = organizationPersistence.fetchByC_N(
1932                                    companyId, name);
1933    
1934                            if ((organization != null) &&
1935                                    organization.getName().equalsIgnoreCase(name)) {
1936    
1937                                    if ((organizationId <= 0) ||
1938                                            (organization.getOrganizationId() != organizationId)) {
1939    
1940                                            throw new DuplicateOrganizationException(
1941                                                    "There is another organization named " + name);
1942                                    }
1943                            }
1944                    }
1945    
1946                    boolean countryRequired = GetterUtil.getBoolean(
1947                            PropsUtil.get(
1948                                    PropsKeys.ORGANIZATIONS_COUNTRY_REQUIRED, new Filter(type)));
1949    
1950                    if (countryRequired || (countryId > 0)) {
1951                            countryPersistence.findByPrimaryKey(countryId);
1952                    }
1953    
1954                    listTypeService.validate(
1955                            statusId, ListTypeConstants.ORGANIZATION_STATUS);
1956            }
1957    
1958            protected void validate(
1959                            long companyId, long parentOrganizationId, String name, String type,
1960                            long countryId, int statusId)
1961                    throws PortalException, SystemException {
1962    
1963                    validate(
1964                            companyId, 0, parentOrganizationId, name, type, countryId,
1965                            statusId);
1966            }
1967    
1968    }