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