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