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