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