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