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